roundabout,
created on Saturday, 7 September 2024, 16:16:23 (1725725783),
received on Saturday, 7 September 2024, 16:16:28 (1725725788)
Author identity: vlad <vlad.muntoiu@gmail.com>
36f19e57c48ebef6a1ffbc30e21a519af8fe2bf5
app.py
@@ -110,9 +110,9 @@ with app.app_context():
resource = db.relationship("PictureResource", back_populates="licences")
licence = db.relationship("Licence", back_populates="pictures")
def __init__(self, resource_id, licence_id):
self.resource_id = resource_id
self.licence_id = licence_id
def __init__(self, resource, licence):
self.resource = resource
self.licence = licence
class Resource(db.Model):
@@ -223,7 +223,7 @@ with app.app_context():
db.session.add(self)
db.session.commit()
for licence_id in licence_ids:
joiner = PictureLicence(self.id, licence_id)
joiner = PictureLicence(self, db.session.get(Licence, licence_id))
db.session.add(joiner)
if replaces is not None:
self.replaces = replaces
@@ -554,6 +554,79 @@ def delete_picture(id):
return flask.redirect("/")
@app.route("/picture/<int:id>/edit-metadata")
def edit_picture(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)
licences = Licence.query.order_by(Licence.free.desc(), Licence.pinned.desc(), Licence.title).all()
types = PictureNature.query.all()
return flask.render_template("edit-picture.html", resource=resource, licences=licences, types=types,
PictureLicence=PictureLicence)
@app.route("/picture/<int:id>/edit-metadata", methods=["POST"])
def edit_picture_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)
title = flask.request.form["title"]
description = flask.request.form["description"]
origin_url = flask.request.form["origin_url"]
licence_ids = flask.request.form.getlist("licence")
nature_id = flask.request.form["nature"]
if not title:
flask.flash("Enter a title")
return flask.redirect(flask.request.url)
if not description:
description = ""
if not nature_id:
flask.flash("Select a picture type")
return flask.redirect(flask.request.url)
if not licence_ids:
flask.flash("Select licences")
return flask.redirect(flask.request.url)
licences = [db.session.get(Licence, licence_id) for licence_id in licence_ids]
if not any(licence.free for licence in licences):
flask.flash("Select at least one free licence")
return flask.redirect(flask.request.url)
resource.title = title
resource.description = description
resource.origin_url = origin_url
for licence_id in licence_ids:
joiner = PictureLicence(resource, db.session.get(Licence, licence_id))
db.session.add(joiner)
resource.nature = db.session.get(PictureNature, nature_id)
db.session.commit()
return flask.redirect("/picture/" + str(resource.id))
@app.route("/query-pictures", methods=["POST"]) # sadly GET can't have a body
def query_pictures():
offset = int(flask.request.args.get("offset", 0))
templates/edit-picture.html
@@ -0,0 +1,83 @@
{% extends "default.html" %}
{% block title %}Edit picture {{ resource.title }} | gigadata{% endblock %}
{% block content %}
<x-frame style="--width: 768px">
<h1>Editing: {{ resource.title }}</h1>
<p>{{ resource.description }}</p>
<p>
<a href="/picture/{{ resource.id }}/">Back</a>
</p>
<form class="vbox" method="POST">
<label>
<span class="required-asterisk">Title</span>
<input type="text" name="title" value="{{ resource.title }}" required>
</label>
<label>
Description
<textarea name="description">{{ resource.description }}</textarea>
</label>
<span class="required-asterisk">Picture type</span>
<div class="single-select" style="height: clamp(320px, 25vh, 640px)">
{% for type in types %}
<div class="image-type-selection">
<label>
<input name="nature" type="radio" value="{{ type.id }}" {% if type == resource.nature %}checked{% endif %} required>
<span class="image-type-title">
<span class="image-type-name">
{{ type.id }}
</span>
</span>
</label>
<div class="image-type-selection-info">
<p>{{ type.description | safe }}</p>
</div>
</div>
{% endfor %}
</div>
<label>
Origin URL
<input type="url" name="origin_url" value="{{ resource.origin_url }}">
Can be left blank if not applicable.
</label>
<span class="required-asterisk">Licences</span>
<div class="multi-select" style="height: clamp(320px, 50vh, 640px)">
{% for licence in licences %}
<div class="licence-selection">
<label>
<input name="licence" type="checkbox" value="{{ licence.id }}" {% if PictureLicence.query.filter_by(resource_id=resource.id, licence_id=licence.id).first() %}checked{% endif %}>
{% if licence.pinned %}
<iconify-icon icon="mdi:pin" title="Pinned">Pinned</iconify-icon>
{% endif %}
{% if not licence.free %}
<iconify-icon icon="mdi:ban" title="Non-free">Non-free</iconify-icon>
{% endif %}
<span class="licence-title">
<span class="licence-name">
[{{ licence.id }}]
{{ licence.title }}
</span>
{% if licence.url %}
<a href="{{ licence.url }}" target="_blank">More information</a>
{% endif %}
</span>
</label>
<div class="licence-selection-info">
{% if licence.logo_url %}
{% if licence.info_url %}
<a href="{{ licence.info_url }}" target="_blank" tabindex="-1"> {# An equivalent link already exists, only one is focusable #}
<img src="{{ licence.logo_url }}" alt="{{ licence.title }}" class="licence-logo">
</a>
{% else %}
<img src="{{ licence.logo_url }}" alt="{{ licence.title }}" class="licence-logo">
{% endif %}
{% endif %}
<p>{{ licence.description | safe }}</p>
</div>
</div>
{% endfor %}
</div>
<button type="submit">Save</button>
</form>
</x-frame>
{% endblock %}
templates/picture.html
@@ -17,7 +17,8 @@
<a href="/raw/picture/{{ resource.id }}" download="GigadataPicture_{{ resource.id }}{{ file_extension }}">Download</a> |
<a href="/picture/{{ resource.id }}/annotate">Annotate</a> |
<a href="/picture/{{ resource.id }}/put-annotations-form">Submit JSON annotations</a> |
<a href="/picture/{{ resource.id }}/get-annotations">Download annotations</a>
<a href="/picture/{{ resource.id }}/get-annotations">Download annotations</a> |
<a href="/picture/{{ resource.id }}/edit-metadata">Edit title or description</a>
</p>
<details>
<summary>Delete</summary>