feat: Add alert processing functionality and UI feedback

This commit is contained in:
bolade
2025-08-12 10:41:47 +01:00
parent 1fd3a95093
commit 3ea27caca6
6 changed files with 54 additions and 12 deletions
+2
View File
@@ -142,6 +142,8 @@ def process_alerts(db: Session, cfg: dict) -> List[int]:
} }
for m in get_thread_messages(db, t.id)[-4:] for m in get_thread_messages(db, t.id)[-4:]
] ]
print(f"These are the messages: {msgs}")
ai = analyze_thread(t.subject or "", msgs) ai = analyze_thread(t.subject or "", msgs)
# Persist AI decision on thread # Persist AI decision on thread
+13 -4
View File
@@ -49,7 +49,12 @@ app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/", response_class=HTMLResponse) @app.get("/", response_class=HTMLResponse)
def home(request: Request, db: Session = Depends(get_db), account: str | None = None): def home(
request: Request,
db: Session = Depends(get_db),
account: str | None = None,
alerts_processed: int | None = None,
):
from datetime import datetime from datetime import datetime
from sqlalchemy import func from sqlalchemy import func
@@ -109,6 +114,7 @@ def home(request: Request, db: Session = Depends(get_db), account: str | None =
"threads": threads_with_info, "threads": threads_with_info,
"account": account or "", "account": account or "",
"status": _status_for_templates(), "status": _status_for_templates(),
"alerts_processed": alerts_processed,
}, },
) )
@@ -335,7 +341,8 @@ async def config_save(request: Request):
def process(db: Session = Depends(get_db)): def process(db: Session = Depends(get_db)):
cfg = load_config() cfg = load_config()
alerted = process_alerts(db, cfg) alerted = process_alerts(db, cfg)
return {"alerted_threads": alerted} # Redirect back to main page with success indicator
return RedirectResponse(url=f"/?alerts_processed={len(alerted)}", status_code=303)
def _sync_emails_once(cfg: dict) -> int: def _sync_emails_once(cfg: dict) -> int:
@@ -357,7 +364,7 @@ def _sync_emails_once(cfg: dict) -> int:
days_back = max(1, delta_days) days_back = max(1, delta_days)
except Exception: except Exception:
pass pass
max_results = 100 max_results = 5
client = ZohoClient( client = ZohoClient(
email=cfg.get("zoho_email") or account_email, email=cfg.get("zoho_email") or account_email,
app_password=cfg.get("zoho_app_password"), app_password=cfg.get("zoho_app_password"),
@@ -413,7 +420,9 @@ def _sync_emails_background_task():
{ {
"sync_in_progress": False, "sync_in_progress": False,
"last_sync_status": "success", "last_sync_status": "success",
"last_sync_at": datetime.now(timezone.utc).strftime("%d/%m/%y %I:%M %p"), "last_sync_at": datetime.now(timezone.utc).strftime(
"%d/%m/%y %I:%M %p"
),
"last_sync_count": count, "last_sync_count": count,
"last_sync_error": None, "last_sync_error": None,
} }
+3 -3
View File
@@ -156,7 +156,7 @@ class ZohoClient:
# Get email body snippet # Get email body snippet
body = self._get_email_body(email_message) body = self._get_email_body(email_message)
snippet = body[:200] + "..." if len(body) > 200 else body
email_data = { email_data = {
"id": num.decode(), "id": num.decode(),
@@ -168,11 +168,11 @@ class ZohoClient:
"messageId": message_id, "messageId": message_id,
"inReplyTo": in_reply_to, "inReplyTo": in_reply_to,
"folder": folder, "folder": folder,
"snippet": snippet, "snippet": body,
} }
emails.append(email_data) emails.append(email_data)
logging.info(f"Long body: {body}")
except Exception as e: except Exception as e:
print(f"❌ Error processing email {num}: {e}") print(f"❌ Error processing email {num}: {e}")
continue continue
+23
View File
@@ -112,3 +112,26 @@ button {
box-shadow: 0 6px 18px rgba(63, 99, 183, 0.35); box-shadow: 0 6px 18px rgba(63, 99, 183, 0.35);
} }
button:hover { filter: brightness(1.05); } button:hover { filter: brightness(1.05); }
/* Alert styles */
.alert {
padding: 0.75rem 1rem;
border-radius: 8px;
border: 1px solid;
font-size: 0.9rem;
}
.alert.success {
background: rgba(34, 197, 94, 0.1);
border-color: var(--success);
color: #4ade80;
}
.alert.warn {
background: rgba(245, 158, 11, 0.1);
border-color: var(--warn);
color: #fbbf24;
}
.alert.danger {
background: rgba(239, 68, 68, 0.1);
border-color: var(--danger);
color: #f87171;
}
+3
View File
@@ -16,6 +16,9 @@
<form action="/sync_emails" method="post" style="display:inline-block; margin-left:12px;"> <form action="/sync_emails" method="post" style="display:inline-block; margin-left:12px;">
<button type="submit">Process Emails</button> <button type="submit">Process Emails</button>
</form> </form>
<form action="/process" method="post" style="display:inline-block; margin-left:12px;">
<button type="submit">Process Alerts</button>
</form>
</nav> </nav>
</div> </div>
</header> </header>
+5
View File
@@ -4,6 +4,11 @@
<div class="col"> <div class="col">
<h2>Threads{% if account %} for {{ account }}{% endif %}</h2> <h2>Threads{% if account %} for {{ account }}{% endif %}</h2>
<p class="muted">Latest updated threads. Click an ID to view details and AI analysis.</p> <p class="muted">Latest updated threads. Click an ID to view details and AI analysis.</p>
{% if alerts_processed is not none %}
<div class="alert success" style="margin-bottom:12px;">
✓ Alerts processed! {{ alerts_processed }} thread(s) were checked for alerts.
</div>
{% endif %}
{% if status %} {% if status %}
<div class="muted" style="margin-top:6px;"> <div class="muted" style="margin-top:6px;">
{% if status.sync_in_progress %} {% if status.sync_in_progress %}