Add image upload preview functionality; update titles and templates for consistency
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -18,6 +18,28 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Image upload preview ───────────────────────────────
|
||||||
|
const imageInput = document.getElementById("reference_image");
|
||||||
|
const imagePreviewWrap = document.getElementById("image-upload-preview");
|
||||||
|
const imagePreview = document.getElementById("image-upload-preview-img");
|
||||||
|
const imageFilename = document.getElementById("image-upload-filename");
|
||||||
|
|
||||||
|
if (imageInput && imagePreviewWrap && imagePreview && imageFilename) {
|
||||||
|
imageInput.addEventListener("change", () => {
|
||||||
|
const file = imageInput.files && imageInput.files[0];
|
||||||
|
if (!file) {
|
||||||
|
imagePreviewWrap.hidden = true;
|
||||||
|
imagePreview.removeAttribute("src");
|
||||||
|
imageFilename.textContent = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
imagePreview.src = URL.createObjectURL(file);
|
||||||
|
imageFilename.textContent = file.name;
|
||||||
|
imagePreviewWrap.hidden = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// ── Generate dropdown tabs ─────────────────────────────
|
// ── Generate dropdown tabs ─────────────────────────────
|
||||||
document.querySelectorAll(".tab-btn").forEach((btn) => {
|
document.querySelectorAll(".tab-btn").forEach((btn) => {
|
||||||
btn.addEventListener("click", () => {
|
btn.addEventListener("click", () => {
|
||||||
|
|||||||
@@ -359,6 +359,10 @@ pre {
|
|||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-upload-preview {
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* ─── Admin table ──────────────────────────────────────── */
|
/* ─── Admin table ──────────────────────────────────────── */
|
||||||
.stats-grid {
|
.stats-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %} {% block title %}Admin — AI Allucanget{% endblock %}
|
{% extends "base.html" %} {% block title %}Admin — All You Can GET AI{% endblock
|
||||||
{% block content %}
|
%} {% block content %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h1>Admin Dashboard</h1>
|
<h1>Admin Dashboard</h1>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>{% block title %}AI Allucanget{% endblock %}</title>
|
<title>{% block title %}All You Can GET AI{% endblock %}</title>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="{{ url_for('static', filename='style.css') }}"
|
href="{{ url_for('static', filename='style.css') }}"
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<nav>
|
<nav>
|
||||||
<a href="{{ url_for('index') }}" class="brand">AI Allucanget</a>
|
<a href="{{ url_for('index') }}" class="brand">All You Can GET AI</a>
|
||||||
|
|
||||||
<button class="hamburger" aria-label="Open menu">
|
<button class="hamburger" aria-label="Open menu">
|
||||||
<span></span><span></span><span></span>
|
<span></span><span></span><span></span>
|
||||||
@@ -22,14 +22,9 @@
|
|||||||
{% if session.get('access_token') %}
|
{% if session.get('access_token') %}
|
||||||
<a href="{{ url_for('dashboard') }}">Dashboard</a>
|
<a href="{{ url_for('dashboard') }}">Dashboard</a>
|
||||||
|
|
||||||
<div class="nav-dropdown">
|
<a href="{{ url_for('generate_text') }}">Generate Text</a>
|
||||||
<a href="{{ url_for('generate_text') }}">Generate ▾</a>
|
<a href="{{ url_for('generate_image') }}">Generate Image</a>
|
||||||
<div class="nav-dropdown-menu">
|
<a href="{{ url_for('generate_video') }}">Generate Video</a>
|
||||||
<a href="{{ url_for('generate_text') }}">Text</a>
|
|
||||||
<a href="{{ url_for('generate_image') }}">Image</a>
|
|
||||||
<a href="{{ url_for('generate_video') }}">Video</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a href="{{ url_for('profile') }}">Profile</a>
|
<a href="{{ url_for('profile') }}">Profile</a>
|
||||||
{% if session.get('user_role') == 'admin' %}
|
{% if session.get('user_role') == 'admin' %}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %} {% block title %}Dashboard — All You Can GET AI{%
|
||||||
{% block title %}Dashboard — AI Allucanget{% endblock %}
|
endblock %} {% block content %}
|
||||||
{% block content %}
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h1>Welcome{% if user.get('email') %}, {{ user.email }}{% endif %}</h1>
|
<h1>Welcome{% if user.get('email') %}, {{ user.email }}{% endif %}</h1>
|
||||||
<p>Role: <strong>{{ user.get('role', 'user') }}</strong></p>
|
<p>Role: <strong>{{ user.get('role', 'user') }}</strong></p>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %} {% block title %}Generate — AI Allucanget{% endblock
|
{% extends "base.html" %} {% block title %}Generate — All You Can GET AI{%
|
||||||
%} {% block content %}
|
endblock %} {% block content %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h1>Generate</h1>
|
<h1>Generate</h1>
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}Image Generation — AI Allucanget{% endblock %}
|
{% block title %}Image Generation — All You Can GET AI{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h1>Image Generation</h1>
|
<h1>Image Generation</h1>
|
||||||
<form method="post">
|
<form method="post" enctype="multipart/form-data">
|
||||||
<label for="model">Model</label>
|
<label for="model">Model</label>
|
||||||
<input id="model" name="model" type="text" required
|
<input id="model" name="model" type="text" required
|
||||||
placeholder="e.g. openai/dall-e-3"
|
placeholder="e.g. openai/dall-e-3"
|
||||||
@@ -49,6 +49,21 @@
|
|||||||
<option value="4" {% if request.form.get('n')=='4' %}selected{% endif %}>4</option>
|
<option value="4" {% if request.form.get('n')=='4' %}selected{% endif %}>4</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<label for="reference_image">Reference image (optional)</label>
|
||||||
|
<input
|
||||||
|
id="reference_image"
|
||||||
|
name="reference_image"
|
||||||
|
type="file"
|
||||||
|
accept="image/png,image/jpeg,image/webp,image/gif"
|
||||||
|
>
|
||||||
|
<p class="text-muted mt-1" id="reference-image-help">
|
||||||
|
Upload image for visual reference in upcoming image-to-image flow.
|
||||||
|
</p>
|
||||||
|
<div class="image-upload-preview" id="image-upload-preview" hidden>
|
||||||
|
<p class="text-muted" id="image-upload-filename"></p>
|
||||||
|
<img id="image-upload-preview-img" alt="Uploaded reference image preview" class="generated-image">
|
||||||
|
</div>
|
||||||
|
|
||||||
<button type="submit">Generate image</button>
|
<button type="submit">Generate image</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %} {% block title %}Text Generation — AI Allucanget{%
|
{% extends "base.html" %} {% block title %}Text Generation — All You Can GET
|
||||||
endblock %} {% block content %}
|
AI{% endblock %} {% block content %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h1>Text Generation</h1>
|
<h1>Text Generation</h1>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %} {% block title %}Video Generation — AI Allucanget{%
|
{% extends "base.html" %} {% block title %}Video Generation — All You Can GET
|
||||||
endblock %} {% block content %}
|
AI{% endblock %} {% block content %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h1>Video Generation</h1>
|
<h1>Video Generation</h1>
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %} {% block title %}Log in — All You Can GET AI{%
|
||||||
{% block title %}Log in — AI Allucanget{% endblock %}
|
endblock %} {% block content %}
|
||||||
{% block content %}
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h1>Log in</h1>
|
<h1>Log in</h1>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<label for="email">Email</label>
|
<label for="email">Email</label>
|
||||||
<input id="email" name="email" type="email" required autofocus>
|
<input id="email" name="email" type="email" required autofocus />
|
||||||
|
|
||||||
<label for="password">Password</label>
|
<label for="password">Password</label>
|
||||||
<input id="password" name="password" type="password" required>
|
<input id="password" name="password" type="password" required />
|
||||||
|
|
||||||
<button type="submit">Log in</button>
|
<button type="submit">Log in</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %} {% block title %}Profile — AI Allucanget{% endblock %}
|
{% extends "base.html" %} {% block title %}Profile — All You Can GET AI{%
|
||||||
{% block content %}
|
endblock %} {% block content %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h1>Your Profile</h1>
|
<h1>Your Profile</h1>
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %} {% block title %}Register — All You Can GET AI{%
|
||||||
{% block title %}Register — AI Allucanget{% endblock %}
|
endblock %} {% block content %}
|
||||||
{% block content %}
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h1>Create account</h1>
|
<h1>Create account</h1>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<label for="email">Email</label>
|
<label for="email">Email</label>
|
||||||
<input id="email" name="email" type="email" required autofocus>
|
<input id="email" name="email" type="email" required autofocus />
|
||||||
|
|
||||||
<label for="password">Password</label>
|
<label for="password">Password</label>
|
||||||
<input id="password" name="password" type="password" required minlength="8">
|
<input
|
||||||
|
id="password"
|
||||||
|
name="password"
|
||||||
|
type="password"
|
||||||
|
required
|
||||||
|
minlength="8"
|
||||||
|
/>
|
||||||
|
|
||||||
<button type="submit">Register</button>
|
<button type="submit">Register</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -196,6 +196,7 @@ def test_generate_image_page_renders(client):
|
|||||||
resp = client.get("/generate/image")
|
resp = client.get("/generate/image")
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
assert b"Image Generation" in resp.data
|
assert b"Image Generation" in resp.data
|
||||||
|
assert b"reference_image" in resp.data
|
||||||
|
|
||||||
|
|
||||||
def test_generate_image_success(client):
|
def test_generate_image_success(client):
|
||||||
|
|||||||
Reference in New Issue
Block a user