From 2d234571d213b571d14ddcf733a3213f21de6c04 Mon Sep 17 00:00:00 2001 From: Tim Eertmoed Date: Sat, 12 Sep 2026 00:26:24 +0200 Subject: [PATCH] Version 2.7.4: Unterschriften in der Sicherung, unterschrieben ist abgeschlossen --- apps/tesm-license/pyproject.toml | 2 +- packages/tesm-core/pyproject.toml | 2 +- .../tesm-core/src/tesm_core/app_factory.py | 2 +- .../static/tesm_core/css/components.css | 61 ++++++++++++++++++- .../tesm_core/static/tesm_core/js/viewer.js | 21 +++++-- .../templates/tesm_core/logs_audit.html | 23 ++++--- packages/tesm-licensing-server/pyproject.toml | 4 +- packages/tesm-licensing/pyproject.toml | 2 +- 8 files changed, 98 insertions(+), 19 deletions(-) diff --git a/apps/tesm-license/pyproject.toml b/apps/tesm-license/pyproject.toml index e53d38f..e12081e 100644 --- a/apps/tesm-license/pyproject.toml +++ b/apps/tesm-license/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "tesm-license" -version = "2.7.3" +version = "2.7.4" description = "TESM-Lizenzserver -- Kunden, Tickets, Lizenzen, Aktivierung" requires-python = ">=3.11" dependencies = [ diff --git a/packages/tesm-core/pyproject.toml b/packages/tesm-core/pyproject.toml index 8c9888f..d6baaec 100644 --- a/packages/tesm-core/pyproject.toml +++ b/packages/tesm-core/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "tesm-core" -version = "2.7.3" +version = "2.7.4" description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver" requires-python = ">=3.11" dependencies = [ diff --git a/packages/tesm-core/src/tesm_core/app_factory.py b/packages/tesm-core/src/tesm_core/app_factory.py index 32aae1c..fb892f9 100644 --- a/packages/tesm-core/src/tesm_core/app_factory.py +++ b/packages/tesm-core/src/tesm_core/app_factory.py @@ -148,7 +148,7 @@ def create_base_app( #: Wortmarke, ohne Zeile darunter; die Marke selbst zeigen beide #: Anwendungen. auth_tagline: str = "", - app_version: str = "2.7.3", + app_version: str = "2.7.4", built_in_trusted_keys: tuple[str, ...] = (), enable_license: bool = True, template_folder: str | None = None, diff --git a/packages/tesm-core/src/tesm_core/static/tesm_core/css/components.css b/packages/tesm-core/src/tesm_core/static/tesm_core/css/components.css index 4962bae..5d05daa 100644 --- a/packages/tesm-core/src/tesm_core/static/tesm_core/css/components.css +++ b/packages/tesm-core/src/tesm_core/static/tesm_core/css/components.css @@ -1486,7 +1486,7 @@ font-size: 5.6cqw; line-height: 1.15; color: #111; - border-top: 1px solid rgba(0, 0, 0, 0.35); + border-top: 1px solid rgba(0, 0, 0, 0.85); padding-top: 1px; pointer-events: none; white-space: nowrap; @@ -1581,3 +1581,62 @@ color: var(--danger); background: rgba(201, 42, 42, 0.12); } + +/* -- Tabelle, die schmal zu Bloecken wird -------------------------------- */ +/* Eine Protokollzeile besteht aus sieben Angaben, von denen eine lang ist: + das Detail. Auf einem breiten Schirm passt das nebeneinander. Wird es eng, + ist eine Spalte von zwei Zentimetern fuer eine Pruefsumme keine Loesung -- + dann steht jede Angabe auf ihrer eigenen Zeile, beschriftet. */ + +.table--stapelbar .td--detail { + /* Zeilenumbrueche aus dem Eintrag bleiben stehen: die Pruefsumme steht + unter dem lesbaren Teil, nicht mitten darin. Und ein Hash ohne Trennstelle + darf notfalls hart umbrechen. */ + white-space: pre-line; + overflow-wrap: anywhere; + max-width: 52ch; +} + +@media (max-width: 1100px) { + .table--stapelbar thead { + display: none; + } + + .table--stapelbar, + .table--stapelbar tbody, + .table--stapelbar tr, + .table--stapelbar td { + display: block; + width: auto; + } + + .table--stapelbar tr { + padding: var(--sp-3) 0; + border-bottom: 1px solid var(--border); + } + + .table--stapelbar td { + display: grid; + grid-template-columns: 8.5rem 1fr; + gap: var(--sp-2); + align-items: baseline; + border: 0; + padding: 2px var(--sp-3); + white-space: normal; + } + + .table--stapelbar td::before { + content: attr(data-spalte); + color: var(--text-muted); + font-size: var(--fs-xs); + } + + .table--stapelbar .td--detail { + max-width: none; + } + + /* Leere Zellen brauchen keine Zeile. */ + .table--stapelbar td:empty { + display: none; + } +} diff --git a/packages/tesm-core/src/tesm_core/static/tesm_core/js/viewer.js b/packages/tesm-core/src/tesm_core/static/tesm_core/js/viewer.js index 748832b..8d08add 100644 --- a/packages/tesm-core/src/tesm_core/static/tesm_core/js/viewer.js +++ b/packages/tesm-core/src/tesm_core/static/tesm_core/js/viewer.js @@ -308,11 +308,14 @@ async function nachbearbeiten( color: PDFLib.rgb(0.1, 0.1, 0.1), }); } + // Kraeftig genug, um neben den Linien eines Formulars als eigener Strich + // erkennbar zu bleiben: ein halber Punkt in hellem Grau ging zwischen + // den Tabellenlinien schlicht unter. seite.drawLine({ - start: { x: eintrag.x, y: eintrag.y - 1 }, - end: { x: eintrag.x + textbreite, y: eintrag.y - 1 }, - thickness: 0.5, - color: PDFLib.rgb(0.4, 0.4, 0.4), + start: { x: eintrag.x, y: eintrag.y - 1.5 }, + end: { x: eintrag.x + textbreite, y: eintrag.y - 1.5 }, + thickness: 0.9, + color: PDFLib.rgb(0.15, 0.15, 0.15), }); } } @@ -901,6 +904,7 @@ export function initFilePreview(wurzel = document) { leiste.hidden = art === "text"; if (speichern) speichern.hidden = art !== "pdf"; if (unterschreibenKnopf) unterschreibenKnopf.hidden = art !== "pdf"; + if (speichern) speichern.hidden = art !== "pdf"; if (unterschriftPanel) unterschriftPanel.hidden = true; }; @@ -942,6 +946,15 @@ export function initFilePreview(wurzel = document) { if (!adresse) return; try { const stand = await window.tesm.api(adresse); + if (stand.status === "unveraendert" || stand.status === "veraendert") { + // Ein unterschriebenes Dokument ist abgeschlossen. Wer daraus eine + // neue Fassung machen koennte, koennte auch eine Unterschrift unter + // einen veraenderten Text setzen -- also gibt es hier nichts mehr zu + // bearbeiten. Der Server weist es zusaetzlich ab. + if (unterschreibenKnopf) unterschreibenKnopf.hidden = true; + if (speichern) speichern.hidden = true; + if (zeile) zeile.hidden = true; + } if (stand.status === "unveraendert") { pdfBehaelter.classList.add("viewer__pdf--unveraendert"); if (pruefzeile) { diff --git a/packages/tesm-core/src/tesm_core/templates/tesm_core/logs_audit.html b/packages/tesm-core/src/tesm_core/templates/tesm_core/logs_audit.html index c6a2f0e..80be4d4 100644 --- a/packages/tesm-core/src/tesm_core/templates/tesm_core/logs_audit.html +++ b/packages/tesm-core/src/tesm_core/templates/tesm_core/logs_audit.html @@ -44,8 +44,11 @@ Zurücksetzen + {# "table--stapelbar": schmal wird aus jeder Zeile ein kleiner Block. Vorher + quetschte sich das Detail mit Pruefsumme in eine Spalte von zwei + Zentimetern und lief ueber zehn Zeilen -- lesbar war das nicht. #}
- +
@@ -60,12 +63,16 @@ {% for row in rows %} - - - - - - + + + + + - + {% endfor %} diff --git a/packages/tesm-licensing-server/pyproject.toml b/packages/tesm-licensing-server/pyproject.toml index 9a63a35..ccfa637 100644 --- a/packages/tesm-licensing-server/pyproject.toml +++ b/packages/tesm-licensing-server/pyproject.toml @@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta" [project] name = "tesm-licensing-server" -version = "2.7.3" +version = "2.7.4" description = "Serverhaelfte des TESM-Lizenzprotokolls: ausstellen, erneuern, antworten" requires-python = ">=3.11" -dependencies = ["tesm-licensing==2.7.3", "cryptography>=41"] +dependencies = ["tesm-licensing==2.7.4", "cryptography>=41"] [tool.setuptools.packages.find] where = ["src"] diff --git a/packages/tesm-licensing/pyproject.toml b/packages/tesm-licensing/pyproject.toml index 523725c..0ebe07a 100644 --- a/packages/tesm-licensing/pyproject.toml +++ b/packages/tesm-licensing/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "tesm-licensing" -version = "2.7.3" +version = "2.7.4" description = "Ed25519-basiertes Lizenz- und Aktivierungsprotokoll fuer TESM und TESM-Lizenzserver" requires-python = ">=3.11" dependencies = ["cryptography>=42"]
Zeit
{{ row.ts | dt }}{{ row.actor }}{{ row.action }}{{ row.target }}{{ row.detail | audit_detail }} + + {{ row.ts | dt }} + {{ row.actor }}{{ row.action }}{{ row.target }} + {{ row.detail | audit_detail }} + {# Ampel: Info grün, Hinweis gelb, Warnung rot. Vorher war Info grau und Hinweis blau -- dabei war nicht zu sehen, was harmlos ist und was Aufmerksamkeit braucht. "kritisch" bekommt eine @@ -76,7 +83,7 @@ {% elif row.severity == 'notice' %}{{ pill('Hinweis', 'warning') }} {% else %}{{ pill('Info', 'online') }}{% endif %} {{ row.ip or '–' | safe }}{{ row.ip or '–' | safe }}