From f59c9a36e3ac1dd5fb238c1c9cd9240057aa5a4b Mon Sep 17 00:00:00 2001 From: Michael Woods Date: Wed, 24 Dec 2025 20:38:28 -0500 Subject: [PATCH] Changes for messages added. --- packetserver/http/routers/message_detail.py | 33 +++++++++++ packetserver/http/routers/messages.py | 56 ++++++++++++++++++- packetserver/http/server.py | 4 ++ packetserver/http/templates/base.html | 2 + .../http/templates/message_detail.html | 40 +++++++++++++ packetserver/http/templates/message_list.html | 33 +++++++++++ 6 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 packetserver/http/routers/message_detail.py create mode 100644 packetserver/http/templates/message_detail.html create mode 100644 packetserver/http/templates/message_list.html diff --git a/packetserver/http/routers/message_detail.py b/packetserver/http/routers/message_detail.py new file mode 100644 index 0000000..55d0057 --- /dev/null +++ b/packetserver/http/routers/message_detail.py @@ -0,0 +1,33 @@ +from fastapi import APIRouter, Path, Request, Depends, HTTPException +from fastapi.responses import HTMLResponse + +from packetserver.http.dependencies import get_current_http_user +from packetserver.http.auth import HttpUser +from packetserver.http.server import templates + +router = APIRouter(tags=["message-detail"]) + +@router.get("/dashboard/message/{msg_id}", response_class=HTMLResponse) +async def message_detail_page( + request: Request, + msg_id: str = Path(..., description="Message UUID as string"), + current_user: HttpUser = Depends(get_current_http_user) +): + # Reuse the existing API endpoint logic internally + from packetserver.http.routers.messages import get_message as api_get_message + + # Call with mark_retrieved=True to auto-mark as read on view (optional—remove if you prefer manual) + message_data = await api_get_message( + msg_id=msg_id, + mark_retrieved=True, + current_user=current_user + ) + + return templates.TemplateResponse( + "message_detail.html", + { + "request": request, + "message": message_data, + "current_user": current_user.username + } + ) \ No newline at end of file diff --git a/packetserver/http/routers/messages.py b/packetserver/http/routers/messages.py index 328dd28..7d4c8ce 100644 --- a/packetserver/http/routers/messages.py +++ b/packetserver/http/routers/messages.py @@ -1,5 +1,6 @@ # packetserver/http/routers/messages.py -from fastapi import APIRouter, Depends, Query, HTTPException, Path +from fastapi import APIRouter, Depends, Query, HTTPException, Path, Request +from fastapi.responses import HTMLResponse from typing import Optional from datetime import datetime from persistent.mapping import PersistentMapping @@ -10,6 +11,8 @@ from pydantic import BaseModel, Field, validator from packetserver.http.dependencies import get_current_http_user from packetserver.http.auth import HttpUser + +html_router = APIRouter(tags=["messages-html"]) router = APIRouter(prefix="/api/v1", tags=["messages"]) # Simple request model (only allow setting to true) @@ -156,4 +159,53 @@ async def mark_message_retrieved( mailbox._p_changed = True transaction.get().commit() - return {"status": "marked_retrieved", "id": msg_id} \ No newline at end of file + return {"status": "marked_retrieved", "id": msg_id} + +@html_router.get("/messages", response_class=HTMLResponse) +async def message_list_page( + request: Request, + msg_type: str = Query("all", description="Filter: received, sent, or all"), + limit: Optional[int] = Query(50, le=200), + current_user: HttpUser = Depends(get_current_http_user) +): + # Reuse the existing API endpoint logic directly (duplicate minimal code for simplicity) + from packetserver.runners.http_server import get_db_connection + from ..server import templates + + conn = get_db_connection() + root = conn.root() + mailbox = root.get("mailbox", []) + + # Filter based on type + if msg_type == "received": + filtered = [m for m in mailbox if current_user.username.upper() in [t.upper() for t in m.to]] + elif msg_type == "sent": + filtered = [m for m in mailbox if m.from_call.upper() == current_user.username.upper()] + else: # all + filtered = mailbox + + # Sort newest first + filtered.sort(key=lambda m: m.sent_at, reverse=True) + + messages = [] + for msg in filtered[:limit]: + messages.append({ + "id": msg.msg_id, + "from": msg.from_call, + "to": ", ".join(msg.to), + "subject": msg.subject or "(no subject)", + "text_preview": msg.text[:100] + ("..." if len(msg.text) > 100 else ""), + "sent_at": msg.sent_at.isoformat() + "Z", + "retrieved": getattr(msg, "retrieved", False), + "has_attachments": bool(getattr(msg, "attachments", [])) + }) + + return templates.TemplateResponse( + "message_list.html", + { + "request": request, + "messages": messages, + "msg_type": msg_type, + "current_user": current_user.username + } + ) \ No newline at end of file diff --git a/packetserver/http/server.py b/packetserver/http/server.py index 59460bb..99560ca 100644 --- a/packetserver/http/server.py +++ b/packetserver/http/server.py @@ -36,6 +36,8 @@ app.mount("/static", StaticFiles(directory=BASE_DIR / "static"), name="static") # Now safe to import dashboard (it needs templates) from .routers import dashboard, bulletins +from .routers.message_detail import router as message_detail_router +from .routers.messages import html_router # Include routers app.include_router(public.router) @@ -45,4 +47,6 @@ app.include_router(send.router) app.include_router(dashboard.router) app.include_router(bulletins.router) app.include_router(bulletins.html_router) +app.include_router(message_detail_router) +app.include_router(messages.html_router) diff --git a/packetserver/http/templates/base.html b/packetserver/http/templates/base.html index 4247cc6..6b4618b 100644 --- a/packetserver/http/templates/base.html +++ b/packetserver/http/templates/base.html @@ -17,6 +17,8 @@ (Close browser to logout) Profile + Messages + Bulletins diff --git a/packetserver/http/templates/message_detail.html b/packetserver/http/templates/message_detail.html new file mode 100644 index 0000000..e3eb1dc --- /dev/null +++ b/packetserver/http/templates/message_detail.html @@ -0,0 +1,40 @@ +{% extends "base.html" %} + +{% block title %}Message {{ message.id }} - {{ current_user }}{% endblock %} + +{% block content %} +
+
Id
+
{{ message.id }}
+ +
From
+
{{ message.from }}
+ +
To
+
{{ message.to | join(', ') }}
+ +
Date
+
{{ message.sent_at[:10] }} {{ message.sent_at[11:19] }} UTC
+ +
Status
+
+ {% if message.retrieved %} + Read + {% else %} + Unread + {% endif %} +
+ + {% if message.has_attachments %} +
Attachments
+
Has {{ message.attachments | length }} attachment(s) (not shown yet)
+ {% endif %} +
+ +

Body

+
{{ message.text }}
+ + +{% endblock %} \ No newline at end of file diff --git a/packetserver/http/templates/message_list.html b/packetserver/http/templates/message_list.html new file mode 100644 index 0000000..88f8a45 --- /dev/null +++ b/packetserver/http/templates/message_list.html @@ -0,0 +1,33 @@ +{% extends "base.html" %} + +{% block title %}Messages - PacketServer{% endblock %} + +{% block content %} +

Messages

+ +
+ Received + Sent + All +
+ +{% if messages %} + +{% else %} +

No messages found.

+{% endif %} + +

← Back to Dashboard

+{% endblock %} \ No newline at end of file