Changes for messages added.
This commit is contained in:
33
packetserver/http/routers/message_detail.py
Normal file
33
packetserver/http/routers/message_detail.py
Normal file
@@ -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
|
||||
}
|
||||
)
|
||||
@@ -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)
|
||||
@@ -157,3 +160,52 @@ async def mark_message_retrieved(
|
||||
transaction.get().commit()
|
||||
|
||||
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
|
||||
}
|
||||
)
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
<small class="text-light ms-3">(Close browser to logout)</small>
|
||||
</span>
|
||||
<a href="{{ url_for('profile_page') }}" class="btn btn-outline-light btn-sm me-2">Profile</a>
|
||||
<a href="/messages" class="btn btn-outline-light btn-sm me-2">Messages</a>
|
||||
<a href="/bulletins" class="btn btn-outline-light btn-sm me-2">Bulletins</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
40
packetserver/http/templates/message_detail.html
Normal file
40
packetserver/http/templates/message_detail.html
Normal file
@@ -0,0 +1,40 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Message {{ message.id }} - {{ current_user }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">Id</dt>
|
||||
<dd class="col-sm-10">{{ message.id }}</dd>
|
||||
|
||||
<dt class="col-sm-2">From</dt>
|
||||
<dd class="col-sm-10">{{ message.from }}</dd>
|
||||
|
||||
<dt class="col-sm-2">To</dt>
|
||||
<dd class="col-sm-10">{{ message.to | join(', ') }}</dd>
|
||||
|
||||
<dt class="col-sm-2">Date</dt>
|
||||
<dd class="col-sm-10">{{ message.sent_at[:10] }} {{ message.sent_at[11:19] }} UTC</dd>
|
||||
|
||||
<dt class="col-sm-2">Status</dt>
|
||||
<dd class="col-sm-10">
|
||||
{% if message.retrieved %}
|
||||
<span class="text-success">Read</span>
|
||||
{% else %}
|
||||
<span class="text-warning">Unread</span>
|
||||
{% endif %}
|
||||
</dd>
|
||||
|
||||
{% if message.has_attachments %}
|
||||
<dt class="col-sm-2">Attachments</dt>
|
||||
<dd class="col-sm-10 text-info">Has {{ message.attachments | length }} attachment(s) (not shown yet)</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
|
||||
<h3>Body</h3>
|
||||
<pre class="bg-light p-3 border">{{ message.text }}</pre>
|
||||
|
||||
<p class="nav-links">
|
||||
<a href="/dashboard">← Back to Dashboard</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
33
packetserver/http/templates/message_list.html
Normal file
33
packetserver/http/templates/message_list.html
Normal file
@@ -0,0 +1,33 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Messages - PacketServer{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Messages</h1>
|
||||
|
||||
<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>
|
||||
<a href="?msg_type=all" class="btn btn-sm {% if msg_type == 'all' %}btn-primary{% else %}btn-outline-primary{% endif %}">All</a>
|
||||
</div>
|
||||
|
||||
{% if messages %}
|
||||
<ul class="message-list">
|
||||
{% for msg in messages %}
|
||||
<li>
|
||||
<strong><a href="/dashboard/message/{{ msg.id }}">{{ msg.subject }}</a></strong>
|
||||
<span class="meta">
|
||||
From: {{ msg.from }} | To: {{ msg.to }} | {{ msg.sent_at[:10] }} {{ msg.sent_at[11:19] }}
|
||||
{% if not msg.retrieved %}<span class="text-warning"> (Unread)</span>{% endif %}
|
||||
{% if msg.has_attachments %}<span class="text-info"> (Attachments)</span>{% endif %}
|
||||
</span>
|
||||
<div class="preview">{{ msg.text_preview }}</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>No messages found.</p>
|
||||
{% endif %}
|
||||
|
||||
<p><a href="/dashboard">← Back to Dashboard</a></p>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user