Auditlog: Statistik-Kacheln zeigen geladen/gesamt (weiterhin v1.1.9)
Alle vier Kacheln (Alle, Hinzufuegen, Aenderungen, Loeschungen) zeigen jetzt "geladen / gesamt" (z.B. "300 / 466"), solange noch nicht alles geladen ist -- Gesamtzahlen je Kategorie kommen aus einer einzigen aggregierten SQL-Abfrage (SUM/CASE ueber die bestehenden LIKE-Muster von category_of), nicht aus einem vollstaendigen Tabellen-Scan. Sobald alles geladen ist, wird wieder nur die reine Zahl angezeigt (client- wie serverseitig identische Formatierungslogik). Dieser Fix wird per Nutzervorgabe unter der GLEICHEN Releasnummer v1.1.9 ausgeliefert (Tag wird bewusst weitergezogen statt neu vergeben, da v1.1.9 zum Zeitpunkt dieses Commits zwar schon getaggt, aber die Kachel-Anzeige noch nicht ausgereift war). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+17
-1
@@ -7727,13 +7727,29 @@ def activity_log():
|
||||
"SELECT id, ts, username, action, target, details FROM audit_log ORDER BY id DESC LIMIT ?",
|
||||
(AUDIT_LOG_PAGE_SIZE,),
|
||||
).fetchall()
|
||||
total_count = conn.execute("SELECT COUNT(*) AS n FROM audit_log").fetchone()["n"]
|
||||
# Gesamtzahlen je Kategorie (nicht nur der geladenen Zeilen) für die
|
||||
# "X / Y geladen"-Anzeige in den Statistik-Kacheln -- eine einzige
|
||||
# aggregierte Abfrage statt die komplette Tabelle einzulesen. Die
|
||||
# LIKE-Muster bilden exakt dieselbe Kategorisierung wie category_of()
|
||||
# in _audit_log_macros.html ab (kind = action.split(".")[-1]).
|
||||
totals_row = conn.execute(
|
||||
"SELECT COUNT(*) AS total, "
|
||||
"SUM(CASE WHEN action LIKE '%.create' OR action LIKE '%.upload' OR action LIKE '%.mkdir' THEN 1 ELSE 0 END) AS create_n, "
|
||||
"SUM(CASE WHEN action LIKE '%.delete' THEN 1 ELSE 0 END) AS delete_n "
|
||||
"FROM audit_log"
|
||||
).fetchone()
|
||||
conn.close()
|
||||
|
||||
total_count = totals_row["total"] or 0
|
||||
total_create = totals_row["create_n"] or 0
|
||||
total_delete = totals_row["delete_n"] or 0
|
||||
total_edit = total_count - total_create - total_delete
|
||||
|
||||
oldest_loaded_id = entries[-1]["id"] if entries else None
|
||||
has_more = len(entries) >= AUDIT_LOG_PAGE_SIZE and total_count > len(entries)
|
||||
return render_template(
|
||||
"activity_log.html", entries=entries, total_count=total_count,
|
||||
total_create=total_create, total_edit=total_edit, total_delete=total_delete,
|
||||
oldest_loaded_id=oldest_loaded_id, has_more=has_more,
|
||||
)
|
||||
|
||||
|
||||
@@ -18,22 +18,24 @@
|
||||
{% else %}{% set ns.edit = ns.edit + 1 %}{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% macro fmt_count(loaded, total) %}{% if loaded < total %}{{ loaded }} / {{ total }}{% else %}{{ loaded }}{% endif %}{% endmacro %}
|
||||
|
||||
<div class="stat-row" style="margin-bottom:18px;">
|
||||
<div class="stat-card" data-category-filter="">
|
||||
<div class="stat-label">Alle</div>
|
||||
<div class="stat-value" id="statAll">{{ entries|length }}</div>
|
||||
<div class="stat-value" id="statAll">{{ fmt_count(entries|length, total_count) }}</div>
|
||||
</div>
|
||||
<div class="stat-card" data-category-filter="create">
|
||||
<div class="stat-label">Hinzufügen</div>
|
||||
<div class="stat-value" id="statCreate" style="color:var(--success);">{{ ns.create }}</div>
|
||||
<div class="stat-value" id="statCreate" style="color:var(--success);">{{ fmt_count(ns.create, total_create) }}</div>
|
||||
</div>
|
||||
<div class="stat-card" data-category-filter="edit">
|
||||
<div class="stat-label">Änderungen</div>
|
||||
<div class="stat-value" id="statEdit" style="color:var(--accent-strong);">{{ ns.edit }}</div>
|
||||
<div class="stat-value" id="statEdit" style="color:var(--accent-strong);">{{ fmt_count(ns.edit, total_edit) }}</div>
|
||||
</div>
|
||||
<div class="stat-card" data-category-filter="delete">
|
||||
<div class="stat-label">Löschungen</div>
|
||||
<div class="stat-value" id="statDelete" style="color:var(--danger);">{{ ns.delete }}</div>
|
||||
<div class="stat-value" id="statDelete" style="color:var(--danger);">{{ fmt_count(ns.delete, total_delete) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -112,16 +114,23 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
|
||||
/* ---- Nachladen älterer Einträge (Mehr laden / Alle laden) ---- */
|
||||
const totalCount = {{ total_count }};
|
||||
const totalCreate = {{ total_create }};
|
||||
const totalEdit = {{ total_edit }};
|
||||
const totalDelete = {{ total_delete }};
|
||||
const entryCountLabel = document.getElementById("auditEntryCount");
|
||||
|
||||
function fmtCount(loaded, total) {
|
||||
return loaded < total ? loaded + " / " + total : String(loaded);
|
||||
}
|
||||
|
||||
function recomputeStats() {
|
||||
const rows = Array.from(document.querySelectorAll("#auditTable tbody tr[data-category]"));
|
||||
const counts = { create: 0, edit: 0, delete: 0 };
|
||||
rows.forEach(function (r) { counts[r.dataset.category] = (counts[r.dataset.category] || 0) + 1; });
|
||||
document.getElementById("statAll").textContent = rows.length;
|
||||
document.getElementById("statCreate").textContent = counts.create;
|
||||
document.getElementById("statEdit").textContent = counts.edit;
|
||||
document.getElementById("statDelete").textContent = counts.delete;
|
||||
document.getElementById("statAll").textContent = fmtCount(rows.length, totalCount);
|
||||
document.getElementById("statCreate").textContent = fmtCount(counts.create, totalCreate);
|
||||
document.getElementById("statEdit").textContent = fmtCount(counts.edit, totalEdit);
|
||||
document.getElementById("statDelete").textContent = fmtCount(counts.delete, totalDelete);
|
||||
if (entryCountLabel) {
|
||||
entryCountLabel.textContent = rows.length < totalCount
|
||||
? rows.length + " von " + totalCount + " Einträgen geladen"
|
||||
|
||||
Reference in New Issue
Block a user