From 50de359838b8060e9a6c251c3d00b6260523ebf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Wed, 30 Jul 2025 23:57:22 +0200 Subject: [PATCH] masowa edycja kategorii, crop dla usera i poprawki w zapytaniach --- app.py | 31 +++++++++-- static/js/admin_mass_categories.js | 11 ++++ templates/admin/admin_panel.html | 12 ++-- templates/admin/mass_edit_categories.html | 67 +++++++++++++++++++++++ templates/base.html | 4 +- templates/edit_my_list.html | 2 +- 6 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 static/js/admin_mass_categories.js create mode 100644 templates/admin/mass_edit_categories.html diff --git a/app.py b/app.py index cae6097..f419a96 100644 --- a/app.py +++ b/app.py @@ -1143,7 +1143,8 @@ def main_page(): # ostatnia kwota (w tym przypadku max = suma z ostatniego zapisu) latest_expenses_map = dict( db.session.query( - Expense.list_id, func.coalesce(func.max(Expense.amount), 0) + Expense.list_id, + func.coalesce(func.sum(Expense.amount), 0) ) .filter(Expense.list_id.in_(all_ids)) .group_by(Expense.list_id) @@ -1907,21 +1908,21 @@ def admin_panel(): .group_by(Item.list_id) .all() ) - stats_map = { s.list_id: (s.total_count or 0, s.purchased_count or 0) for s in stats } - # Pobranie ostatnich kwot dla wszystkich list w jednym zapytaniu latest_expenses_map = dict( db.session.query( - Expense.list_id, func.coalesce(func.max(Expense.amount), 0) + Expense.list_id, + func.coalesce(func.sum(Expense.amount), 0) ) .filter(Expense.list_id.in_(all_ids)) .group_by(Expense.list_id) .all() ) + enriched_lists = [] for l in all_lists: total_count, purchased_count = stats_map.get(l.id, (0, 0)) @@ -2024,6 +2025,7 @@ def admin_panel(): ) + @app.route("/admin/delete_list/") @login_required @admin_required @@ -2634,6 +2636,27 @@ def recalculate_filesizes_all(): return redirect(url_for("admin_receipts", id="all")) +@app.route("/admin/mass_edit_categories", methods=["GET", "POST"]) +@login_required +@admin_required +def admin_mass_edit_categories(): + lists = ShoppingList.query.options(joinedload(ShoppingList.categories)).order_by(ShoppingList.created_at.desc()).all() + categories = Category.query.order_by(Category.name.asc()).all() + + if request.method == "POST": + for lst in lists: + selected_ids = request.form.getlist(f"categories_{lst.id}") + lst.categories.clear() + if selected_ids: + cats = Category.query.filter(Category.id.in_(selected_ids)).all() + lst.categories.extend(cats) + db.session.commit() + flash("Zaktualizowano kategorie dla wybranych list", "success") + return redirect(url_for("admin_mass_edit_categories")) + + return render_template("admin/mass_edit_categories.html", lists=lists, categories=categories) + + @app.route("/healthcheck") def healthcheck(): header_token = request.headers.get("X-Internal-Check") diff --git a/static/js/admin_mass_categories.js b/static/js/admin_mass_categories.js new file mode 100644 index 0000000..7e1f2fd --- /dev/null +++ b/static/js/admin_mass_categories.js @@ -0,0 +1,11 @@ +document.addEventListener("DOMContentLoaded", function () { + document.querySelectorAll('select[multiple]').forEach(function (el) { + new TomSelect(el, { + plugins: ['remove_button'], + placeholder: 'Wybierz kategorie...', + create: false, + sortField: { field: "text", direction: "asc" }, + dropdownParent: 'body' + }); + }); +}); \ No newline at end of file diff --git a/templates/admin/admin_panel.html b/templates/admin/admin_panel.html index c8fdce5..0d777be 100644 --- a/templates/admin/admin_panel.html +++ b/templates/admin/admin_panel.html @@ -18,14 +18,18 @@ @@ -195,7 +199,7 @@ }); - + {% endblock %}
diff --git a/templates/admin/mass_edit_categories.html b/templates/admin/mass_edit_categories.html new file mode 100644 index 0000000..ffbca7f --- /dev/null +++ b/templates/admin/mass_edit_categories.html @@ -0,0 +1,67 @@ +{% extends 'base.html' %} +{% block title %}Masowa edycja kategorii{% endblock %} +{% block content %} + +
+

🗂 Masowa edycja kategorii list

+
+ ← Powrót do panelu +
+
+ +
+
+
+
+ + + + + + + + + + + + {% for lst in lists %} + + + + + + + + {% endfor %} + +
IDNazwa listyWłaścicielData utworzeniaKategorie
{{ lst.id }}{{ lst.title }}{{ lst.owner.username if lst.owner else "?" }}{{ lst.created_at.strftime('%Y-%m-%d') }} + +
+
+
+
+ +
+ +
+
+ +{% endblock %} +{% block scripts %} + + + + +{% endblock %} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index fd89dbd..51f1c50 100644 --- a/templates/base.html +++ b/templates/base.html @@ -15,7 +15,7 @@ {% if '/admin/receipts' in request.path or '/edit_my_list' in request.path %} {% endif %} - {% if '/edit_my_list' or '/admin/edit_list' in request.path %} + {% if '/edit_my_list' or '/admin/edit_list' in request.path or '/admin/mass_edit_categories' %} {% endif %} @@ -106,7 +106,7 @@ {% if '/admin/receipts' in request.path or '/edit_my_list' in request.path %} {% endif %} - {% if '/edit_my_list' or '/admin/edit_list' in request.path %} + {% if '/edit_my_list' or '/admin/edit_list' or '/admin/mass_edit_categories' in request.path %} {% endif %} diff --git a/templates/edit_my_list.html b/templates/edit_my_list.html index 99960f9..55c3471 100644 --- a/templates/edit_my_list.html +++ b/templates/edit_my_list.html @@ -100,7 +100,7 @@ 🔄 Obróć o 90° - ✂️ Przytnij