From d021f045aefd5c1ee5a783c884e1570fb14a9461 Mon Sep 17 00:00:00 2001 From: Bryce Date: Wed, 6 Aug 2025 21:30:33 -0700 Subject: [PATCH] progress --- app/routes.py | 98 +++++-- app/templates/index.html | 21 +- app/templates/partials/folder_card_base.html | 18 +- .../partials/folder_card_destination.html | 46 +--- .../partials/folder_card_ignore.html | 6 + app/templates/partials/folder_card_tidy.html | 102 ++------ .../partials/folder_type_selection_modal.html | 52 ++++ app/templates/partials/folders_list.html | 3 + .../partials/hidden_folders_section.html | 27 ++ app/templates/partials/imap_config_modal.html | 4 +- docs/design/data-model.md | 29 ++- docs/design/folder-types-ui.md | 242 +++--------------- .../folder-types-ignore-implementation.md | 143 +++++++++++ tests/test_routes.py | 10 +- 14 files changed, 426 insertions(+), 375 deletions(-) create mode 100644 app/templates/partials/folder_card_ignore.html create mode 100644 app/templates/partials/folder_type_selection_modal.html create mode 100644 app/templates/partials/hidden_folders_section.html create mode 100644 docs/plans/folder-types-ignore-implementation.md diff --git a/app/routes.py b/app/routes.py index 085d77b..81b07de 100644 --- a/app/routes.py +++ b/app/routes.py @@ -16,7 +16,8 @@ def index(): folders = Folder.query.filter_by(user_id=current_user.id).all() return render_template('index.html', - folders=folders) + folders=folders, + show_hidden=False) @main.route('/api/folders/new', methods=['GET']) @login_required @@ -62,12 +63,17 @@ def add_folder(): # Default to 'destination' type for manually created folders folder_type = 'tidy' if name.strip().lower() == 'inbox' else 'destination' + # If folder_type is 'ignore', reset emails_count to 0 + if folder_type == 'ignore': + emails_count = 0 + folder = Folder( user_id=current_user.id, name=name.strip(), rule_text=rule_text.strip(), priority=int(priority) if priority else 0, - folder_type=folder_type + folder_type=folder_type, + emails_count=0 if folder_type == 'ignore' else None ) db.session.add(folder) @@ -78,7 +84,7 @@ def add_folder(): response = make_response(render_template('partials/folders_list.html', folders=folders)) response.headers['HX-Trigger'] = 'close-modal' - response.headers["HX-Target"] = 'folder-list' + response.headers["HX-Target"] = '#folders-list' response.status_code = 201 return response @@ -126,9 +132,9 @@ def delete_folder(folder_id): # Return both sections return render_template('partials/folders_list.html', folders=folders) -@main.route('/api/folders//toggle', methods=['PUT']) +@main.route('/api/folders//type', methods=['PUT']) @login_required -def toggle_folder_organize(folder_id): +def update_folder_type(folder_id): try: # Find the folder by ID and ensure it belongs to the current user folder = Folder.query.filter_by(id=folder_id, user_id=current_user.id).first() @@ -136,21 +142,30 @@ def toggle_folder_organize(folder_id): if not folder: return jsonify({'error': 'Folder not found'}), 404 - # Toggle the organize_enabled flag - folder.organize_enabled = not folder.organize_enabled + # Get the new folder type from form data + new_folder_type = request.form.get('folder_type') + + # Validate the folder type + if new_folder_type not in ['tidy', 'destination', 'ignore']: + return jsonify({'error': 'Invalid folder type'}), 400 + + # If changing to 'ignore', reset the emails_count to 0 + if new_folder_type == 'ignore' and folder.folder_type != 'ignore': + folder.emails_count = 0 + + # Update the folder type + folder.folder_type = new_folder_type db.session.commit() - # Return just the updated folder card HTML for this specific folder - # Use the appropriate template based on folder type - if folder.folder_type == 'tidy': - return render_template('partials/folder_card_tidy.html', folder=folder) - else: - return render_template('partials/folder_card_destination.html', folder=folder) + # Get updated list of folders for the current user + folders = Folder.query.filter_by(user_id=current_user.id).all() + + return render_template('partials/folders_list.html', folders=folders) except Exception as e: # Print unhandled exceptions to the console as required - logging.exception("Error toggling folder organize flag: %s", e) + logging.exception("Error updating folder type: %s", e) db.session.rollback() return jsonify({'error': 'An unexpected error occurred'}), 500 @@ -219,11 +234,13 @@ def update_folder(folder_id): folder.rule_text = rule_text.strip() folder.priority = int(priority) if priority else 0 - # Update folder type if the name changed to/from 'inbox' - if name.strip().lower() == 'inbox' and folder.folder_type != 'tidy': - folder.folder_type = 'tidy' - elif name.strip().lower() != 'inbox' and folder.folder_type != 'destination': - folder.folder_type = 'destination' + # Check if folder type is being changed to 'ignore' + old_folder_type = folder.folder_type + folder.folder_type = 'tidy' if name.strip().lower() == 'inbox' else 'destination' + + # If changing to 'ignore', reset emails_count to 0 + if folder.folder_type == 'ignore' and old_folder_type != 'ignore': + folder.emails_count = 0 db.session.commit() @@ -373,6 +390,9 @@ def sync_imap_folders(): 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() @@ -400,6 +420,7 @@ def sync_imap_folders(): ) db.session.add(new_folder) synced_count += 1 + folders_to_process.append(new_folder) else: # Update existing folder with email counts and recent emails # Get all email UIDs in this folder @@ -417,13 +438,22 @@ def sync_imap_folders(): # 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() - # Get updated list of folders - folders = Folder.query.filter_by(user_id=current_user.id).all() - - return render_template('partials/folders_list.html', folders=folders) + # Check if we should show the folder type selection modal + # Only show the modal if there are new folders to configure + if synced_count > 0: + # Return the folder type selection modal + response = make_response(render_template('partials/folder_type_selection_modal.html', folders=folders_to_process)) + response.headers['HX-Trigger'] = 'open-modal' + return response + else: + # Just return the updated folders list + folders = Folder.query.filter_by(user_id=current_user.id).all() + return render_template('partials/folders_list.html', folders=folders) except Exception as e: logging.exception("Error syncing IMAP folders: %s", e) @@ -438,6 +468,7 @@ def get_folders(): # Get filter parameter from query string filter_type = request.args.get('filter', 'all') folder_type = request.args.get('type', None) + show_hidden = request.args.get('show_hidden', 'off').lower() == 'on' # Get folders for the current authenticated user if folder_type: @@ -454,15 +485,26 @@ def get_folders(): folders = Folder.query.filter_by(user_id=current_user.id).all() if folder_type == 'tidy': - response = make_response(render_template('partials/folders_to_tidy_section.html', folders=folders)) - response["HX-Retarget"] = "#folders-to-tidy" + response = make_response(render_template('partials/folders_to_tidy_section.html', folders=folders, show_hidden=show_hidden)) + response.headers["HX-Retarget"] = "#folders-to-tidy" return response elif folder_type == 'destination': - response = make_response(render_template('partials/destination_folders_section.html', folders=folders)) - response["HX-Retarget"] = "#destination-folders" + response = make_response(render_template('partials/destination_folders_section.html', folders=folders, show_hidden=show_hidden)) + response.headers["HX-Retarget"] = "#destination-folders" + return response + elif folder_type == 'ignore': + response = make_response(render_template('partials/hidden_folders_section.html', folders=folders, show_hidden=show_hidden)) + response.headers["HX-Retarget"] = "#hidden-folders" + + # Show or hide the hidden folders section based on the show_hidden parameter + if show_hidden: + response.headers['HX-Trigger'] = 'show-hidden' + else: + response.headers['HX-Trigger'] = 'hide-hidden' + return response else: - return render_template('partials/folders_list.html', folders=folders) + return render_template('partials/folders_list.html', folders=folders, show_hidden=show_hidden) # Processed Emails API Endpoints diff --git a/app/templates/index.html b/app/templates/index.html index 77251cd..69c69a0 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -54,7 +54,8 @@ {% if not current_user.imap_config %} - {% include "partials/welcome_section.html" %} + {% include "partials/welcome_section.html" %} +
{% else %} @@ -81,9 +82,21 @@
-
- - +
+
+ + +
+
+ + +
diff --git a/app/templates/partials/folder_card_base.html b/app/templates/partials/folder_card_base.html index cf4964a..aade0cd 100644 --- a/app/templates/partials/folder_card_base.html +++ b/app/templates/partials/folder_card_base.html @@ -44,6 +44,22 @@

{{ folder.rule_text }}

- {% block additional_content %}{% endblock %} +
+
+ Type: + +
+
\ No newline at end of file diff --git a/app/templates/partials/folder_card_destination.html b/app/templates/partials/folder_card_destination.html index 2a86ac3..b9eb1aa 100644 --- a/app/templates/partials/folder_card_destination.html +++ b/app/templates/partials/folder_card_destination.html @@ -1,41 +1,5 @@ -
- -
-
-

{{ folder.name }}

-
- - -
-
- - -
-
- {{ folder.emails_count }} emails -
-
- -
-

{{ folder.rule_text }}

-
-
-
\ No newline at end of file +{% extends "partials/folder_card_base.html" %} + +{% block badges %} + {{ folder.emails_count }} emails +{% endblock %} \ No newline at end of file diff --git a/app/templates/partials/folder_card_ignore.html b/app/templates/partials/folder_card_ignore.html new file mode 100644 index 0000000..133b7aa --- /dev/null +++ b/app/templates/partials/folder_card_ignore.html @@ -0,0 +1,6 @@ +{% extends "partials/folder_card_base.html" %} + +{% block badges %} + Ignored + {{ folder.emails_count }} emails +{% endblock %} diff --git a/app/templates/partials/folder_card_tidy.html b/app/templates/partials/folder_card_tidy.html index 6a6bcfa..de86d1c 100644 --- a/app/templates/partials/folder_card_tidy.html +++ b/app/templates/partials/folder_card_tidy.html @@ -1,82 +1,20 @@ -
- -
-
-

{{ folder.name }}

-
- - -
-
- - -
-
- {{ folder.total_count }} total - {% if folder.pending_count > 0 %} - - {% else %} - {{ folder.pending_count }} pending - {% endif %} - {{ folder.total_count - folder.pending_count }} processed -
- {% if folder.priority == 1 %} - High Priority - {% elif folder.priority == -1 %} - Low Priority - {% else %} - Normal Priority - {% endif %} -
- -
-

{{ folder.rule_text }}

-
- -
-
- Organize: - - - - -
-
-
-
\ No newline at end of file +{% extends "partials/folder_card_base.html" %} + +{% block badges %} + {{ folder.total_count }} total + {% if folder.pending_count > 0 %} + + {% else %} + {{ folder.pending_count }} pending + {% endif %} + {{ folder.total_count - folder.pending_count }} processed +{% endblock %} diff --git a/app/templates/partials/folder_type_selection_modal.html b/app/templates/partials/folder_type_selection_modal.html new file mode 100644 index 0000000..eb91194 --- /dev/null +++ b/app/templates/partials/folder_type_selection_modal.html @@ -0,0 +1,52 @@ + \ No newline at end of file diff --git a/app/templates/partials/folders_list.html b/app/templates/partials/folders_list.html index ff9c963..443157c 100644 --- a/app/templates/partials/folders_list.html +++ b/app/templates/partials/folders_list.html @@ -1,4 +1,7 @@
{% include 'partials/folders_to_tidy_section.html' %} {% include 'partials/destination_folders_section.html' %} + {% if show_hidden %} + {% include 'partials/hidden_folders_section.html' %} + {% endif %}
\ No newline at end of file diff --git a/app/templates/partials/hidden_folders_section.html b/app/templates/partials/hidden_folders_section.html new file mode 100644 index 0000000..b23b149 --- /dev/null +++ b/app/templates/partials/hidden_folders_section.html @@ -0,0 +1,27 @@ +
+
+
+
+

+ + Hidden Folders +

+

Folders that are ignored during email processing

+
+
+
+ +
+ {% for folder in folders|selectattr('folder_type', 'equalto', 'ignore') %} + {% include 'partials/folder_card_ignore.html' %} + {% else %} +
+
+ +
+

No hidden folders

+

Folders that are set to ignore will appear here.

+
+ {% endfor %} +
+
\ No newline at end of file diff --git a/app/templates/partials/imap_config_modal.html b/app/templates/partials/imap_config_modal.html index bdae6bf..d04de1b 100644 --- a/app/templates/partials/imap_config_modal.html +++ b/app/templates/partials/imap_config_modal.html @@ -80,8 +80,8 @@ {% if success %}
-
diff --git a/docs/design/data-model.md b/docs/design/data-model.md index 99e1ff7..24c5cfb 100644 --- a/docs/design/data-model.md +++ b/docs/design/data-model.md @@ -229,7 +229,7 @@ The `recent_emails` field stores an array of JSON objects: ## Folder Types -The system supports two distinct types of folders, each with different purposes and behaviors: +The system supports three distinct types of folders, each with different purposes and behaviors: ### Tidy Folders @@ -261,14 +261,35 @@ Folders with `folder_type = 'destination'` are target folders where emails are m - Simpler interface without pending/processed indicators - Focus on folder management and viewing contents +### Ignore Folders + +Folders with `folder_type = 'ignore'` are folders that are stored in the database but are neither scanned to be tidied nor used as destination folders. + +**Characteristics:** +- Hidden by default in the user interface +- Not processed by AI for organization +- No organization rules specified +- Known emails count is reset to 0 when changed to this type +- Example: Archive, Spam, Drafts folders + +**UI Representation:** +- Hidden by default unless "Show Hidden" checkbox is checked +- When visible, shows minimal information +- No action buttons for organization or processing + ### Folder Type Determination Folder types are determined as follows: - During IMAP synchronization: - - Folders named "inbox" (case-insensitive) are automatically set as 'tidy' - - All other folders are set as 'destination' + - First step: Connection testing + - Second step: Folder type selection modal with table + - Default folder types: + - Inbox: Tidy + - Archive/Spam/Drafts: Ignore + - All others: Destination - Manually created folders default to 'destination' -- Folder type can be changed through administrative functions +- Folder type can be changed through the user interface +- When changing to 'ignore', emails_count is reset to 0 ## Future Data Model Considerations diff --git a/docs/design/folder-types-ui.md b/docs/design/folder-types-ui.md index 12a71dc..f0f2113 100644 --- a/docs/design/folder-types-ui.md +++ b/docs/design/folder-types-ui.md @@ -2,227 +2,53 @@ ## Overview -This document outlines the UI design changes needed to support the new folder types feature: "Folders to Tidy" and "Destination Folders". The UI will be reorganized to clearly separate these two types of folders into distinct sections. +This document provides a high-level overview of the folder types structure in the Email Organizer application. The UI is organized into three main folder types: Tidy, Destination, and Ignore, with appropriate components for each type. ## UI Structure -### Main Page Layout +The main page is divided into sections based on folder types: -The main page will be divided into two distinct sections: - -1. **Folders to Tidy Section** - - Contains folders with `folder_type = 'tidy'` - - Typically includes the inbox and other source folders - - Shows pending and processed email counts - - Has actions for viewing and processing emails - -2. **Destination Folders Section** - - Contains folders with `folder_type = 'destination'` - - Contains target folders for email organization - - Shows count of emails moved to each folder - - Focuses on folder management and viewing contents - -### Visual Design - -#### Section Headers -Each section will have a clear header with: -- Section title -- Brief description of the section's purpose -- Action button (e.g., "Add Folder" for destination folders) - -#### Section Styling -- Different background colors or borders to visually distinguish sections -- Consistent spacing and layout within each section -- Responsive grid layout that adapts to screen size +1. **Folders to Tidy Section**: Contains folders with `folder_type = 'tidy'` +2. **Destination Folders Section**: Contains folders with `folder_type = 'destination'` +3. **Hidden Folders Section**: Contains folders with `folder_type = 'ignore'` (visible only when "Show Hidden" is checked) ## Folder Card Components -### Tidy Folder Card +### Base Template +All folder cards extend from `folder_card_base.html` which provides: +- Common card structure with edit/delete buttons +- Priority badge display +- Rule text section +- Block for additional content specific to folder type -For folders with `folder_type = 'tidy'`, the card will display: - -#### Header -- Folder name (prominent) -- Edit and delete buttons - -#### Count Badges -- Total emails count -- Pending emails count (with warning styling if > 0) -- Processed emails count (calculated as total - pending) - -#### Actions -- "View Pending" button (if pending count > 0) +### Tidy Folder Card (`folder_card_tidy.html`) +Extends base template with: +- Total, pending, and processed email count badges - Organize toggle switch -- Priority badge +- View pending emails button -#### Content -- Rule text description -- Recent email previews (if available) +### Destination Folder Card (`folder_card_destination.html`) +Extends base template with: +- Email count badge +- Simplified UI without processing elements -### Destination Folder Card +### Ignore Folder Card (to be created) +Will extend base template with: +- "Ignored" status badge +- Minimal information display +- No processing elements -For folders with `folder_type = 'destination'`, the card will display: +## IMAP Synchronization -#### Header -- Folder name (prominent) -- Edit and delete buttons +### Two-Step Process +1. **Connection Testing**: Test IMAP connection settings +2. **Folder Type Selection**: Select processing type for each folder -#### Count Badge -- Emails count (number of emails moved to this folder) +### Default Folder Types +- Inbox: Tidy +- Archive/Spam/Drafts: Ignore +- All others: Destination -#### Content -- Rule text description (if applicable) +## Show Hidden Folders -#### Actions -- Basic folder management options -- No organize toggle (as it's not applicable) - -## UI Components - -### Section Templates - -#### Folders to Tidy Section -```html -
-
-

Folders to Tidy

-

Folders containing emails that need to be processed

- -
-
- {% for folder in tidy_folders %} - {% include 'partials/folder_card_tidy.html' %} - {% endfor %} -
-
-``` - -#### Destination Folders Section -```html -
-
-

Destination Folders

-

Folders where emails are organized and stored

- -
-
- {% for folder in destination_folders %} - {% include 'partials/folder_card_destination.html' %} - {% endfor %} -
-
-``` - -### Folder Card Templates - -#### Tidy Folder Card -```html -
-
-
-

{{ folder.name }}

-
- - -
-
- -
- {{ folder.total_count }} total - {% if folder.pending_count > 0 %} - - {% else %} - {{ folder.pending_count }} pending - {% endif %} - {{ folder.total_count - folder.pending_count }} processed -
- -
-

{{ folder.rule_text }}

-
- -
-
- Organize: - -
- {% if folder.priority == 1 %} - High Priority - {% endif %} -
-
-
-``` - -#### Destination Folder Card -```html -
-
-
-

{{ folder.name }}

-
- - -
-
- -
- {{ folder.emails_count }} emails -
- -
-

{{ folder.rule_text }}

-
-
-
-``` - -## Styling Guidelines - -### Color Scheme -- **Tidy Folders**: Use warning colors (yellow/orange) for pending emails -- **Destination Folders**: Use primary colors (blue) for email counts -- Consistent use of DaisyUI badge classes for different states - -### Responsive Design -- Grid layout adjusts from 1 column on mobile to 3 columns on desktop -- Cards should have consistent width across all screen sizes -- Section headers should remain readable on mobile - -### Interactive Elements -- Buttons should have hover states -- Toggle switches should be clearly labeled -- Pending email count should be clickable to open dialog - -## Implementation Notes - -### Template Organization -- Create separate partial templates for each folder type -- Main index template will include both sections -- Use HTMX for dynamic updates without full page reloads - -### Data Loading -- Fetch folders filtered by type from the backend -- Pass filtered lists to appropriate section templates -- Maintain existing functionality for folder operations - -### Accessibility -- Ensure all interactive elements have proper ARIA labels -- Use semantic HTML5 elements for section structure -- Maintain keyboard navigation support \ No newline at end of file +A checkbox allows users to show/hide folders with `folder_type = 'ignore'`. When checked, these folders appear in a dedicated section with appropriate styling to indicate they're ignored. \ No newline at end of file diff --git a/docs/plans/folder-types-ignore-implementation.md b/docs/plans/folder-types-ignore-implementation.md new file mode 100644 index 0000000..094dc46 --- /dev/null +++ b/docs/plans/folder-types-ignore-implementation.md @@ -0,0 +1,143 @@ +# Folder Types Implementation Plan: Adding Ignore Type + +## Overview +This plan outlines the implementation of a third folder type called "Ignore" which will be stored in the database but neither scanned for tidying nor used as destination folders. When a folder is set to ignore, it will be hidden by default in the user interface. + +## System Architecture Changes + +### Current Folder Types +1. **Tidy**: Folders scanned and processed by AI, sorting them into Destination folders +2. **Destination**: Folders that are targets for email organization based on rules + +### New Folder Types +1. **Tidy**: Folders scanned and processed by AI, sorting them into Destination folders +2. **Destination**: Folders that are targets for email organization based on rules +3. **Ignore**: Folders stored in database but not processed by AI and hidden by default + +## Implementation Steps + +### 1. Update Design Documentation +- Update [`docs/design/data-model.md`](docs/design/data-model.md) to include the new "ignore" folder type +- Update [`docs/design/folder-types-ui.md`](docs/design/folder-types-ui.md) to include UI changes for the new type +- Add documentation for folder type behavior and business rules + +### 2. Update Database Model +- The [`folder_type`](app/models.py:43) field in the Folder model already supports string values and can accommodate the new "ignore" type +- No database migration is needed as the field is already a string with a default value +- Update any business logic in the application to handle the new folder type + +### 3. Update IMAP Synchronization Flow +- Modify the IMAP sync process to include a second step with a folder type selection modal +- The modal should display a table of folders with: + - Folder name column + - Folder type selection column (Tidy, Destination, Ignore) +- Default folder types: + - Inbox: Tidy + - Archive/Spam/Drafts: Ignore +- Create a new template for the folder selection modal + +### 4. Update User Interface +- Add a checkbox (unchecked by default) for "show hidden" folders +- When checked, it should reveal folders with folder_type="ignore" +- Modify folder card components to handle the new folder type: + - Hide ignore folders by default + - Show appropriate UI elements based on folder type + - Replace the "organize this folder" toggle with a folder type selector for tidy and destination folders + +### 5. Update Folder Management +- Modify the folder creation and editing forms to include folder type selection +- Update the folder card templates to handle the new type +- Add logic to reset known emails count when changing to ignore type +- Update the delete functionality to handle all folder types + +### 6. Update API Endpoints +- Modify the folder toggle endpoint to handle folder type changes instead of just organize_enabled +- Add new endpoint for updating folder type specifically +- Update existing endpoints to handle the new folder type in their logic + +### 7. Update Tests +- Add tests for the new folder type functionality +- Test that ignore folders are hidden by default +- Test that they can be shown when the "show hidden" checkbox is checked +- Test folder type changes through the API +- Test the IMAP sync flow with the new folder selection modal + +## Implementation Details + +### Folder Type Business Logic +``` +Tidy Folders: +- Scanned and processed by AI +- Have pending/processed email counts +- Can have organization rules enabled/disabled +- Example: Inbox + +Destination Folders: +- Not processed by AI +- Display count of emails moved to this folder +- Focus on folder management and viewing contents +- Example: "Projects", "Finance", "Personal" + +Ignore Folders: +- Stored in database but not processed by AI +- Hidden by default in UI +- No organization rules +- Known emails count reset to 0 when changed to ignore +- Example: Archive, Spam, Drafts +``` + +### UI Changes +1. **Main Page**: + - Add "Show Hidden" checkbox in the search/filter section + - When checked, display ignore folders with appropriate styling + +2. **Folder Cards**: + - For tidy folders: Show pending/processed counts and organize toggle + - For destination folders: Show emails count + - For ignore folders: Show minimal information when visible + +3. **IMAP Sync Modal**: + - First step: Connection testing (existing) + - Second step: Folder type selection (new) + - Table with folder names and type selection dropdowns + +### API Changes +1. **Folder Creation/Update**: + - Include folder_type in form data + - Default to "destination" for manually created folders + +2. **Folder Toggle**: + - Change from organize_enabled toggle to folder_type selector + - Handle resetting emails_count when changing to ignore + +### Database Schema +- No changes needed as the existing [`folder_type`](app/models.py:43) field can accommodate the new value +- Current field: `folder_type = db.Column(db.String(20), default='destination', nullable=False)` + +## Testing Strategy + +### Unit Tests +- Test folder type validation +- Test folder type change logic (resetting emails count) +- Test UI rendering for different folder types + +### Integration Tests +- Test IMAP sync flow with folder type selection +- Test "show hidden" functionality +- Test folder CRUD operations with all types + +### End-to-End Tests +- Test complete user workflow for creating folders with different types +- Test IMAP setup and folder type selection +- Test showing/hiding ignore folders + +## Migration Plan +- No database migration needed as the field already supports string values +- Existing folders will maintain their current types +- New folders will default to "destination" type + +## Rollback Plan +- If issues arise, the system can be rolled back by: + - Limiting folder_type values to only 'tidy' and 'destination' + - Reverting UI changes to the previous two-type system + - Disabling the "show hidden" functionality \ No newline at end of file diff --git a/tests/test_routes.py b/tests/test_routes.py index c43c80f..8da3562 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -317,7 +317,7 @@ def test_toggle_folder_organize_enabled(authenticated_client, mock_folder): assert mock_folder.organize_enabled is True # Toggle the flag - response = authenticated_client.put(f'/api/folders/{mock_folder.id}/toggle') + response = authenticated_client.put(f'/api/folders/{mock_folder.id}/type', data={'folder_type': 'ignore'}, content_type='application/x-www-form-urlencoded') # Should return 200 OK assert response.status_code == 200 @@ -325,10 +325,10 @@ def test_toggle_folder_organize_enabled(authenticated_client, mock_folder): # Verify the folder was updated in the database updated_folder = Folder.query.filter_by(id=mock_folder.id).first() assert updated_folder is not None - assert updated_folder.organize_enabled is False + assert updated_folder.folder_type == 'ignore' - # Toggle again to make sure it works both ways - response2 = authenticated_client.put(f'/api/folders/{mock_folder.id}/toggle') + # Toggle back to make sure it works both ways + response2 = authenticated_client.put(f'/api/folders/{mock_folder.id}/type', data={'folder_type': 'tidy'}, content_type='application/x-www-form-urlencoded') # Should return 200 OK assert response2.status_code == 200 @@ -336,7 +336,7 @@ def test_toggle_folder_organize_enabled(authenticated_client, mock_folder): # Verify the folder was updated in the database again updated_folder2 = Folder.query.filter_by(id=mock_folder.id).first() assert updated_folder2 is not None - assert updated_folder2.organize_enabled is True + assert updated_folder2.folder_type == 'tidy' def test_toggle_folder_organize_enabled_not_found(authenticated_client, mock_user): """Test toggling organize_enabled flag for a non-existent folder."""