216 lines
8.7 KiB
Markdown
216 lines
8.7 KiB
Markdown
# Milestone 1: Prototype Implementation Plan
|
|
|
|
## Objective
|
|
Deliver a functional prototype demonstrating the core infrastructure, basic UI for rule configuration, a mock email processing pipeline, and database schema implementation as outlined in the project roadmap.
|
|
|
|
## Scope
|
|
This milestone focuses on establishing the foundational elements required for the Email Organizer. It will not include actual email fetching, complex AI processing, or user authentication. The goal is to have a working skeleton that proves the core concepts.
|
|
|
|
## File and Folder Structure
|
|
```
|
|
email-organizer/
|
|
├── app/ # Main application package
|
|
│ ├── __init__.py # Flask app factory
|
|
│ ├── models.py # SQLAlchemy models (User, Folder)
|
|
│ ├── routes.py # Flask routes (UI endpoints)
|
|
│ ├── static/ # Static files (CSS, JS, images)
|
|
│ │ └── ... # HTMX, AlpineJS, Tailwind CSS files
|
|
│ └── templates/ # Jinja2 HTML templates
|
|
│ └── index.html # Main UI page
|
|
├── migrations/ # Alembic migrations
|
|
├── tests/ # Unit and integration tests
|
|
│ ├── __init__.py
|
|
│ ├── conftest.py # Pytest configuration and fixtures
|
|
│ ├── test_models.py # Tests for database models
|
|
│ └── test_routes.py # Tests for UI routes
|
|
├── config.py # Application configuration
|
|
├── manage.py # CLI commands (e.g., db setup, mock process)
|
|
├── requirements.txt # Python dependencies
|
|
├── .env # Environment variables (not in VCS)
|
|
├── .env.example # Example environment variables
|
|
├── README.md
|
|
└── plans/
|
|
└── milestone-1.md # This plan
|
|
```
|
|
|
|
## Sample Code
|
|
|
|
### 1. Flask App Factory (`app/__init__.py`)
|
|
```python
|
|
from flask import Flask
|
|
from flask_sqlalchemy import SQLAlchemy
|
|
|
|
db = SQLAlchemy()
|
|
|
|
def create_app(config_name='default'):
|
|
app = Flask(__name__)
|
|
app.config.from_object(config[config_name])
|
|
|
|
db.init_app(app)
|
|
|
|
from app.routes import main
|
|
app.register_blueprint(main)
|
|
|
|
return app
|
|
```
|
|
|
|
### 2. SQLAlchemy Models (`app/models.py`)
|
|
```python
|
|
from app import db
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
import uuid
|
|
|
|
class User(db.Model):
|
|
__tablename__ = 'users'
|
|
id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
email = db.Column(db.String(255), unique=True, nullable=False)
|
|
# Placeholders for Milestone 1
|
|
password_hash = db.Column(db.LargeBinary)
|
|
imap_config = db.Column(db.JSONB)
|
|
|
|
class Folder(db.Model):
|
|
__tablename__ = 'folders'
|
|
id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
user_id = db.Column(UUID(as_uuid=True), db.ForeignKey('users.id'), nullable=False)
|
|
name = db.Column(db.String(255), nullable=False)
|
|
rule_text = db.Column(db.Text)
|
|
priority = db.Column(db.Integer)
|
|
|
|
user = db.relationship('User', backref=db.backref('folders', lazy=True))
|
|
```
|
|
|
|
### 3. Basic UI Route (`app/routes.py`)
|
|
```python
|
|
from flask import Blueprint, render_template, request, jsonify
|
|
from app.models import Folder
|
|
|
|
main = Blueprint('main', __name__)
|
|
|
|
@main.route('/')
|
|
def index():
|
|
# For prototype, use a mock user ID
|
|
mock_user_id = '123e4567-e89b-12d3-a456-426614174000'
|
|
folders = Folder.query.filter_by(user_id=mock_user_id).all()
|
|
return render_template('index.html', folders=folders)
|
|
|
|
@main.route('/api/folders', methods=['POST'])
|
|
def add_folder():
|
|
# Mock implementation for prototype
|
|
data = request.get_json()
|
|
# In a real implementation, this would save to the database
|
|
# For now, just echo back the data
|
|
return jsonify({'message': 'Folder added (mock)', 'folder': data}), 201
|
|
```
|
|
|
|
### 4. Simple HTML Template (`app/templates/index.html`)
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Email Organizer - Prototype</title>
|
|
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<!-- Include AlpineJS if needed -->
|
|
</head>
|
|
<body class="bg-base-100">
|
|
<div class="container mx-auto p-4">
|
|
<h1 class="text-2xl font-bold mb-4">Email Organizer - Prototype</h1>
|
|
|
|
<div id="folders-list">
|
|
<h2 class="text-xl font-semibold mb-2">Folders</h2>
|
|
<ul>
|
|
{% for folder in folders %}
|
|
<li class="mb-2 p-2 bg-base-200 rounded">{{ folder.name }}: {{ folder.rule_text }}</li>
|
|
{% endfor %
|
|
</ul>
|
|
</div>
|
|
|
|
<div id="add-folder-form" class="mt-6">
|
|
<h2 class="text-xl font-semibold mb-2">Add Folder</h2>
|
|
<form hx-post="/api/folders" hx-target="#folders-list" hx-swap="beforeend">
|
|
<div class="mb-2">
|
|
<label for="folder-name" class="block">Name:</label>
|
|
<input type="text" id="folder-name" name="name" class="input input-bordered w-full max-w-xs" required>
|
|
</div>
|
|
<div class="mb-2">
|
|
<label for="folder-rule" class="block">Rule (Natural Language):</label>
|
|
<textarea id="folder-rule" name="rule_text" class="textarea textarea-bordered w-full" required></textarea>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">Add Folder</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
### 5. Mock Email Processing Script (`manage.py`)
|
|
```python
|
|
import sys
|
|
from app import create_app, db
|
|
from app.models import Folder
|
|
|
|
def mock_process_emails():
|
|
"""Simulate processing emails with defined rules."""
|
|
app = create_app()
|
|
with app.app_context():
|
|
# Mock user ID
|
|
mock_user_id = '123e4567-e89b-12d3-a456-426614174000'
|
|
folders = Folder.query.filter_by(user_id=mock_user_id).all()
|
|
|
|
# Mock emails
|
|
emails = [
|
|
{'subject': 'Your Amazon Order', 'from': 'no-reply@amazon.com', 'body': 'Your order has shipped.'},
|
|
{'subject': 'Meeting Reminder', 'from': 'boss@company.com', 'body': 'Don\'t forget the meeting at 3 PM.'},
|
|
{'subject': 'Special Offer!', 'from': 'deals@shop.com', 'body': 'Exclusive discounts inside!'}
|
|
]
|
|
|
|
print("Starting mock email processing...")
|
|
for email in emails:
|
|
print(f"\nProcessing email: {email['subject']}")
|
|
matched = False
|
|
for folder in folders:
|
|
# Simple mock rule matching (in real app, this would be more complex)
|
|
if folder.rule_text.lower() in email['subject'].lower() or folder.rule_text.lower() in email['from'].lower():
|
|
print(f" -> Matched rule '{folder.rule_text}' -> Folder '{folder.name}'")
|
|
matched = True
|
|
break
|
|
if not matched:
|
|
print(" -> No matching rule found.")
|
|
|
|
if __name__ == '__main__':
|
|
if len(sys.argv) > 1 and sys.argv[1] == 'mock-process':
|
|
mock_process_emails()
|
|
else:
|
|
print("Usage: python manage.py mock-process")
|
|
```
|
|
|
|
## Testing Plan
|
|
|
|
### Unit Tests (`tests/test_models.py`)
|
|
- Test `User` model instantiation and basic properties.
|
|
- Test `Folder` model instantiation, properties, and relationship with `User`.
|
|
- Test database constraints (e.g., unique email for User).
|
|
|
|
### Integration Tests (`tests/test_routes.py`)
|
|
- Test the `/` route loads successfully and renders the template.
|
|
- Test the `/api/folders` POST endpoint accepts data and returns a JSON response (mock behavior).
|
|
|
|
### Setup (`tests/conftest.py`)
|
|
- Use `pytest` fixtures to create an app instance and a temporary database for testing.
|
|
- Provide a fixture to create a mock user and folders for tests.
|
|
|
|
## Acceptance Criteria
|
|
1. **Infrastructure**: The Flask application initializes correctly, connects to the PostgreSQL database, and the development server starts without errors.
|
|
2. **Database Schema**: The `users` and `folders` tables are created in the database with the correct columns, data types, and relationships as defined in `models.py`.
|
|
3. **UI Functionality**:
|
|
* The root URL (`/`) loads the `index.html` template.
|
|
* The page displays a list of folders (initially empty or seeded).
|
|
* The "Add Folder" form is present and can be submitted.
|
|
* Submitting the form sends a request to the `/api/folders` endpoint.
|
|
4. **Mock Processing**:
|
|
* The `python manage.py mock-process` command runs without errors.
|
|
* The script correctly fetches folder rules from the database.
|
|
* The script demonstrates matching mock emails to rules and prints the results to the console.
|
|
5. **Code Quality**: Code follows Python best practices, is well-structured, and includes basic documentation/comments where necessary. |