Implement image upload functionality with metadata storage; update frontend to display uploaded images
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
+31
-1
@@ -4,6 +4,7 @@ import functools
|
||||
import httpx
|
||||
from flask import (
|
||||
Flask,
|
||||
Response,
|
||||
flash,
|
||||
jsonify,
|
||||
redirect,
|
||||
@@ -121,11 +122,27 @@ def dashboard():
|
||||
token = session["access_token"]
|
||||
resp = _api("GET", "/users/me", token=token)
|
||||
user = resp.json() if resp.status_code == 200 else {}
|
||||
return render_template("dashboard.html", user=user)
|
||||
img_resp = _api("GET", "/images/", token=token)
|
||||
images = img_resp.json() if img_resp.status_code == 200 else []
|
||||
return render_template("dashboard.html", user=user, images=images)
|
||||
|
||||
|
||||
# ── Generate ──────────────────────────────────────────────────────────────
|
||||
|
||||
@app.get("/images/<image_id>/file")
|
||||
@login_required
|
||||
def serve_uploaded_image(image_id: str):
|
||||
resp = _api("GET", f"/images/{image_id}/file",
|
||||
token=session["access_token"])
|
||||
if resp.status_code != 200:
|
||||
return Response("Not found", status=404)
|
||||
return Response(
|
||||
resp.content,
|
||||
status=200,
|
||||
content_type=resp.headers.get("content-type", "image/jpeg"),
|
||||
)
|
||||
|
||||
|
||||
@app.get("/generate")
|
||||
@login_required
|
||||
def generate():
|
||||
@@ -153,6 +170,19 @@ def generate_text():
|
||||
def generate_image():
|
||||
result = error = None
|
||||
if request.method == "POST":
|
||||
# Upload reference image if provided
|
||||
ref_file = request.files.get("reference_image")
|
||||
if ref_file and ref_file.filename:
|
||||
up_resp = _api(
|
||||
"POST", "/images/upload",
|
||||
token=session["access_token"],
|
||||
files={"file": (ref_file.filename,
|
||||
ref_file.stream, ref_file.content_type)},
|
||||
)
|
||||
if up_resp.status_code not in (200, 201):
|
||||
error = up_resp.json().get("detail", "Image upload failed.")
|
||||
return render_template("generate_image.html", result=result, error=error)
|
||||
|
||||
resp = _api("POST", "/generate/image", token=session["access_token"], json={
|
||||
"model": request.form.get("model", "").strip(),
|
||||
"prompt": request.form.get("prompt", "").strip(),
|
||||
|
||||
@@ -363,6 +363,25 @@ pre {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.image-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
||||
gap: 1rem;
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.image-grid-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.image-grid-item .generated-image {
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
/* ─── Admin table ──────────────────────────────────────── */
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
|
||||
@@ -5,4 +5,24 @@ endblock %} {% block content %}
|
||||
<p>Role: <strong>{{ user.get('role', 'user') }}</strong></p>
|
||||
<a href="{{ url_for('generate') }}" class="btn">Start generating</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% if images %}
|
||||
<div class="card mt-2">
|
||||
<h2>Uploaded reference images</h2>
|
||||
<div class="image-grid">
|
||||
{% for img in images %}
|
||||
<div class="image-grid-item">
|
||||
<img
|
||||
src="{{ url_for('serve_uploaded_image', image_id=img.id) }}"
|
||||
alt="{{ img.filename }}"
|
||||
class="generated-image"
|
||||
loading="lazy"
|
||||
/>
|
||||
<p class="text-muted" style="font-size: 0.75rem; margin-top: 0.25rem">
|
||||
{{ img.filename }} — {{ (img.size_bytes / 1024) | round(1) }} KB
|
||||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %} {% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user