Adding objects dashboard.
This commit is contained in:
31
packetserver/http/routers/objects_html.py
Normal file
31
packetserver/http/routers/objects_html.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
from fastapi import APIRouter, Depends, Request, Form, File, UploadFile
|
||||||
|
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||||
|
from packetserver.http.dependencies import get_current_http_user
|
||||||
|
from packetserver.http.auth import HttpUser
|
||||||
|
from packetserver.http.server import templates
|
||||||
|
from packetserver.http.routers.objects import router as api_router # to call internal endpoints
|
||||||
|
from packetserver.http.database import DbDependency
|
||||||
|
|
||||||
|
router = APIRouter(tags=["objects_html"])
|
||||||
|
|
||||||
|
# Internal reference to the list function (assuming it's list_my_objects)
|
||||||
|
from packetserver.http.routers.objects import list_my_objects as api_list_objects
|
||||||
|
|
||||||
|
@router.get("/objects", response_class=HTMLResponse)
|
||||||
|
async def objects_page(
|
||||||
|
db: DbDependency,
|
||||||
|
request: Request,
|
||||||
|
current_user: HttpUser = Depends(get_current_http_user)
|
||||||
|
):
|
||||||
|
# Call the API list endpoint internally
|
||||||
|
objects_resp = await api_list_objects(db, current_user=current_user) # db injected via dependency
|
||||||
|
objects = objects_resp # it's already the list
|
||||||
|
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
"objects.html",
|
||||||
|
{
|
||||||
|
"request": request,
|
||||||
|
"current_user": current_user.username,
|
||||||
|
"objects": objects
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -43,6 +43,7 @@ from .routers import dashboard, bulletins
|
|||||||
from .routers.message_detail import router as message_detail_router
|
from .routers.message_detail import router as message_detail_router
|
||||||
from .routers.messages import html_router
|
from .routers.messages import html_router
|
||||||
from .routers.objects import router as objects_router
|
from .routers.objects import router as objects_router
|
||||||
|
from .routers import objects_html
|
||||||
|
|
||||||
# initialize database
|
# initialize database
|
||||||
init_db()
|
init_db()
|
||||||
@@ -58,5 +59,6 @@ app.include_router(bulletins.html_router)
|
|||||||
app.include_router(message_detail_router)
|
app.include_router(message_detail_router)
|
||||||
app.include_router(html_router)
|
app.include_router(html_router)
|
||||||
app.include_router(objects_router)
|
app.include_router(objects_router)
|
||||||
|
app.include_router(objects_html.router)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
<a href="{{ url_for('profile_page') }}" class="btn btn-outline-light btn-sm me-2">Profile</a>
|
<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="/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>
|
<a href="/bulletins" class="btn btn-outline-light btn-sm me-2">Bulletins</a>
|
||||||
|
<a href="/objects" class="btn btn-outline-light btn-sm me-2">Objects</a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|||||||
99
packetserver/http/templates/objects.html
Normal file
99
packetserver/http/templates/objects.html
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}My Objects - {{ current_user }}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2 class="mb-4">My Objects</h2>
|
||||||
|
|
||||||
|
<!-- Simple File Upload Form -->
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5>Upload File</h5>
|
||||||
|
<form action="/api/v1/objects" method="post" enctype="multipart/form-data">
|
||||||
|
<div class="mb-3">
|
||||||
|
<input type="file" name="file" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<input type="text" name="name" class="form-control" placeholder="Optional name">
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-3">
|
||||||
|
<input type="checkbox" name="private" class="form-check-input" checked>
|
||||||
|
<label class="form-check-label">Private</label>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Upload</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Quick Text Object -->
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5>Create Text Object</h5>
|
||||||
|
<form action="/api/v1/objects/text" method="post">
|
||||||
|
<div class="mb-3">
|
||||||
|
<textarea name="text" class="form-control" rows="4" placeholder="Enter text content..." required></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<input type="text" name="name" class="form-control" placeholder="Optional name (e.g. note.txt)">
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-3">
|
||||||
|
<input type="checkbox" name="private" class="form-check-input" checked>
|
||||||
|
<label class="form-check-label">Private</label>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-success">Create</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Objects Table -->
|
||||||
|
{% if objects %}
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead class="table-dark">
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Size</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Uploaded</th>
|
||||||
|
<th>Visibility</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for obj in objects %}
|
||||||
|
<tr>
|
||||||
|
<td><strong>{{ obj.name }}</strong></td>
|
||||||
|
<td>{{ "%0.1f KB" | format(obj.size / 1024) if obj.size > 1024 else obj.size ~ " bytes" }}</td>
|
||||||
|
<td>
|
||||||
|
{% if obj.binary %}
|
||||||
|
<span class="badge bg-secondary">Binary</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-info">Text</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>{{ obj.created_at[:10] }}</td>
|
||||||
|
<td>
|
||||||
|
{% if obj.private %}
|
||||||
|
<span class="badge bg-warning">Private</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-success">Public</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if not obj.binary %}
|
||||||
|
<a href="/api/v1/objects/{{ obj.uuid }}/text" class="btn btn-sm btn-outline-info" target="_blank">View Text</a>
|
||||||
|
{% endif %}
|
||||||
|
<a href="/api/v1/objects/{{ obj.uuid }}/download" class="btn btn-sm btn-primary">Download</a>
|
||||||
|
<form action="/api/v1/objects/{{ obj.uuid }}" method="post" style="display:inline;">
|
||||||
|
<input type="hidden" name="_method" value="DELETE">
|
||||||
|
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Delete {{ obj.name }}?')">Delete</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
<p>No objects uploaded yet.</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user