feat: Add browse folder API and enhance folder selection in Scan component

This commit introduces a new API endpoint for browsing folders, utilizing tkinter for a native folder picker dialog. The Scan component has been updated to integrate this functionality, allowing users to select folders more easily. If the native picker is unavailable, a browser-based fallback is implemented, ensuring a seamless user experience. Additionally, the input field for batch size has been modified to restrict input to numeric values only, improving data validation. Documentation has been updated to reflect these changes.
This commit is contained in:
tanyar09
2025-11-10 14:12:51 -05:00
parent ac07932e14
commit 8d668a9658
4 changed files with 178 additions and 114 deletions
+69
View File
@@ -313,6 +313,75 @@ async def upload_photos(
}
@router.post("/browse-folder")
def browse_folder() -> dict:
"""Open native folder picker dialog and return selected folder path.
Uses tkinter to show a native OS folder picker dialog.
Returns the full absolute path of the selected folder.
Returns:
dict with 'path' (str) and 'success' (bool) keys
"""
import os
import sys
try:
import tkinter as tk
from tkinter import filedialog
except ImportError:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="tkinter is not available. Cannot show folder picker.",
)
try:
# Create root window (hidden)
root = tk.Tk()
root.withdraw() # Hide main window
root.attributes('-topmost', True) # Bring to front
# Show folder picker dialog
folder_path = filedialog.askdirectory(
title="Select folder to scan",
mustexist=True
)
# Clean up
root.destroy()
if folder_path:
# Normalize path to absolute
abs_path = os.path.abspath(folder_path)
return {
"path": abs_path,
"success": True,
"message": f"Selected folder: {abs_path}"
}
else:
return {
"path": "",
"success": False,
"message": "No folder selected"
}
except Exception as e:
# Handle errors gracefully
error_msg = str(e)
# Check for common issues (display/headless server)
if "display" in error_msg.lower() or "DISPLAY" not in os.environ:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="No display available. Cannot show folder picker. "
"If running on a remote server, ensure X11 forwarding is enabled.",
)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Error showing folder picker: {error_msg}",
)
@router.get("/{photo_id}", response_model=PhotoResponse)
def get_photo(photo_id: int, db: Session = Depends(get_db)) -> PhotoResponse:
"""Get photo by ID."""