diff --git a/the_works/static/the_works.css b/the_works/static/the_works.css index 36a121c..4a126ce 100644 --- a/the_works/static/the_works.css +++ b/the_works/static/the_works.css @@ -58,7 +58,6 @@ nav { border-color: var(--pico-primary-border); } - table.dataTable span.dt-column-order::before, table.dataTable span.dt-column-order::after { @@ -81,3 +80,7 @@ svg { content: " *"; color: #cf0000; } + +label:has([type="checkbox"]) { + width: 100%; +} \ No newline at end of file diff --git a/the_works/templates/views/text.html b/the_works/templates/views/text.html index db16c84..9c0fb15 100644 --- a/the_works/templates/views/text.html +++ b/the_works/templates/views/text.html @@ -1,4 +1,5 @@ {% extends 'base.html' %} +{% set SPLIT_CHARACTER = "|" %} {% block title %}Texte{% endblock title %} @@ -7,14 +8,17 @@ const SCRIPT_ROOT = {{ request.script_root | tojson }}; const textValues = ["Titel", "Untertitel"]; const selectValues = ["Reihe", "Textform", "Sprache"]; + const multiSelectValues = ["Genres"]; function showCreateModal() { // set modal heading document.getElementById("dialog-heading").textContent = "Text hinzufügen"; - // empty text inputs + // empty inputs for (const v of textValues) { document.getElementById(`form_${v}`).value = ""; } - // empty select inputs for (const v of selectValues) { document.getElementById(`form_${v}`).selectedIndex = ""; } + for (const v of multiSelectValues) { + document.getElementById(`form_${v}`).querySelectorAll("input[type=checkbox]").forEach( cb => { cb.checked = false; }) + } // set form action document.getElementById("form_submit").formAction = "{{ url_for('text.create') }}"; // show modal @@ -22,33 +26,24 @@ } function showUpdateModal() { - let id = this.dataset.id; - let url = `${SCRIPT_ROOT}/text/read/${id}`; - fetch(url) - // throw error if network error occurred, get JSON data otherwise - .then((response) => { - if (response.ok) { - return response.json(); + let tr = document.getElementById(`text-${this.dataset.id}`); + // set modal heading + document.getElementById("dialog-heading").textContent = "Text ansehen / bearbeiten"; + // populate inputs + for (const v of textValues) { document.getElementById(`form_${v}`).value = tr.querySelector(`[data-${v}]`).dataset[v.toLowerCase()]; } + for (const v of selectValues) { document.getElementById(`form_${v}`).selectedIndex = tr.querySelector(`[data-${v}]`).dataset[v.toLowerCase()]; } + for (const v of multiSelectValues) { + let data = tr.querySelector(`[data-${v}]`).dataset[v.toLowerCase()]; + if ( data ) { + for (const i of data.split("{{ SPLIT_CHARACTER }}")) { + document.getElementById(`form_${v}_${i}`).checked = true; } - throw new Error ("There was an error while fetching data for the text with ID " + id); - }) - // populate modal with response data and raise modal - .then( - function (response) { - console.log(response); - // set modal heading - document.getElementById("dialog-heading").textContent = "Text ansehen / bearbeiten"; - // populate text inputs - for (const v of textValues) { document.getElementById(`form_${v}`).value = response[v]; } - // populate select imputs - for (const v of selectValues) { document.getElementById(`form_${v}`).selectedIndex = response[v]; } - // set form action - document.getElementById("form_submit").formAction = `${SCRIPT_ROOT}/text/update/${id}`; - // show modal - document.getElementById("textmodal").showModal(); - } - ) - .catch((error) => console.log(error)); + } + } + // set form action + document.getElementById("form_submit").formAction = `${SCRIPT_ROOT}/text/update/${this.dataset.id}`; + // show modal + document.getElementById("textmodal").showModal(); } window.onload = function () { @@ -89,17 +84,19 @@ Reihe Textform Sprache + Genres Aktionen {% for text in texte %} - {{ text["Titel"] }} - {{ text["Untertitel"] }} - {{ text["Reihe"] }} - {{ text["Textform"] }} - {{ text["Sprache"] }} + {{ text["Titel"] }} + {{ text["Untertitel"] }} + {{ text["Reihe"] }} + {{ text["Textform"] }} + {{ text["Sprache"] }} + {{ text["Genre_list"] | join(SPLIT_CHARACTER) }} @@ -118,8 +115,8 @@
+
diff --git a/the_works/views/text.py b/the_works/views/text.py index 958b57d..da7731a 100644 --- a/the_works/views/text.py +++ b/the_works/views/text.py @@ -1,7 +1,8 @@ from flask import Blueprint, render_template, request, redirect, flash, url_for from sqlalchemy import select, insert, update, delete +from sqlalchemy.orm import joinedload from the_works.database import db -from the_works.models import Text, Reihe, Sprache, Textform +from the_works.models import Text, Reihe, Sprache, Textform, Text_Genre, Genre bp = Blueprint("text", __name__) @@ -9,10 +10,10 @@ bp = Blueprint("text", __name__) @bp.route("/text/all") def all(): # select all rows from table "Text", ORM style - rows = db.session.execute(select(Text, Reihe, Textform, Sprache).join(Text.reihe, isouter=True).join(Text.textform, isouter=True).join(Text.sprache, isouter=True)) + rows = db.session.execute(select(Text, Reihe, Textform, Sprache).join(Text.reihe, isouter=True).join(Text.textform, isouter=True).join(Text.sprache, isouter=True).options(joinedload(Text.text_genre))).unique() # condense result into list of dicts texte = [] - for row in rows: + for row in rows.all(): texte.append({ "id": row.Text.ID, "Titel": row.Text.Titel, @@ -22,9 +23,11 @@ def all(): "Textform": row.Textform.Textform, "tf_id": row.Text.Textform, "Sprache": row.Sprache.Sprache, - "s_id": row.Text.Sprache + "s_id": row.Text.Sprache, + "Genre_list": map(lambda tg: tg.genre.Genre, row.Text.text_genre) if row.Text.text_genre else [], + "g_id_list": map(lambda tg: tg.Genre, row.Text.text_genre) if row.Text.text_genre else [] }) - return render_template("views/text.html", texte=texte, reihen=db.session.scalars(select(Reihe)), textformen=db.session.scalars(select(Textform)), sprachen=db.session.scalars(select(Sprache))) + return render_template("views/text.html", texte=texte, reihen=db.session.scalars(select(Reihe)), textformen=db.session.scalars(select(Textform)), sprachen=db.session.scalars(select(Sprache)), genres=db.session.scalars(select(Genre))) @bp.route("/text/read/") def read(id): @@ -39,13 +42,16 @@ def read(id): @bp.route("/text/create", methods=["POST"]) def create(): - db.session.add(Text( + text = Text( Titel = request.form["form_Titel"], Untertitel = request.form["form_Untertitel"] or None, Reihe = request.form["form_Reihe"] or None, Textform = request.form["form_Textform"], Sprache = request.form["form_Sprache"] - )) + ) + for g in request.form.getlist("form_Genres"): + text.genres.append(g) + db.session.add(text) db.session.commit() flash("Eintrag erfolgreich hinzugefügt") return redirect(url_for("text.all")) @@ -60,6 +66,12 @@ def update(id): text.Reihe = request.form["form_Reihe"] or None text.Textform = request.form["form_Textform"] text.Sprache = request.form["form_Sprache"] + # update genre list by removing genres not in form selection and adding selected ones not currently in list + form_set = set(map(lambda g: int(g), request.form.getlist("form_Genres"))) + for g in set(text.genres) - form_set: + text.genres.remove(g) + for g in form_set - set(text.genres): + text.genres.append(g) # commit changes db.session.commit() flash("Eintrag erfolgreich geändert") @@ -72,4 +84,3 @@ def delete(id): db.session.commit() flash("Eintrag erfolgreich gelöscht") return redirect(url_for("text.all")) -