aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2026-10-15 00:06:55 +0200
committerDaniel Schadt <kingdread@gmx.de>2026-10-15 00:06:55 +0200
commit698592e608ae849c6c9d107167ab1c4217d01fa0 (patch)
tree26cb6b12173e05a67f2aceae3002c8c114cfd120
parent485fcb9107957d391af3c30db5d577ed84f7e6e9 (diff)
downloadfietsboek-logs-in-ui.tar.gz
fietsboek-logs-in-ui.tar.bz2
fietsboek-logs-in-ui.zip
add a fietsboek log view to the admin sitelogs-in-ui
-rw-r--r--asset-sources/theme.scss35
-rw-r--r--fietsboek/__init__.py3
-rw-r--r--fietsboek/locale/de/LC_MESSAGES/messages.mobin21619 -> 21673 bytes
-rw-r--r--fietsboek/locale/de/LC_MESSAGES/messages.po22
-rw-r--r--fietsboek/locale/en/LC_MESSAGES/messages.mobin20345 -> 20386 bytes
-rw-r--r--fietsboek/locale/en/LC_MESSAGES/messages.po22
-rw-r--r--fietsboek/locale/fietslog.pot18
-rw-r--r--fietsboek/log.py48
-rw-r--r--fietsboek/routes.py1
-rw-r--r--fietsboek/static/theme.css34
-rw-r--r--fietsboek/static/theme.css.map2
-rw-r--r--fietsboek/templates/admin.jinja21
-rw-r--r--fietsboek/templates/admin_logs.jinja246
-rw-r--r--fietsboek/views/admin.py10
14 files changed, 213 insertions, 29 deletions
diff --git a/asset-sources/theme.scss b/asset-sources/theme.scss
index e8ed1a5..fbb836e 100644
--- a/asset-sources/theme.scss
+++ b/asset-sources/theme.scss
@@ -420,7 +420,10 @@ strong {
#adminContainer {
display: grid;
grid-template-areas: "sidebar main";
- grid-template-columns: 1fr 5fr;
+ /* Use minmax() to force fr to be an actual size, and not just split the
+ * "remaining size".
+ */
+ grid-template-columns: minmax(0px, 1fr) minmax(0px, 5fr);
gap: 1rem;
}
@@ -436,6 +439,36 @@ strong {
font-size: 120%;
}
+.logview {
+ background-color: white;
+ border-radius: 0.375rem;
+ padding: 0.375rem;
+}
+
+.logline {
+ font-family: monospace;
+
+ td {
+ padding-right: 1em;
+ }
+}
+
+.logline-debug {
+ color: #444;
+}
+
+.logline-info {
+ color: #00c;
+}
+
+.logline-warning {
+ color: #990;
+}
+
+.logline-error {
+ color: #c00;
+}
+
.list-group.list-group-root {
padding: 0;
overflow: hidden;
diff --git a/fietsboek/__init__.py b/fietsboek/__init__.py
index b2af484..519cdce 100644
--- a/fietsboek/__init__.py
+++ b/fietsboek/__init__.py
@@ -33,6 +33,7 @@ from pyramid.session import SignedCookieSessionFactory
from . import config as mod_config
from . import fstrans
from . import jinja2 as mod_jinja2
+from . import log as mod_log
from . import transformers
from .data import DataManager
from .pages import Pages
@@ -164,6 +165,8 @@ def main(global_config, **settings):
from .osm import OverpassApi
from .views.tileproxy import TileRequester
+ mod_log.install()
+
# In tests this isn't passed, so guard against it
if "__file__" in global_config:
check_update_state(global_config["__file__"])
diff --git a/fietsboek/locale/de/LC_MESSAGES/messages.mo b/fietsboek/locale/de/LC_MESSAGES/messages.mo
index 2cd5007..4376c91 100644
--- a/fietsboek/locale/de/LC_MESSAGES/messages.mo
+++ b/fietsboek/locale/de/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/fietsboek/locale/de/LC_MESSAGES/messages.po b/fietsboek/locale/de/LC_MESSAGES/messages.po
index 552880f..27e798b 100644
--- a/fietsboek/locale/de/LC_MESSAGES/messages.po
+++ b/fietsboek/locale/de/LC_MESSAGES/messages.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2026-10-01 13:36+0200\n"
+"POT-Creation-Date: 2026-10-15 00:03+0200\n"
"PO-Revision-Date: 2022-07-02 17:35+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: de\n"
@@ -18,11 +18,11 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.18.0\n"
-#: fietsboek/actions.py:269
+#: fietsboek/actions.py:271
msgid "email.verify_mail.subject"
msgstr "Fietsboek Konto Bestätigung"
-#: fietsboek/actions.py:272
+#: fietsboek/actions.py:274
msgid "email.verify.text"
msgstr ""
"Um Dein Fietsboek-Konto zu bestätigen, nutze diesen Link: {}\n"
@@ -145,6 +145,10 @@ msgstr "Übersicht"
msgid "page.admin.nav.badges"
msgstr "Wappen"
+#: fietsboek/templates/admin.jinja2:12
+msgid "page.admin.nav.logs"
+msgstr "Ereignisprotokoll"
+
#: fietsboek/templates/admin_badges.jinja2:5
msgid "page.admin.badges"
msgstr "Wappen"
@@ -551,8 +555,8 @@ msgstr "Schlagwörter"
#: fietsboek/templates/details.jinja2:111
msgid "page.details.background_tasks_in_progress"
msgstr ""
-"Hintergrundaufgaben für diese Strecke sind noch nicht abgeschlossen. "
-"Die angezeigten Informationen sind noch unvollständig."
+"Hintergrundaufgaben für diese Strecke sind noch nicht abgeschlossen. Die "
+"angezeigten Informationen sind noch unvollständig."
#: fietsboek/templates/details.jinja2:121 fietsboek/templates/edit.jinja2:10
#: fietsboek/templates/finish_upload.jinja2:10
@@ -1250,15 +1254,15 @@ msgstr "Ungültige E-Mail-Adresse"
msgid "flash.a_confirmation_link_has_been_sent"
msgstr "Ein Bestätigungslink wurde versandt"
-#: fietsboek/views/admin.py:189
+#: fietsboek/views/admin.py:197
msgid "flash.badge_added"
msgstr "Wappen hinzugefügt"
-#: fietsboek/views/admin.py:213
+#: fietsboek/views/admin.py:221
msgid "flash.badge_modified"
msgstr "Wappen bearbeitet"
-#: fietsboek/views/admin.py:233
+#: fietsboek/views/admin.py:241
msgid "flash.badge_deleted"
msgstr "Wappen gelöscht"
@@ -1338,7 +1342,7 @@ msgstr "Keine Datei ausgewählt"
msgid "flash.upload_success"
msgstr "Hochladen erfolgreich"
-#: fietsboek/views/upload.py:202
+#: fietsboek/views/upload.py:203
msgid "flash.upload_cancelled"
msgstr "Hochladen abgebrochen"
diff --git a/fietsboek/locale/en/LC_MESSAGES/messages.mo b/fietsboek/locale/en/LC_MESSAGES/messages.mo
index 19b3c28..6ea8566 100644
--- a/fietsboek/locale/en/LC_MESSAGES/messages.mo
+++ b/fietsboek/locale/en/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/fietsboek/locale/en/LC_MESSAGES/messages.po b/fietsboek/locale/en/LC_MESSAGES/messages.po
index 1feb09a..0269f88 100644
--- a/fietsboek/locale/en/LC_MESSAGES/messages.po
+++ b/fietsboek/locale/en/LC_MESSAGES/messages.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2026-10-01 13:36+0200\n"
+"POT-Creation-Date: 2026-10-15 00:03+0200\n"
"PO-Revision-Date: 2023-04-03 20:42+0200\n"
"Last-Translator: \n"
"Language: en\n"
@@ -18,11 +18,11 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.18.0\n"
-#: fietsboek/actions.py:269
+#: fietsboek/actions.py:271
msgid "email.verify_mail.subject"
msgstr "Fietsboek Account Verification"
-#: fietsboek/actions.py:272
+#: fietsboek/actions.py:274
msgid "email.verify.text"
msgstr ""
"To verify your Fietsboek account, please use this link: {}\n"
@@ -145,6 +145,10 @@ msgstr "Overview"
msgid "page.admin.nav.badges"
msgstr "Badges"
+#: fietsboek/templates/admin.jinja2:12
+msgid "page.admin.nav.logs"
+msgstr "Logs"
+
#: fietsboek/templates/admin_badges.jinja2:5
msgid "page.admin.badges"
msgstr "Badges"
@@ -549,8 +553,8 @@ msgstr "Tagged as"
#: fietsboek/templates/details.jinja2:111
msgid "page.details.background_tasks_in_progress"
msgstr ""
-"Background tasks for this track are still running. "
-"The information displayed is still incomplete."
+"Background tasks for this track are still running. The information "
+"displayed is still incomplete."
#: fietsboek/templates/details.jinja2:121 fietsboek/templates/edit.jinja2:10
#: fietsboek/templates/finish_upload.jinja2:10
@@ -1240,15 +1244,15 @@ msgstr "Invalid email"
msgid "flash.a_confirmation_link_has_been_sent"
msgstr "A confirmation link has been sent"
-#: fietsboek/views/admin.py:189
+#: fietsboek/views/admin.py:197
msgid "flash.badge_added"
msgstr "Badge has been added"
-#: fietsboek/views/admin.py:213
+#: fietsboek/views/admin.py:221
msgid "flash.badge_modified"
msgstr "Badge has been modified"
-#: fietsboek/views/admin.py:233
+#: fietsboek/views/admin.py:241
msgid "flash.badge_deleted"
msgstr "Badge has been deleted"
@@ -1327,7 +1331,7 @@ msgstr "No file selected"
msgid "flash.upload_success"
msgstr "Upload successful"
-#: fietsboek/views/upload.py:202
+#: fietsboek/views/upload.py:203
msgid "flash.upload_cancelled"
msgstr "Upload cancelled"
diff --git a/fietsboek/locale/fietslog.pot b/fietsboek/locale/fietslog.pot
index 4a9e203..26b222b 100644
--- a/fietsboek/locale/fietslog.pot
+++ b/fietsboek/locale/fietslog.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2026-10-01 13:36+0200\n"
+"POT-Creation-Date: 2026-10-15 00:03+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,11 +17,11 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.18.0\n"
-#: fietsboek/actions.py:269
+#: fietsboek/actions.py:271
msgid "email.verify_mail.subject"
msgstr ""
-#: fietsboek/actions.py:272
+#: fietsboek/actions.py:274
msgid "email.verify.text"
msgstr ""
@@ -139,6 +139,10 @@ msgstr ""
msgid "page.admin.nav.badges"
msgstr ""
+#: fietsboek/templates/admin.jinja2:12
+msgid "page.admin.nav.logs"
+msgstr ""
+
#: fietsboek/templates/admin_badges.jinja2:5
msgid "page.admin.badges"
msgstr ""
@@ -1224,15 +1228,15 @@ msgstr ""
msgid "flash.a_confirmation_link_has_been_sent"
msgstr ""
-#: fietsboek/views/admin.py:189
+#: fietsboek/views/admin.py:197
msgid "flash.badge_added"
msgstr ""
-#: fietsboek/views/admin.py:213
+#: fietsboek/views/admin.py:221
msgid "flash.badge_modified"
msgstr ""
-#: fietsboek/views/admin.py:233
+#: fietsboek/views/admin.py:241
msgid "flash.badge_deleted"
msgstr ""
@@ -1308,7 +1312,7 @@ msgstr ""
msgid "flash.upload_success"
msgstr ""
-#: fietsboek/views/upload.py:202
+#: fietsboek/views/upload.py:203
msgid "flash.upload_cancelled"
msgstr ""
diff --git a/fietsboek/log.py b/fietsboek/log.py
new file mode 100644
index 0000000..5e48e85
--- /dev/null
+++ b/fietsboek/log.py
@@ -0,0 +1,48 @@
+"""Logging-related utilities."""
+import collections
+import datetime
+import logging
+from dataclasses import asdict, dataclass
+
+@dataclass(slots=True)
+class LogLine:
+ time: str
+ name: str
+ level: int
+ level_name: str
+ message: str
+ thread: str
+ lineno: int
+
+ def as_dict(self) -> dict:
+ return asdict(self)
+
+
+class RingBuffer(logging.Handler):
+ """Stores messages in a ring-buffer.
+
+ When the buffer is full, a new message will replace the oldest one.
+ """
+
+ def __init__(self, maxlen):
+ super().__init__()
+ self.buffer = collections.deque(maxlen=maxlen)
+
+ def emit(self, record):
+ line = LogLine(
+ time=record.asctime,
+ name=record.name,
+ level=record.levelno,
+ level_name=record.levelname,
+ message=record.getMessage(),
+ thread=record.threadName,
+ lineno=record.lineno,
+ )
+ self.buffer.append(line)
+
+
+HANDLER = RingBuffer(5000)
+
+
+def install():
+ logging.getLogger().addHandler(HANDLER)
diff --git a/fietsboek/routes.py b/fietsboek/routes.py
index 2e1a171..da9ed04 100644
--- a/fietsboek/routes.py
+++ b/fietsboek/routes.py
@@ -101,6 +101,7 @@ def includeme(config):
config.add_route("badge", "/badge/{badge_id}", factory="fietsboek.models.Badge.factory")
config.add_route("admin", "/admin/")
+ config.add_route("admin-logs", "/admin/logs")
config.add_route("admin-badge", "/admin/badges/")
config.add_route("admin-badge-add", "/admin/badges/add")
config.add_route("admin-badge-edit", "/admin/badges/edit")
diff --git a/fietsboek/static/theme.css b/fietsboek/static/theme.css
index b295203..6b9e1c2 100644
--- a/fietsboek/static/theme.css
+++ b/fietsboek/static/theme.css
@@ -404,7 +404,10 @@ strong {
#adminContainer {
display: grid;
grid-template-areas: "sidebar main";
- grid-template-columns: 1fr 5fr;
+ /* Use minmax() to force fr to be an actual size, and not just split the
+ * "remaining size".
+ */
+ grid-template-columns: minmax(0px, 1fr) minmax(0px, 5fr);
gap: 1rem;
}
@@ -420,6 +423,35 @@ strong {
font-size: 120%;
}
+.logview {
+ background-color: white;
+ border-radius: 0.375rem;
+ padding: 0.375rem;
+}
+
+.logline {
+ font-family: monospace;
+}
+.logline td {
+ padding-right: 1em;
+}
+
+.logline-debug {
+ color: #444;
+}
+
+.logline-info {
+ color: #00c;
+}
+
+.logline-warning {
+ color: #990;
+}
+
+.logline-error {
+ color: #c00;
+}
+
.list-group.list-group-root {
padding: 0;
overflow: hidden;
diff --git a/fietsboek/static/theme.css.map b/fietsboek/static/theme.css.map
index b91d750..30b9235 100644
--- a/fietsboek/static/theme.css.map
+++ b/fietsboek/static/theme.css.map
@@ -1 +1 @@
-{"version":3,"sourceRoot":"","sources":["../../asset-sources/theme.scss"],"names":[],"mappings":"AAAA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAIA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAlCJ;EAqCE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACI;;;AAGJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;AACA;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAIA;EACE;;;AAGJ;AAEA;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;;AAEF;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;EACA;;AACA;EACE;;AAIJ;EACE;EACA;;;AAKF;EACE;EACA;EAEA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAGF;EACE;;;AAGF;AACA;EACE;;;AAGF;EACE;EACA;;AAEA;EAJF;IAKI,eACE;;;AAIJ;EACE;;AAGF;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;;;AAIJ;EACE;;;AAGF;AACA;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE","file":"theme.css"} \ No newline at end of file
+{"version":3,"sourceRoot":"","sources":["../../asset-sources/theme.scss"],"names":[],"mappings":"AAAA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAIA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAlCJ;EAqCE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACI;;;AAGJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;AACA;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAIA;EACE;;;AAGJ;AAEA;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;;AAEF;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;EACA;;AACA;EACE;;AAIJ;EACE;EACA;;;AAKF;EACE;EACA;EAEA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAGF;EACE;;;AAGF;AACA;EACE;;;AAGF;EACE;EACA;;AAEA;EAJF;IAKI,eACE;;;AAIJ;EACE;;AAGF;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;;;AAIJ;EACE;;;AAGF;AACA;EACE;EACA;AACA;AAAA;AAAA;EAGA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;AAEA;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE","file":"theme.css"} \ No newline at end of file
diff --git a/fietsboek/templates/admin.jinja2 b/fietsboek/templates/admin.jinja2
index e05e9f0..f324495 100644
--- a/fietsboek/templates/admin.jinja2
+++ b/fietsboek/templates/admin.jinja2
@@ -9,6 +9,7 @@
<nav class="nav nav-pills nav-fill flex-column">
<a class="nav-link{% if admin_index == 0 %} active text-bg-dark{% endif %}" href="{{ request.route_url('admin') }}">{{ _("page.admin.nav.overview") }}</a>
<a class="nav-link{% if admin_index == 1 %} active text-bg-dark{% endif %}" href="{{ request.route_url('admin-badge') }}">{{ _("page.admin.nav.badges") }}</a>
+ <a class="nav-link{% if admin_index == 2 %} active text-bg-dark{% endif %}" href="{{ request.route_url('admin-logs') }}">{{ _("page.admin.nav.logs") }}</a>
</nav>
</aside>
diff --git a/fietsboek/templates/admin_logs.jinja2 b/fietsboek/templates/admin_logs.jinja2
new file mode 100644
index 0000000..ac3f956
--- /dev/null
+++ b/fietsboek/templates/admin_logs.jinja2
@@ -0,0 +1,46 @@
+{% set admin_index = 2 %}
+{% extends "admin.jinja2" %}
+{% block admin_content %}
+<div>
+ Filter:
+ <select class="form-select my-2" id="logLevelSelect">
+ <option value="10">Debug</option>
+ <option value="20" selected>Info</option>
+ <option value="30">Warning</option>
+ <option value="40">Error</option>
+ <option value="50">Critical</option>
+ </select>
+</div>
+<div class="logview" style="overflow: scroll; white-space: nowrap;">
+ <table>
+ {% for entry in entries %}
+ <tr class="logline logline-{{entry.level_name | lower}}" data-level="{{ entry.level }}">
+ <td>{{ entry.time }}</td>
+ <td>{{ entry.level_name }}</td>
+ <td>{{ entry.name }}:{{ entry.lineno }}</td>
+ <td>{{ entry.thread }}</td>
+ <td>{{ entry.message }}</td>
+ </tr>
+ {% endfor %}
+ </table>
+</div>
+{% endblock %}
+
+{% block latescripts %}
+ <script type="text/javascript">
+ function filterLogEntries() {
+ let wantedLevel = parseInt(document.querySelector("#logLevelSelect").value);
+ document.querySelectorAll(".logline").forEach((line) => {
+ let lineLevel = parseInt(line.getAttribute("data-level"));
+ if (lineLevel >= wantedLevel) {
+ line.style.display = "";
+ } else {
+ line.style.display = "none";
+ }
+ });
+ }
+
+ document.querySelector("#logLevelSelect").addEventListener("change", (e) => filterLogEntries());
+ filterLogEntries();
+ </script>
+{% endblock %}
diff --git a/fietsboek/views/admin.py b/fietsboek/views/admin.py
index f0aa271..9252090 100644
--- a/fietsboek/views/admin.py
+++ b/fietsboek/views/admin.py
@@ -12,7 +12,7 @@ from pyramid.request import Request
from pyramid.view import view_config
from sqlalchemy import func, select, text
-from .. import models, util
+from .. import log, models, util
from ..data import DataManager
GOOD_CRON_THRESHOLD = datetime.timedelta(hours=1)
@@ -147,6 +147,14 @@ def admin(request: Request):
"cron_good": cron_good,
}
+@view_config(
+ route_name="admin-logs",
+ renderer="fietsboek:templates/admin_logs.jinja2",
+ permission="admin",
+)
+def admin_logs(request: Request):
+ return {"entries": log.HANDLER.buffer}
+
@view_config(
route_name="admin-badge",