roundabout,
created on Sunday, 16 February 2025, 09:30:17 (1739698217),
received on Sunday, 16 February 2025, 09:30:20 (1739698220)
Author identity: vlad <vlad.muntoiu@gmail.com>
fd0d48ff70a8cfcca492622557ad363df1585044
app.py
@@ -904,6 +904,56 @@ def copy_picture(id):
return flask.redirect("/picture/" + str(new_resource.id))
@app.route("/picture/<int:id>/put-file")
def put_file(id):
resource = db.session.get(PictureResource, id)
if resource is None:
flask.abort(404)
current_user = db.session.get(User, flask.session.get("username"))
if current_user is None:
flask.abort(401)
if resource.author != current_user and not current_user.admin:
flask.abort(403)
return flask.render_template("put-file.html", resource=resource)
@app.route("/picture/<int:id>/put-file", methods=["POST"])
def put_file_post(id):
resource = db.session.get(PictureResource, id)
if resource is None:
flask.abort(404)
current_user = db.session.get(User, flask.session.get("username"))
if current_user is None:
flask.abort(401)
if resource.author != current_user and not current_user.admin:
flask.abort(403)
file = flask.request.files["file"]
if not file or not file.filename:
flask.flash("Select a file")
return flask.redirect(flask.request.url)
if not file.mimetype.startswith("image/") or file.mimetype == "image/svg+xml":
flask.flash("Only images are supported")
return flask.redirect(flask.request.url)
file_path = path.join(config.DATA_PATH, "pictures", str(resource.id))
print(file_path)
file.save(file_path)
pil_image = Image.open(file_path)
resource.width, resource.height = pil_image.size
pil_image = make_thumbnail(pil_image)
pil_image.save(path.join(config.DATA_PATH, "picture-thumbnails", str(resource.id)), **config.THUMBNAIL_SAVE_OPTIONS)
return flask.redirect("/picture/" + str(resource.id))
@app.route("/gallery/<int:id>/")
def gallery(id):
gallery = db.session.get(Gallery, id)
@@ -1696,6 +1746,35 @@ def api_delete_picture(id):
return flask.jsonify({"message": "Picture deleted successfully"})
@app.route("/api/picture/<int:id>/put-file", methods=["POST"])
def api_put_file(id):
resource = db.session.get(PictureResource, id)
if resource is None:
return flask.jsonify({"error": "Picture not found"}), 404
current_user = db.session.get(User, flask.session.get("username"))
if current_user is None:
return flask.jsonify({"error": "You must be logged in to edit pictures"}), 401
if resource.author != current_user and not current_user.admin:
return flask.jsonify({"error": "You are not the author of this picture"}), 403
file = flask.request.files["file"]
if not file or not file.filename:
return flask.jsonify({"error": "Provide a file"}), 400
if not file.mimetype.startswith("image/") or file.mimetype == "image/svg+xml":
return flask.jsonify({"error": "Only images are supported"}), 400
file_path = path.join(config.DATA_PATH, "pictures", str(resource.id))
file.save(file_path)
pil_image = Image.open(file_path)
resource.width, resource.height = pil_image.size
pil_image = make_thumbnail(pil_image)
pil_image.save(path.join(config.DATA_PATH, "picture-thumbnails", str(resource.id)), **config.THUMBNAIL_SAVE_OPTIONS)
return flask.jsonify({"message": "File uploaded successfully"})
@app.route("/api/picture/<int:id>/rate", methods=["POST"])
def api_rate_picture(id):
resource = db.session.get(PictureResource, id)
static/style.css
@@ -922,3 +922,9 @@ button, .button, input, select, textarea {
--color-button-hover: var(--color-error);
--color-button-active: var(--color-error);
}
input[type="file"] {
padding: 0.5rem;
display: flex;
font-style: italic;
}
templates/edit-picture.html
@@ -1,6 +1,6 @@
{% extends "default.html" %}
{% block nav_title %}Edit '{{ resource.title }}'{% endblock %}
{% block nav_title %}{{ resource.title }}{% endblock %}
{% block title %}Edit picture '{{ resource.title }}' | {{ site_name }}{% endblock %}
{% set back_url = "/picture/" + resource.id|string %}
templates/picture.html
@@ -55,8 +55,9 @@
<li><a href="/picture/{{ resource.id }}/edit-metadata">
<iconify-icon icon="mdi:edit"></iconify-icon>Edit metadata
</a></li>
{% endif %}
{% if have_permission %}
<li><a href="/picture/{{ resource.id }}/put-file">
<iconify-icon icon="mdi:file-upload"></iconify-icon>Replace image
</a></li>
<li><details>
<summary>
<iconify-icon icon="mdi:delete"></iconify-icon>Delete
templates/put-annotations-form.html
@@ -2,6 +2,8 @@
{% block nav_title %}{{ resource.title }}{% endblock %}
{% block title %}Submit JSON annotations for {{ resource.title }} | {{ site_name }}{% endblock %}
{% set back_url = "/picture/" + resource.id|string %}
{% block content %}
<x-frame style="--width: 768px">
<form method="POST" class="vbox">
templates/put-file.html
@@ -0,0 +1,20 @@
{% extends "default.html" %}
{% block nav_title %}{{ resource.title }}{% endblock %}
{% block title %}Replace {{ resource.title }} | {{ site_name }}{% endblock %}
{% set back_url = "/picture/" + resource.id|string %}
{% block content %}
<x-frame style="--width: 768px">
<form method="POST" class="vbox" enctype="multipart/form-data">
<p>
Change the picture <a href="/picture/{{ resource.id }}">{{ resource.title }}</a>.
</p>
<label>
<span class="required-asterisk">File</span>
<input type="file" name="file" required>
</label>
<button type="submit">Submit</button>
</form>
</x-frame>
{% endblock %}