animations

This commit is contained in:
2025-08-09 07:55:42 -07:00
parent 608cd7357c
commit c8a5768aff
10 changed files with 423 additions and 18 deletions

View File

@@ -22,6 +22,65 @@ def imap_config_modal():
response.headers['HX-Trigger'] = 'open-modal'
return response
@imap_bp.route('/api/imap/folders/modal', methods=['GET'])
@login_required
def imap_folders_modal():
"""Return the folder selection modal after successful IMAP connection."""
try:
if not current_user.imap_config:
return jsonify({'error': 'No IMAP configuration found. Please configure IMAP first.'}), 400
# Test connection first
imap_service = IMAPService(current_user)
# Get folders from IMAP server
imap_folders = imap_service.get_folders()
if not imap_folders:
return jsonify({'error': 'No folders found on IMAP server'}), 400
# Deduplicate folders by name to prevent creating multiple entries for the same folder
unique_folders = []
seen_names = set()
for imap_folder in imap_folders:
folder_name = imap_folder['name']
# Skip special folders that might not be needed
if folder_name.lower() in ['sent', 'drafts', 'spam', 'trash']:
continue
# Use case-insensitive comparison for deduplication
folder_name_lower = folder_name.lower()
if folder_name_lower not in seen_names:
# Check if this folder already exists in the database
existing_folder = Folder.query.filter_by(
user_id=current_user.id,
name=folder_name
).first()
# Add folder type if it exists
if existing_folder:
imap_folder['folder_type'] = existing_folder.folder_type
imap_folder['selected'] = True
else:
# Set default folder type
imap_folder['folder_type'] = 'tidy' if folder_name.lower().strip() == 'inbox' else 'destination'
imap_folder['selected'] = True
unique_folders.append(imap_folder)
seen_names.add(folder_name_lower)
# Return the folder selection modal
response = make_response(render_template('partials/folder_selection_modal.html', folders=unique_folders))
response.headers['hx-retarget'] = "#modal-holder"
response.headers['HX-Trigger'] = 'open-modal'
return response
except Exception as e:
logging.exception("Error getting IMAP folders modal: %s", e)
print(e)
return jsonify({'error': 'An unexpected error occurred while fetching folders'}), 500
@imap_bp.route('/api/imap/test', methods=['POST'])
@login_required
def test_imap_connection():
@@ -75,10 +134,10 @@ def test_imap_connection():
current_user.imap_config = test_config
db.session.commit()
response = make_response(render_template('partials/imap_config_modal.html',
success=True, message=message))
response.headers['HX-Retarget'] = '#imap-modal'
response.headers['HX-Reswap'] = 'outerHTML'
# Redirect to folder selection modal after successful connection
response = make_response('')
response.headers['HX-Trigger'] = 'open-modal'
response.headers['HX-Location'] = '/api/imap/folders/modal'
else:
print(message)
response = make_response(render_template('partials/imap_config_modal.html',
@@ -97,10 +156,168 @@ def test_imap_connection():
response.headers['HX-Reswap'] = 'outerHTML'
return response
@imap_bp.route('/api/imap/folders', methods=['GET'])
@login_required
def get_imap_folders():
"""Get folders from IMAP server without creating database records."""
try:
if not current_user.imap_config:
return jsonify({'error': 'No IMAP configuration found. Please configure IMAP first.'}), 400
# Test connection first
imap_service = IMAPService(current_user)
# Get folders from IMAP server
imap_folders = imap_service.get_folders()
if not imap_folders:
return jsonify({'error': 'No folders found on IMAP server'}), 400
# Deduplicate folders by name to prevent creating multiple entries for the same folder
unique_folders = []
seen_names = set()
for imap_folder in imap_folders:
folder_name = imap_folder['name']
# Skip special folders that might not be needed
if folder_name.lower() in ['sent', 'drafts', 'spam', 'trash']:
continue
# Use case-insensitive comparison for deduplication
folder_name_lower = folder_name.lower()
if folder_name_lower not in seen_names:
unique_folders.append(imap_folder)
seen_names.add(folder_name_lower)
return jsonify({'folders': unique_folders})
except Exception as e:
logging.exception("Error getting IMAP folders: %s", e)
print(e)
return jsonify({'error': 'An unexpected error occurred while fetching folders'}), 500
@imap_bp.route('/api/imap/sync-selected', methods=['POST'])
@login_required
def sync_selected_folders():
"""Sync only the selected folders from IMAP server with processed email tracking."""
try:
if not current_user.imap_config:
return jsonify({'error': 'No IMAP configuration found. Please configure IMAP first.'}), 400
# Get selected folder names and types from form data
selected_folders = {}
for key, value in request.form.items():
if key.startswith('folder_'):
folder_name = value
# Check if there's a corresponding folder type
type_key = f'folder_type_{key.split("_")[1]}'
folder_type = request.form.get(type_key, 'destination') # Default to 'destination'
selected_folders[folder_name] = folder_type
if not selected_folders:
return jsonify({'error': 'No folders selected'}), 400
# Test connection first
imap_service = IMAPService(current_user)
# Get folders from IMAP server
imap_folders = imap_service.get_folders()
if not imap_folders:
return jsonify({'error': 'No folders found on IMAP server'}), 400
# Deduplicate folders by name to prevent creating multiple entries for the same folder
unique_folders = []
seen_names = set()
for imap_folder in imap_folders:
folder_name = imap_folder['name']
# Skip special folders that might not be needed
if folder_name.lower() in ['sent', 'drafts', 'spam', 'trash']:
continue
# Only include folders that were selected by the user
if folder_name in selected_folders:
# Use case-insensitive comparison for deduplication
folder_name_lower = folder_name.lower()
if folder_name_lower not in seen_names:
# Add the selected folder type
imap_folder['selected_type'] = selected_folders[folder_name]
unique_folders.append(imap_folder)
seen_names.add(folder_name_lower)
# Process each selected unique folder
synced_count = 0
processed_emails_service = ProcessedEmailsService(current_user)
# Create a list of folders to process
folders_to_process = []
for imap_folder in unique_folders:
folder_name = imap_folder['name'].strip()
folder_type = imap_folder.get('selected_type', 'destination') # Get the selected type
# Handle nested folder names (convert slashes to underscores or keep as-is)
# According to requirements, nested folders should be created with slashes in the name
display_name = folder_name
# Check if folder already exists
existing_folder = Folder.query.filter_by(
user_id=current_user.id,
name=display_name
).first()
if not existing_folder:
# Create new folder with the selected type
new_folder = Folder(
user_id=current_user.id,
name=display_name,
rule_text=f"Auto-synced from IMAP folder: {folder_name}",
priority=0, # Default priority
folder_type=folder_type
)
db.session.add(new_folder)
synced_count += 1
folders_to_process.append(new_folder)
else:
# Update existing folder with the selected type and email counts
existing_folder.folder_type = folder_type
# Get all email UIDs in this folder
email_uids = imap_service.get_folder_email_uids(folder_name)
# Sync with processed emails service
new_emails_count = processed_emails_service.sync_folder_emails(display_name, email_uids)
print("NEW", new_emails_count)
# Update counts
pending_count = processed_emails_service.get_pending_count(display_name)
existing_folder.pending_count = pending_count
existing_folder.total_count = len(email_uids)
# Get the most recent emails for this folder
recent_emails = imap_service.get_recent_emails(folder_name, 3)
existing_folder.recent_emails = recent_emails
folders_to_process.append(existing_folder)
db.session.commit()
# Just trigger the folder list update and close the modal
response = make_response('')
response.headers['HX-Trigger'] = 'close-modal, folder-list-invalidated'
return response
except Exception as e:
logging.exception("Error syncing selected IMAP folders: %s", e)
print(e)
db.session.rollback()
return jsonify({'error': 'An unexpected error occurred'}), 500
@imap_bp.route('/api/imap/sync', methods=['POST'])
@login_required
def sync_imap_folders():
"""Sync folders from IMAP server with processed email tracking."""
"""Create and sync folders from IMAP server with processed email tracking."""
try:
if not current_user.imap_config:
return jsonify({'error': 'No IMAP configuration found. Please configure IMAP first.'}), 400