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 %}