This commit is contained in:
Bryce
2025-08-09 08:40:55 -07:00
parent c8a5768aff
commit 707a8a3095
5 changed files with 31 additions and 126 deletions

View File

@@ -39,37 +39,40 @@ def imap_folders_modal():
if not imap_folders: if not imap_folders:
return jsonify({'error': 'No folders found on IMAP server'}), 400 return jsonify({'error': 'No folders found on IMAP server'}), 400
# Deduplicate folders by name to prevent creating multiple entries for the same folder # Get all existing folders in a single query
existing_folders = Folder.query.filter(
Folder.user_id == current_user.id
).all()
# Create a dictionary for quick lookup
existing_folders_dict = {folder.name: folder for folder in existing_folders}
# Process folders
unique_folders = [] unique_folders = []
seen_names = set()
for imap_folder in imap_folders: for imap_folder in imap_folders:
folder_name = imap_folder['name'] folder_name = imap_folder['name'].strip()
# Skip special folders that might not be needed # Skip special folders that might not be needed
if folder_name.lower() in ['sent', 'drafts', 'spam', 'trash']: if folder_name.lower() in ['sent', 'drafts', 'spam', 'trash']:
continue continue
# Use case-insensitive comparison for deduplication # Check if this folder already exists in the database
folder_name_lower = folder_name.lower() existing_folder = existing_folders_dict.get(folder_name)
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 # Add folder type and subscribed status if it exists
if existing_folder: if existing_folder:
imap_folder['folder_type'] = existing_folder.folder_type imap_folder['folder_type'] = existing_folder.folder_type
imap_folder['selected'] = True imap_folder['subscribed'] = True
else: imap_folder['selected'] = True
# Set default folder type else:
imap_folder['folder_type'] = 'tidy' if folder_name.lower().strip() == 'inbox' else 'destination' # Set default folder type
imap_folder['selected'] = True imap_folder['folder_type'] = 'tidy' if folder_name.lower() == 'inbox' else 'destination'
imap_folder['subscribed'] = False
imap_folder['selected'] = True
unique_folders.append(imap_folder) unique_folders.append(imap_folder)
seen_names.add(folder_name_lower)
print(unique_folders, existing_folders_dict)
# Return the folder selection modal # Return the folder selection modal
response = make_response(render_template('partials/folder_selection_modal.html', folders=unique_folders)) response = make_response(render_template('partials/folder_selection_modal.html', folders=unique_folders))
response.headers['hx-retarget'] = "#modal-holder" response.headers['hx-retarget'] = "#modal-holder"
@@ -137,7 +140,7 @@ def test_imap_connection():
# Redirect to folder selection modal after successful connection # Redirect to folder selection modal after successful connection
response = make_response('') response = make_response('')
response.headers['HX-Trigger'] = 'open-modal' response.headers['HX-Trigger'] = 'open-modal'
response.headers['HX-Location'] = '/api/imap/folders/modal' response.headers['HX-location'] = '/api/imap/folders/modal'
else: else:
print(message) print(message)
response = make_response(render_template('partials/imap_config_modal.html', response = make_response(render_template('partials/imap_config_modal.html',

View File

@@ -1,98 +0,0 @@
/* Modal transition animations using Tailwind classes */
/*
.slide-left-move {
transform: translateX(0);
opacity: 1;
transition: all 300ms ease-out;
}
.slide-left-enter-from {
transform: translateX(100%);
opacity: 0;
}
.slide-left-enter-to {
transform: translateX(0);
opacity: 1;
transition: all 300ms ease-out;
}
.slide-left-leave-from {
transform: translateX(0);
opacity: 1;
}
.slide-left-leave-to {
transform: translateX(-100%);
opacity: 0;
transition: all 300ms ease-in;
}
.slide-right-move {
transform: translateX(0);
opacity: 1;
transition: all 300ms ease-out;
}
.slide-right-enter-from {
transform: translateX(-100%);
opacity: 0;
}
.slide-right-enter-to {
transform: translateX(0);
opacity: 1;
transition: all 300ms ease-out;
}
.slide-right-leave-from {
transform: translateX(0);
opacity: 1;
}
.slide-right-leave-to {
transform: translateX(100%);
opacity: 0;
transition: all 300ms ease-in;
}
.translate-up-move {
transform: translateY(0);
opacity: 1;
transition: all 300ms ease-out;
}
.translate-up-enter-from {
transform: translateY(100%);
opacity: 0;
}
.translate-up-enter-to {
transform: translateY(0);
opacity: 1;
transition: all 300ms ease-out;
}
.translate-up-leave-from {
transform: translateY(0);
opacity: 1;
}
.translate-up-leave-to {
transform: translateY(-100%);
opacity: 0;
transition: all 300ms ease-in;
}
.step-1 .steps .step:first-child,
.step-2 .steps .step:last-child {
--tw-step-text: hsl(var(--bc));
--tw-step-primary: hsl(var(--p));
}
.step-1 .steps .step:last-child,
.step-2 .steps .step:first-child {
--tw-step-text: hsl(var(--bc));
color: hsl(var(--bc));
}
*/

View File

@@ -13,7 +13,6 @@
<script src="https://cdn.jsdelivr.net/npm/@ryangjchandler/alpine-tooltip@1.x.x/dist/cdn.min.js" defer></script> <script src="https://cdn.jsdelivr.net/npm/@ryangjchandler/alpine-tooltip@1.x.x/dist/cdn.min.js" defer></script>
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/dist/tippy.css" /> <link rel="stylesheet" href="https://unpkg.com/tippy.js@6/dist/tippy.css" />
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script> <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<link rel="stylesheet" href="/static/css/animations.css">
<style> <style>
@keyframes shake { @keyframes shake {
0%, 100% { transform: translateX(0); } 0%, 100% { transform: translateX(0); }

View File

@@ -1,4 +1,4 @@
<div id="folder-selection-modal" class="modal-box step-2 slide-left-enter-from" @click.away="$refs.modal.close()"> <div id="folder-selection-modal" class="modal-box step-2 slide-left-enter-from w-11/12 max-w-4xl" @click.away="$refs.modal.close()">
<div class="flex items-center mb-4"> <div class="flex items-center mb-4">
<div class="steps flex-1"> <div class="steps flex-1">
<span class="step">Step 1</span> <span class="step">Step 1</span>
@@ -28,10 +28,11 @@
<td> <td>
{% if folder.subscribed %} {% if folder.subscribed %}
<span class="badge badge-success">Synced</span> <span class="badge badge-success">Synced</span>
{% else %}
{% endif %} {% endif %}
</td> </td>
<td> <td>
<!-- Hidden input for folder name -->
<input type="hidden" name="folder_{{ loop.index }}" value="{{ folder.name }}">
<select class="select select-bordered select-sm" <select class="select select-bordered select-sm"
name="folder_type_{{ loop.index }}"> name="folder_type_{{ loop.index }}">
<option value="tidy" {% if folder.folder_type == 'tidy' %}selected{% endif %}>Tidy</option> <option value="tidy" {% if folder.folder_type == 'tidy' %}selected{% endif %}>Tidy</option>

View File

@@ -1,4 +1,4 @@
<div id="imap-modal" @click.away="$refs.modal.close()" class="modal-box step-1 translate-up-enter-from" x-data="{ errors: {{ 'true' if errors else 'false' }} }" x-init="$nextTick(() => { if (errors) { document.querySelector('#submit-btn').classList.add('shake'); } })" > <div id="imap-modal" @click.away="$refs.modal.close()" class="modal-box step-1 translate-up-enter-from w-11/12 max-w-4xl" x-data="{ errors: {{ 'true' if errors else 'false' }} }" x-init="$nextTick(() => { if (errors) { document.querySelector('#submit-btn').classList.add('shake'); } })" >
<div class="flex items-center mb-4"> <div class="flex items-center mb-4">
<div class="steps flex-1"> <div class="steps flex-1">
<span class="step step-primary">Step 1</span> <span class="step step-primary">Step 1</span>