Add csv-export and manual ISBN

This commit is contained in:
augustin64 2024-04-03 18:30:04 +02:00
parent cb8b6ab4fa
commit 6bffd45051
3 changed files with 57 additions and 10 deletions

27
app.py
View File

@ -1,4 +1,5 @@
from flask import Flask, render_template, redirect, url_for, request, abort, g from flask import Flask, render_template, redirect, request, g, flash
import secrets
import json import json
from book import Book from book import Book
@ -7,12 +8,16 @@ import isbn_db
app = Flask(__name__) app = Flask(__name__)
app.config["DATABASE"] = "data/books.sqlite" app.config["DATABASE"] = "data/books.sqlite"
app.config["SECRET_KEY"] = secrets.token_hex()
@app.route("/submit-isbn") @app.route("/submit-isbn")
def submit_isbn(): def submit_isbn():
if "isbn" not in request.args: if "isbn" not in request.args:
return "/submit-isbn?isbn=xxxxxx" return "/submit-isbn?isbn=xxxxxx"
if request.args["isbn"] == "":
return "Pas d'ISBN spécifié"
try: try:
book = Book(request.args["isbn"]) book = Book(request.args["isbn"])
except ValueError: except ValueError:
@ -29,6 +34,11 @@ def submit_isbn():
return f"{book.title} ajouté (plusieurs occurrences)" return f"{book.title} ajouté (plusieurs occurrences)"
return f"{book.title} ajouté" return f"{book.title} ajouté"
@app.route("/web-submit-isbn")
def web_submit_isbn():
flash(submit_isbn())
return redirect("/")
@app.route("/") @app.route("/")
def index(): def index():
return render_template("index.html", books=isbn_db.get_all_books()) return render_template("index.html", books=isbn_db.get_all_books())
@ -65,6 +75,21 @@ def update_book():
isbn_db.update_book(book) isbn_db.update_book(book)
return redirect("/") return redirect("/")
@app.route("/export-csv")
def export_csv():
books = isbn_db.get_all_books()
csv = "ISBN;Titre;Auteur;Éditeur;Date;Nombre\n"
for book in books:
csv += f"{book.isbn};{book.title};{book.author};{book.publisher};{book.publish_date};{book.count}\n"
# return as file with a good filename
return app.response_class(
csv,
mimetype="text/csv",
headers={"Content-Disposition": "attachment;filename=books.csv"}
)
@app.after_request @app.after_request
def after_request(response): def after_request(response):
"""Automatically close db after each request""" """Automatically close db after each request"""

View File

@ -1,4 +1,4 @@
@import url('/static/font/iosevka.css'); /*@import url('/static/font/iosevka.css');*/
/** Color Schemes */ /** Color Schemes */
/* Themes used: Catppuccin Latte & Moccha /* Themes used: Catppuccin Latte & Moccha
@ -32,6 +32,7 @@
--color-base: #1e1e2e; --color-base: #1e1e2e;
--color-mantle: #181825; --color-mantle: #181825;
--color-crust: #11111b; --color-crust: #11111b;
--color-action: #333d5d;
--font-family: Iosevka Web; --font-family: Iosevka Web;
} }
@ -64,6 +65,7 @@
--color-base: #eff1f5; --color-base: #eff1f5;
--color-mantle: #e6e9ef; --color-mantle: #e6e9ef;
--color-crust: #dce0e8; --color-crust: #dce0e8;
--color-action: #cdd6f4;
} }
} }
@ -183,7 +185,7 @@ input[type=number] {
padding-bottom: 10px; padding-bottom: 10px;
} }
button { button, input[type="submit"] {
color: inherit; color: inherit;
background-color: var(--color-crust); background-color: var(--color-crust);
border-color: var(--color-crust); border-color: var(--color-crust);
@ -192,9 +194,15 @@ button {
border-width: 2px; border-width: 2px;
padding: 5px; padding: 5px;
font-family: inherit; font-family: inherit;
width: unset;
} }
button:hover { dialog > button, dialog > form > input[type="submit"] {
background-color: var(--color-base);
border-color: var(--color-base);
}
button:hover, input[type="submit"]:hover {
border-color: var(--color-lavender); border-color: var(--color-lavender);
} }
@ -247,7 +255,7 @@ table {
margin: 3px; margin: 3px;
border-radius: 3px; border-radius: 3px;
box-shadow: 1px 2px 2px rgba(0, 0, 0, 0.2); box-shadow: 1px 2px 2px rgba(0, 0, 0, 0.2);
background-color: #cdd6f4; background-color: var(--color-action);
} }
th { th {
@ -263,7 +271,7 @@ table tr:nth-child(even) td{
dialog { dialog {
/* Geometry */ /* Geometry */
border-width: 2px; border-width: 1px;
border-radius: 3px; border-radius: 3px;
/* Colors */ /* Colors */
@ -272,3 +280,8 @@ dialog {
min-width: 75vw; min-width: 75vw;
} }
#add-book {
max-width: 300px;
margin: auto;
}

View File

@ -1,6 +1,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}Table{% endblock %} {% block title %}Liste des livres{% endblock %}
{% block header %} {% block header %}
<h1>Table des livres</h1> <h1>Table des livres</h1>
@ -20,7 +20,7 @@
<input type="text" id="edit-publisher" name="publisher"><br> <input type="text" id="edit-publisher" name="publisher"><br>
<label for="edit-quantity">Quantité:</label><br> <label for="edit-quantity">Quantité:</label><br>
<input type="number" id="edit-quantity" name="count"><br> <input type="number" id="edit-quantity" name="count"><br>
<button type="submit">Mettre à jour</button> <input type="submit" value="Mettre à jour">
</form> </form>
<button onclick="hideEditBookDialog()">Annuler</button> <button onclick="hideEditBookDialog()">Annuler</button>
</dialog> </dialog>
@ -29,10 +29,17 @@
<b id="delete-book-name">Nom du livre...</b> <b id="delete-book-name">Nom du livre...</b>
<form id="delete-book-form" action="/delete-book" method="post"> <form id="delete-book-form" action="/delete-book" method="post">
<input type="hidden" id="delete-isbn" value="" name="isbn"> <input type="hidden" id="delete-isbn" value="" name="isbn">
<button type="submit">Oui</button> <input type="submit" value="Oui">
</form> </form>
<button id="cancel-delete">Annuler</button> <button id="cancel-delete">Annuler</button>
</dialog> </dialog>
<div id="add-book">
Ajouter manuellement
<form action="web-submit-isbn">
<input type="text" name="isbn" placeholder="ISBN">
<input type="submit" value="Ajouter">
</form>
</div>
<table id="books-table"> <table id="books-table">
<tr> <tr>
<th>ISBN</th> <th>ISBN</th>
@ -50,7 +57,7 @@
<td><p {% if book.author == None %}class="red"{% endif %}>{{ book.author }}</p></td> <td><p {% if book.author == None %}class="red"{% endif %}>{{ book.author }}</p></td>
<td><p {% if book.publish_date == None %}class="red"{% endif %}>{{ book.publish_date }}</p></td> <td><p {% if book.publish_date == None %}class="red"{% endif %}>{{ book.publish_date }}</p></td>
<td><p {% if book.publisher == None %}class="red"{% endif %}>{{ book.publisher }}</p></td> <td><p {% if book.publisher == None %}class="red"{% endif %}>{{ book.publisher }}</p></td>
<td>{{ book.count }}</td> <td><p {% if book.count != 1 %}class="red"{% endif %}>{{ book.count }}</p></td>
<td> <td>
<button class="action" onclick="edit_book({{ book.isbn }})">✏️</button> <button class="action" onclick="edit_book({{ book.isbn }})">✏️</button>
<button class="action" onclick="delete_book({{ book.isbn }})">🗑️</button> <button class="action" onclick="delete_book({{ book.isbn }})">🗑️</button>
@ -58,4 +65,6 @@
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
<br/>
<a href="/export-csv" download="books.csv">Exporter en CSV</a>
{% endblock %} {% endblock %}