Skip to content

Conversation

@Yogesh-Shivaji365
Copy link

@Yogesh-Shivaji365 Yogesh-Shivaji365 commented Nov 28, 2025

Problem Summary

When AI tagging is enabled on empty folders, the progress bar shows 0% indefinitely instead of displaying a meaningful message that the folder is empty.

Fixes : #592

Solution Implemented

Backend Changes:

  • Enhanced API to return total_images and tagged_images fields
  • Updated database queries to include detailed image counts
  • Improved error handling with specific error types

Frontend Changes:

  • Added smart loading detection with 3-second grace period
  • Implemented three clear UI states:
    • Loading: "Loading status..." with spinner
    • Empty: "No images found in this folder" with alert icon
    • Progress: Animated progress bar with image counts (5/10 images)
  • Added estimated time display for large folders
  • Enhanced Redux state with timestamp tracking

Key Benefits

  • Clear user feedback for empty folders
  • No more indefinite 0% progress
  • Better UX with image counts and ETA
  • Independent loading states per folder
  • Enhanced error handling

Testing Performed

  • - Empty folders show proper message
  • - Folders with images show progress with counts
  • - Loading states work correctly
  • - Multiple folders maintain independent states

Screenshots and Video

Images

Before After
Screenshot 2025-11-28 154116 Screenshot 2025-11-28 153410

Video

Before Video After Video
Defore.video.mp4
After.video.mp4

Summary by CodeRabbit

  • New Features

    • Redesigned Folder Management UI with per-folder cards, progress bars, loading/empty states, and per-folder delete.
    • Added image counts (total/tagged), tagging percentage, and estimated time remaining.
    • UI now tracks per-folder status timestamps for tagging updates.
  • API / Backend

    • API docs updated: face-search parameter simplified and image metadata now accepts arbitrary properties.
    • Folder status endpoints now include total_images and tagged_images and improved error/timing info.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions
Copy link
Contributor

⚠️ No issue was linked in the PR description.
Please make sure to link an issue (e.g., 'Fixes #issue_number')

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 28, 2025

Walkthrough

Adds per-folder image counts and tagging timestamps across backend and frontend, updates API schema, refactors Settings UI to show per-folder status (loading/empty/progress) and progress estimates, and extends sync service routes/schemas with timing and richer error responses.

Changes

Cohort / File(s) Summary
Sync microservice: DB / routes / schemas
sync-microservice/app/database/folders.py, sync-microservice/app/routes/folders.py, sync-microservice/app/schemas/folders.py
Added total_images and tagged_images to FolderTaggingInfo (NamedTuple and Pydantic schema). db_get_tagging_progress now returns those counts. routes add timing, separate sqlite3 vs general exception handling, and include new fields in responses.
Frontend: state & types
frontend/src/features/folderSlice.ts, frontend/src/types/FolderStatus.ts
Added total_images and tagged_images to FolderTaggingInfo. Introduced folderStatusTimestamps map in state, updated setTaggingStatus to record per-folder timestamps and to reset the map when clearing status.
Frontend: Settings UI (Folder management)
frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx
Refactored per-folder rendering into card layout; added helpers calculateEstimatedTime and isStatusLoading; added loading/empty/progress UI states, progress bar, per-folder delete button and related icon imports.
Docs: OpenAPI
docs/backend/backend_python/openapi.json
Replaced allOf wrapper with direct $ref for input_type parameter on /face-clusters/face-search; removed parameter title. Allowed additionalProperties: true on ImageInCluster.metadata.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Areas needing closer review:
    • frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx — verify status computation, loading/empty detection, estimate calculation, and progress bar visual logic.
    • frontend/src/features/folderSlice.ts — confirm timestamp map updates only when intended and that resets are correct.
    • sync-microservice/app/routes/folders.py — validate error handling branches, response shaping, and timing/logging side-effects.

Possibly related PRs

Suggested labels

UI

Suggested reviewers

  • rahulharpal1603

Poem

🐰 I hopped through folders, counted each sight,
Stamped times when tagging flickered to light.
Progress bars shimmer, empty nests say “none”,
Counts and timestamps stored — tidy and done. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing AI tagging status display for empty folders, which is the core issue addressed across backend and frontend modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added backend bug Something isn't working frontend labels Nov 28, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (8)
sync-microservice/app/routes/folders.py (3)

50-50: Use logger instead of print for consistent logging.

The codebase uses a configured logger (as seen in sync-microservice/app/database/folders.py). Replace print with structured logging for consistency and better log management.

-        print(f"Tagging status API: {len(folder_info_list)} folders in {round((time.time() - start_time)*1000)}ms")
+        logger.info(f"Tagging status API: {len(folder_info_list)} folders in {round((time.time() - start_time)*1000)}ms")

You'll also need to import and initialize the logger:

from app.logging.setup_logging import get_sync_logger
logger = get_sync_logger(__name__)

54-61: Unused exception variable e — consider logging the error details.

The captured exception e is not used, which loses diagnostic information. Log the actual error for debugging while returning a user-friendly message.

     except sqlite3.Error as e:
-        
+        logger.error(f"Database error in tagging status: {e}")
         return FolderTaggingStatusErrorResponse(
             status="error",
             message="Database connection issue - please try again",
             data=[],
             total_folders=0
         )

62-69: Log the exception details for the generic error handler as well.

The exception variable e is unused here too. Logging helps with debugging unexpected errors.

     except Exception as e:
-        
+        logger.error(f"Unexpected error in tagging status: {e}")
         return FolderTaggingStatusErrorResponse(
             status="error",
             message="Service temporarily unavailable",
             data=[],
             total_folders=0
         )
sync-microservice/app/database/folders.py (1)

110-118: Fix inconsistent indentation.

The indentation for total_images and tagged_images is inconsistent with the other fields.

             folder_info_list.append(
                 FolderTaggingInfo(
                     folder_id=folder_id,
                     folder_path=folder_path,
-                     total_images=total_images, 
-                tagged_images=tagged_images, 
+                    total_images=total_images,
+                    tagged_images=tagged_images,
                     tagging_percentage=round(tagging_percentage, 2),
                 )
             )
frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx (4)

35-51: Hardcoded 2 seconds per image may be inaccurate.

The estimatedSeconds = remaining * 2 assumes a fixed 2 seconds per image. Actual tagging time varies by image complexity, model size, and hardware. Consider:

  1. Making this configurable
  2. Calculating based on actual elapsed time and progress
  3. Documenting this as a rough estimate

For now, this is acceptable as a simple heuristic, but consider extracting the magic number to a named constant.

+const ESTIMATED_SECONDS_PER_IMAGE = 2;
+
 const calculateEstimatedTime = (status: FolderTaggingInfo) => {
   if (!status || status.total_images === 0 || status.tagging_percentage >= 100) 
     return '';
   
   const processed = status.tagged_images;
   const total = status.total_images;
   const remaining = total - processed;
   
-  const estimatedSeconds = Math.round(remaining * 2);
+  const estimatedSeconds = Math.round(remaining * ESTIMATED_SECONDS_PER_IMAGE);

54-70: Extract magic numbers to named constants for clarity.

The 3000 (3 seconds) grace period is a magic number. Extract it to improve readability and maintainability.

+const LOADING_GRACE_PERIOD_MS = 3000;
+
 const isStatusLoading = (folderId: string, folderHasAITagging: boolean) => {
   if (!folderHasAITagging) return false;

   const status = taggingStatus[folderId];
   if (!status) return true; 

   const timestamp = folderStatusTimestamps[folderId];
   const timeSinceUpdate = timestamp ? Date.now() - timestamp : Infinity;

-  if (status.total_images === 0 && timeSinceUpdate < 3000) {
+  if (status.total_images === 0 && timeSinceUpdate < LOADING_GRACE_PERIOD_MS) {
     return true;
   }

   return false;
 };

147-181: Inconsistent indentation in JSX block.

The JSX block starting at line 147 has inconsistent indentation compared to the rest of the component. Consider aligning it with the surrounding code for better readability.


164-168: Extract threshold constant for ETA visibility.

The 50 images threshold for showing ETA is a magic number.

+const MIN_IMAGES_FOR_ETA_DISPLAY = 50;
+
 // In the JSX:
-{status.total_images > 50 && status.tagging_percentage < 100 && (
+{status.total_images > MIN_IMAGES_FOR_ETA_DISPLAY && status.tagging_percentage < 100 && (
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c37d8df and 22ad8ce.

📒 Files selected for processing (7)
  • docs/backend/backend_python/openapi.json (2 hunks)
  • frontend/src/features/folderSlice.ts (2 hunks)
  • frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx (3 hunks)
  • frontend/src/types/FolderStatus.ts (1 hunks)
  • sync-microservice/app/database/folders.py (2 hunks)
  • sync-microservice/app/routes/folders.py (2 hunks)
  • sync-microservice/app/schemas/folders.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx (4)
frontend/src/app/store.ts (1)
  • RootState (22-22)
frontend/src/types/FolderStatus.ts (1)
  • FolderTaggingInfo (1-7)
sync-microservice/app/database/folders.py (1)
  • FolderTaggingInfo (14-19)
sync-microservice/app/schemas/folders.py (1)
  • FolderTaggingInfo (5-15)
sync-microservice/app/routes/folders.py (3)
sync-microservice/app/database/folders.py (2)
  • db_get_tagging_progress (75-123)
  • FolderTaggingInfo (14-19)
frontend/src/types/FolderStatus.ts (1)
  • FolderTaggingInfo (1-7)
sync-microservice/app/schemas/folders.py (3)
  • FolderTaggingInfo (5-15)
  • FolderTaggingStatusSuccessResponse (18-23)
  • FolderTaggingStatusErrorResponse (26-36)
🔇 Additional comments (10)
sync-microservice/app/routes/folders.py (1)

31-40: LGTM!

The new total_images and tagged_images fields are correctly passed from the database layer to the API response schema.

docs/backend/backend_python/openapi.json (2)

1119-1123: Verify OpenAPI spec was auto-generated.

These schema changes (simplified $ref for input_type, removed title) appear to be from OpenAPI spec regeneration rather than manual edits. Confirm this file is auto-generated and not manually maintained to avoid merge conflicts.


2202-2203: additionalProperties: true allows arbitrary metadata fields.

This change permits any additional properties in the metadata object for ImageInCluster. This provides flexibility but reduces type safety. Verify this is intentional.

frontend/src/types/FolderStatus.ts (1)

1-7: LGTM!

The FolderTaggingInfo interface correctly mirrors the backend schema with the new total_images and tagged_images fields, maintaining type consistency across the stack.

sync-microservice/app/database/folders.py (1)

14-19: LGTM!

The FolderTaggingInfo NamedTuple now correctly includes total_images and tagged_images fields, enabling the API layer to pass these values through to the frontend.

sync-microservice/app/schemas/folders.py (1)

5-15: LGTM!

The schema correctly adds total_images and tagged_images with appropriate ge=0 validation constraints, ensuring non-negative values from the API.

frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx (1)

80-186: Overall implementation achieves PR objectives well.

The refactored UI correctly handles three distinct states: loading (with spinner), empty folder (with alert icon), and progress display (with counts and ETA). The 3-second grace period effectively prevents premature "empty folder" display during initial load.

frontend/src/features/folderSlice.ts (3)

8-8: LGTM: Clean state extension for timestamp tracking.

The folderStatusTimestamps field correctly tracks per-folder status change times, and the initialization is appropriate.

Also applies to: 15-15


96-100: LGTM: Complete cleanup of tagging-related state.

The clearTaggingStatus reducer correctly resets all tagging-related state, including the new folderStatusTimestamps field.


83-87: I attempted to verify the type definitions but encountered a repository access issue. Let me provide the rewritten review comment based on the information available:


Verify that total_images and tagged_images are required (non-optional) fields in FolderTaggingInfo.

The change detection logic compares these fields without null/undefined checks. If they are optional fields, the comparison could behave unexpectedly (e.g., undefined !== 0 evaluates to true, causing unnecessary timestamp updates). Confirm the type definition in frontend/src/types/FolderStatus.ts or wherever FolderTaggingInfo is defined to ensure total_images and tagged_images are required properties.

- Show 'No images found' message for empty folders instead of 0% progress
- Add image counts and estimated time for better UX
- Implement smart loading states with 3-second grace period
- Enhanced progress display with animations
@Yogesh-Shivaji365 Yogesh-Shivaji365 force-pushed the fix/empty-folder-ai-tagging-status branch from 22ad8ce to 9083138 Compare December 3, 2025 05:52
@Yogesh-Shivaji365
Copy link
Author

is my PR ready for review?

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
frontend/src/features/folderSlice.ts (1)

77-103: Tagging status update & timestamp cleanup logic looks solid

The setTaggingStatus reducer correctly:

  • Rebuilds taggingStatus from the payload.
  • Uses a single now = Date.now() for all updates to keep timestamps comparable.
  • Only updates folderStatusTimestamps when total_images or tagged_images actually change.
  • Cleans up timestamps for folders no longer present in the payload, preventing stale entries.
  • Updates lastUpdatedAt in sync with these changes.

clearTaggingStatus also resets both taggingStatus and folderStatusTimestamps, which keeps the slice state coherent.

If you ever want to be extra defensive, you could iterate Object.keys(state.folderStatusTimestamps) instead of for ... in, but with a plain object from Redux this is more of a style preference than a necessity.

Also applies to: 105-110

sync-microservice/app/routes/folders.py (2)

3-4: Success-path timing and payload shaping are correct; prefer structured logging to print

The success path looks good:

  • start_time = time.time() and the elapsed time calculation are correct in milliseconds.
  • FolderTaggingInfo now includes total_images and tagged_images, which aligns with the frontend’s needs.
  • The unified response object is clean and explicit.

Instead of print(...), consider using your FastAPI app/logger (e.g., logger.info(...)) so logs are captured by your logging stack and can be filtered/aggregated in production.

Also applies to: 27-28, 31-40, 43-52


54-61: Error handling is user-friendly; consider logging exceptions before returning

Both the sqlite3.Error and generic Exception handlers return sensible, non-leaky error messages with an empty data list and total_folders=0, which is good for clients.

Right now, the caught exceptions (e) are unused. It would be helpful to log them (e.g., logger.exception("Failed to fetch folder tagging status")) so operational issues can be diagnosed without exposing details to users.

Also applies to: 62-69

frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx (2)

30-32: Helper logic for ETA and loading state is aligned with requirements

  • calculateEstimatedTime correctly skips ETA when there are no images or the folder is complete, and produces a simple seconds/minutes estimate based on remaining images.
  • isStatusLoading implements the intended behavior:
    • Returns loading when AI tagging is enabled but no status has arrived yet.
    • Applies a 3-second grace period when total_images === 0 before declaring the folder “empty.”
    • Treats disabled AI tagging as not loading.

To make this a bit more robust against unexpected backend values, you could defensively clamp remaining to a minimum of 0 before computing estimatedSeconds, e.g.:

-    const remaining = total - processed;
+    const remaining = Math.max(total - processed, 0);

This avoids negative ETAs if tagged_images ever exceeds total_images due to upstream issues.

Also applies to: 35-51, 54-70


82-90: Folder row rendering cleanly separates loading, empty, and progress states

The per-folder rendering looks good and matches the described UX:

  • Uses key={folder.folder_id}, which is the right stable key.
  • Computes status, loading, hasImages, isEmpty, and isComplete per folder, and only shows the status block when folder.AI_Tagging is enabled.
  • Conditional block correctly prioritizes:
    • Loading spinner (“Loading status...”) when loading is true.
    • Empty-state message when isEmpty is true.
    • Progress details when hasImages is true, including:
      • Percentage with a check icon and green styling when complete.
      • Tagged/total image counts.
      • ETA chip for large folders using calculateEstimatedTime.
      • A progress bar that visually distinguishes complete vs in-progress states.

Two very small cleanups you might consider later:

  • Drop the unused index parameter in folders.map((folder, index) => ...) since the key now uses folder.folder_id.
  • If TypeScript ever complains about status possibly being undefined inside the hasImages branch, an early if (!status) return null; guard before that branch would make the type relationship explicit.

Functionally, the status UI and per-folder state handling look correct.

Also applies to: 92-185

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22ad8ce and 9083138.

📒 Files selected for processing (7)
  • docs/backend/backend_python/openapi.json (2 hunks)
  • frontend/src/features/folderSlice.ts (2 hunks)
  • frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx (3 hunks)
  • frontend/src/types/FolderStatus.ts (1 hunks)
  • sync-microservice/app/database/folders.py (2 hunks)
  • sync-microservice/app/routes/folders.py (2 hunks)
  • sync-microservice/app/schemas/folders.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • frontend/src/types/FolderStatus.ts
  • sync-microservice/app/database/folders.py
  • sync-microservice/app/schemas/folders.py
🔇 Additional comments (3)
docs/backend/backend_python/openapi.json (2)

1119-1125: Redundant parameter descriptions in input_type schema.

The input_type parameter now has duplicate descriptions: one at line 1121 (schema level) and one at line 1124 (parameter level). In OpenAPI 3.1.0, this is valid but creates redundancy. Consider removing the description from the schema to keep it solely at the parameter level, or remove the duplicate at line 1124.

Additionally, verify that this manual change to the OpenAPI spec is intentional. If this file is auto-generated from your FastAPI backend code, manual edits may be overwritten on the next generation. Consider regenerating the spec from the backend source to ensure consistency.


2199-2210: Explicit additionalProperties allowance in ImageInCluster metadata.

Line 2202 now explicitly allows additional properties on the metadata object ("additionalProperties": true). This aligns with the PR's goal of flexible metadata handling but loosens the schema validation. Ensure the backend code supports this flexibility and that consumers (frontend, integrations) are aware that metadata may contain unexpected fields.

Verify that the backend endpoints returning ImageInCluster actually populate dynamic/flexible metadata fields and that this schema change reflects the implemented behavior.

frontend/src/features/folderSlice.ts (1)

5-16: State shape for per-folder timestamps is consistent

Adding folderStatusTimestamps to FolderState and initializing it in initialState is correct and keeps the timestamp map co-located with taggingStatus. No issues here.

@Yogesh-Shivaji365
Copy link
Author

@rahulharpal1603 this PR is ready for your review.

@Yogesh-Shivaji365
Copy link
Author

what i do now?

@rahulharpal1603
Copy link
Contributor

@Yogesh-Shivaji365
This is already being addressed by the PR #604

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend bug Something isn't working frontend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: AI Tagging Shows 0% Progress for Empty Folders Instead of "No Images" Message

2 participants