From ce7a371cafc6ea11d7b6596f8b4feb8a05bc18aa Mon Sep 17 00:00:00 2001 From: Florian Heinz Date: Wed, 15 Apr 2026 13:34:12 +0200 Subject: [PATCH] fix: persist quick win reorder changes --- README.md | 5 ++++ app/routes/settings.py | 13 ++++++++--- app/static/js/app.js | 32 +++++--------------------- app/templates/settings/quick_wins.html | 7 ++++-- 4 files changed, 26 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 90fe01f..9e476ad 100644 --- a/README.md +++ b/README.md @@ -351,13 +351,18 @@ Der ausgegebene `VAPID_PRIVATE_KEY` ist bereits `.env`-freundlich mit escaped Ne - Quick-Wins als gemeinsames Team-Feature ausgebaut - neuer Optionen-Tab zum Anlegen und Verwalten gemeinsamer Quick-Wins - bestehende Quick-Wins in den Optionen direkt bearbeitbar gemacht +- Quick-Win-Reihenfolge per Drag & Drop ergänzt und Speichern der Sortierung in den Optionen stabilisiert - Plus-Dialog von Einzelkarten auf kompakte auswählbare Quick-Win-Chips umgestellt - mehrere Quick-Wins lassen sich gesammelt als erledigt speichern - „Sonstiges“ blendet Titel und Aufwand jetzt nur bei Auswahl ein - neue Aufwand-Stufe `super aufwendig` - Quick-Win-Popup visuell mit übernommenem Sparkles-Icon aus `heinz.marketing` aufgewertet +- gemeinsame Aufgaben für zwei Personen mit halbierten Punkten pro Person ergänzt +- Aufgabenstatus in `morgen fällig`, `übermorgen fällig` und `bald fällig` feiner aufgeteilt +- Aufgaben können jetzt von allen Nutzern direkt gelöscht werden - Kalenderdarstellung für lange deutsche Begriffe und Namen bei der Worttrennung nachgeschärft - deutsche Silbentrennung serverseitig vorbereitet, mit optionalem `pyphen`-Fallback ohne Startfehler im lokalen Dev-Setup +- mobile Layouts für Aufgabenkarten, Bearbeiten-Ansicht und Quick-Win-Verwaltung weiter verdichtet und ausgerichtet - Footer auf Versionslink, Herkunftshinweis und `hnz.io`-Verweis umgebaut - Cloudron-Version auf `0.6.5` angehoben diff --git a/app/routes/settings.py b/app/routes/settings.py index 0a9f507..4d5a6d7 100644 --- a/app/routes/settings.py +++ b/app/routes/settings.py @@ -274,8 +274,11 @@ def update_quick_win(quick_win_id: int): @login_required @csrf.exempt def reorder_quick_wins(): - payload = request.get_json(silent=True) or {} - raw_ids = payload.get("ids", []) + payload = request.get_json(silent=True) + if payload is not None: + raw_ids = payload.get("ids", []) + else: + raw_ids = request.form.get("ids", "").split(",") ordered_ids = [int(item) for item in raw_ids if str(item).isdigit()] quick_wins = QuickWin.query.filter_by(active=True).all() @@ -292,7 +295,11 @@ def reorder_quick_wins(): quick_win.sort_order = offset db.session.commit() - return jsonify({"ok": True}) + if payload is not None: + return jsonify({"ok": True}) + + flash("Die Quick-Win-Reihenfolge wurde gespeichert.", "success") + return redirect(url_for("settings.quick_wins")) @bp.route("/users//toggle-admin", methods=["POST"]) diff --git a/app/static/js/app.js b/app/static/js/app.js index e66cb76..a5764d3 100644 --- a/app/static/js/app.js +++ b/app/static/js/app.js @@ -17,7 +17,7 @@ const currentUserId = document.body.dataset.currentUserId; const currentUserName = document.body.dataset.currentUserName; const quickWinSortList = document.querySelector("[data-quick-win-sort-list]"); - const quickWinSortToken = document.getElementById("quickWinSortToken"); + const quickWinSortIds = document.getElementById("quickWinSortIds"); const quickWinSortSave = document.getElementById("quickWinSortSave"); const quickWinToggleButtons = document.querySelectorAll("[data-quick-win-toggle]"); let draggedQuickWin = null; @@ -123,22 +123,14 @@ }); } - async function persistQuickWinSort() { - if (!quickWinSortList || !quickWinSortToken) { + function syncQuickWinSortIds() { + if (!quickWinSortList || !quickWinSortIds) { return; } const ids = [...quickWinSortList.querySelectorAll("[data-quick-win-sort-item]")] .map((item) => item.dataset.quickWinSortItem) .filter(Boolean); - - await fetch("/settings/quick-wins/reorder", { - method: "POST", - headers: { - "Content-Type": "application/json", - "X-CSRFToken": quickWinSortToken.value, - }, - body: JSON.stringify({ ids }), - }); + quickWinSortIds.value = ids.join(","); } function setQuickWinSortDirty(isDirty) { @@ -149,6 +141,7 @@ } if (quickWinSortList) { + syncQuickWinSortIds(); setQuickWinSortDirty(false); quickWinSortList.querySelectorAll("[data-quick-win-sort-item]").forEach((item) => { @@ -180,25 +173,12 @@ } else { item.before(draggedQuickWin); } + syncQuickWinSortIds(); setQuickWinSortDirty(true); }); }); } - if (quickWinSortSave) { - quickWinSortSave.addEventListener("click", async () => { - if (!quickWinSortDirty) { - return; - } - try { - await persistQuickWinSort(); - setQuickWinSortDirty(false); - } catch (error) { - console.error("Quick-Win-Sortierung konnte nicht gespeichert werden", error); - } - }); - } - quickWinToggleButtons.forEach((button) => { button.addEventListener("click", () => { const targetId = button.dataset.target; diff --git a/app/templates/settings/quick_wins.html b/app/templates/settings/quick_wins.html index a5dfdab..69bc638 100644 --- a/app/templates/settings/quick_wins.html +++ b/app/templates/settings/quick_wins.html @@ -37,9 +37,12 @@

Direkt sichtbar

Aktive Quick-Wins bearbeiten

Per Drag & Drop kannst du die Reihenfolge festlegen, die später auch bei den Quick-Win-Chips erscheint.

- +
+ + +
- +
{% for quick_win in quick_wins %}