Revert "message pagination"

This reverts commit fd9d113eef.
This commit is contained in:
Michael Woods
2025-12-28 19:14:48 -05:00
parent fd9d113eef
commit f8305945a4
2 changed files with 41 additions and 139 deletions

View File

@@ -1,5 +1,5 @@
# packetserver/http/routers/messages.py
from fastapi import APIRouter, Depends, Query, HTTPException, Path, Request, Query
from fastapi import APIRouter, Depends, Query, HTTPException, Path, Request
from fastapi.responses import HTMLResponse
from typing import Optional
from datetime import datetime
@@ -11,7 +11,6 @@ from pydantic import BaseModel, Field, validator
from packetserver.http.dependencies import get_current_http_user
from packetserver.http.auth import HttpUser
from packetserver.http.database import DbDependency
from packetserver.http.server import templates
html_router = APIRouter(tags=["messages-html"])
@@ -28,78 +27,58 @@ class MarkRetrievedRequest(BaseModel):
return v
@router.get("/messages", response_class=HTMLResponse)
async def message_list(
request: Request,
@router.get("/messages")
async def get_messages(
db: DbDependency,
current_user: HttpUser = Depends(get_current_http_user),
msg_type: str = Query("received", alias="type"), # received, sent, all
search: Optional[str] = Query(None),
page: int = Query(1, ge=1),
per_page: int = Query(50, ge=1, le=200),
type: str = Query("received", description="received, sent, or all"),
limit: Optional[int] = Query(20, le=100, description="Max messages to return (default 20, max 100)"),
since: Optional[str] = Query(None, description="ISO UTC timestamp filter (e.g. 2025-12-01T00:00:00Z)"),
):
username = current_user.username.upper().strip()
valid_types = {"received", "sent", "all"}
if msg_type not in valid_types:
msg_type = "received"
if limit is None or limit < 1:
limit = 20
username = current_user.username
with db.transaction() as conn:
root = conn.root()
user_messages = root["messages"].get(username, [])
# Convert to list of dicts (as current code does)
if 'messages' not in root:
root['messages'] = PersistentMapping()
if username not in root['messages']:
root['messages'][username] = persistent.list.PersistentList()
mailbox = root['messages'][username]
since_dt = None
if since:
try:
since_dt = datetime.fromisoformat(since.replace("Z", "+00:00"))
except ValueError:
raise HTTPException(status_code=400, detail="Invalid 'since' format")
messages = []
for msg_id, msg in user_messages.items():
for msg in mailbox:
if type == "received" and msg.msg_from == username:
continue
if type == "sent" and msg.msg_from != username:
continue
if since_dt and msg.sent_at < since_dt:
continue
messages.append({
"id": msg_id,
"from": msg["from"],
"to": msg["to"],
"text": msg["text"],
"timestamp": msg["timestamp"],
"id": str(msg.msg_id),
"from": msg.msg_from,
"to": list(msg.msg_to) if isinstance(msg.msg_to, tuple) else [msg.msg_to],
"sent_at": msg.sent_at.isoformat() + "Z",
"text": msg.text,
"has_attachments": len(msg.attachments) > 0,
"retrieved": msg.retrieved,
})
# Filter by type
if msg_type == "received":
filtered = [m for m in messages if username in m["to"]]
elif msg_type == "sent":
filtered = [m for m in messages if m["from"] == username]
else: # all
filtered = messages
messages.sort(key=lambda m: m["sent_at"], reverse=True)
# Apply search
if search:
search_lower = search.strip().lower()
filtered = [
m for m in filtered
if (search_lower in m["from"].lower() or
any(search_lower in t.lower() for t in m["to"]) or
search_lower in m["text"].lower())
]
# Sort newest first
filtered.sort(key=lambda m: m["timestamp"], reverse=True)
# Pagination
total = len(filtered)
start = (page - 1) * per_page
paginated = filtered[start:start + per_page]
total_pages = (total + per_page - 1) // per_page
return templates.TemplateResponse(
"message_list.html",
{
"request": request,
"messages": paginated,
"current_user": current_user,
"total": total,
"page": page,
"per_page": per_page,
"total_pages": total_pages,
"current_type": msg_type,
"current_search": search,
}
)
return {"messages": messages[:limit], "total_returned": len(messages[:limit])}
@router.get("/messages/{msg_id}")
async def get_message(

View File

@@ -10,45 +10,6 @@
</button>
</div>
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-3">
<!-- Type tabs -->
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link {% if current_type == 'received' %}active{% endif %}"
href="?type=received{% if current_search %}&search={{ current_search }}{% endif %}">Received</a>
</li>
<li class="nav-item">
<a class="nav-link {% if current_type == 'sent' %}active{% endif %}"
href="?type=sent{% if current_search %}&search={{ current_search }}{% endif %}">Sent</a>
</li>
<li class="nav-item">
<a class="nav-link {% if current_type == 'all' %}active{% endif %}"
href="?type=all{% if current_search %}&search={{ current_search }}{% endif %}">All</a>
</li>
</ul>
<!-- Search form -->
<form method="get" class="d-flex">
<input type="hidden" name="type" value="{{ current_type }}">
<input type="text" name="search" class="form-control me-2" placeholder="Search messages..."
value="{{ current_search or '' }}">
<button type="submit" class="btn btn-outline-primary">Search</button>
{% if current_search %}
<a href="?type={{ current_type }}" class="btn btn-outline-secondary ms-2">Clear</a>
{% endif %}
</form>
</div>
{% if total == 0 %}
<div class="alert alert-info">
{% if current_search %}
No messages found matching "{{ current_search }}".
{% else %}
No messages yet.
{% endif %}
</div>
{% endif %}
<div class="mb-3">
<a href="?msg_type=received" class="btn btn-sm {% if msg_type == 'received' %}btn-primary{% else %}btn-outline-primary{% endif %}">Received</a>
<a href="?msg_type=sent" class="btn btn-sm {% if msg_type == 'sent' %}btn-primary{% else %}btn-outline-primary{% endif %}">Sent</a>
@@ -56,9 +17,6 @@
</div>
{% if messages %}
<p class="text-muted text-center mb-3">
Showing {{ (page-1)*per_page + 1 }}{{ min(page*per_page, total) }} of {{ total }} messages
</p>
<ul class="message-list">
{% for msg in messages %}
<li>
@@ -72,41 +30,6 @@
</li>
{% endfor %}
</ul>
{% if total_pages > 1 %}
<nav aria-label="Message pagination" class="mt-4">
<ul class="pagination justify-content-center">
<!-- Previous -->
<li class="page-item {% if page == 1 %}disabled{% endif %}">
<a class="page-link" href="?page={{ page - 1 }}&type={{ current_type }}{% if current_search %}&search={{ current_search }}{% endif %}">Previous</a>
</li>
<!-- Page numbers (simple: show current ±2, plus first/last) -->
{% set nearby = range(max(1, page-2), min(total_pages+1, page+3)) %}
{% if 1 not in nearby %}
<li class="page-item"><a class="page-link" href="?page=1&type={{ current_type }}{% if current_search %}&search={{ current_search }}{% endif %}">1</a></li>
{% if page > 4 %}<li class="page-item disabled"><span class="page-link">...</span></li>{% endif %}
{% endif %}
{% for p in nearby %}
<li class="page-item {% if p == page %}active{% endif %}">
<a class="page-link" href="?page={{ p }}&type={{ current_type }}{% if current_search %}&search={{ current_search }}{% endif %}">{{ p }}</a>
</li>
{% endfor %}
{% if total_pages not in nearby %}
{% if page < total_pages - 3 %}<li class="page-item disabled"><span class="page-link">...</span></li>{% endif %}
<li class="page-item"><a class="page-link" href="?page={{ total_pages }}&type={{ current_type }}{% if current_search %}&search={{ current_search }}{% endif %}">{{ total_pages }}</a></li>
{% endif %}
<!-- Next -->
<li class="page-item {% if page == total_pages %}disabled{% endif %}">
<a class="page-link" href="?page={{ page + 1 }}&type={{ current_type }}{% if current_search %}&search={{ current_search }}{% endif %}">Next</a>
</li>
</ul>
</nav>
{% endif %}
{% else %}
<p>No messages found.</p>
{% endif %}