Compare commits

...
1 Commits
8 changed files with 98 additions and 19 deletions

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "tesm-license" name = "tesm-license"
version = "2.7.3" version = "2.7.4"
description = "TESM-Lizenzserver -- Kunden, Tickets, Lizenzen, Aktivierung" description = "TESM-Lizenzserver -- Kunden, Tickets, Lizenzen, Aktivierung"
requires-python = ">=3.11" requires-python = ">=3.11"
dependencies = [ dependencies = [
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "tesm-core" 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" description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver"
requires-python = ">=3.11" requires-python = ">=3.11"
dependencies = [ dependencies = [
@@ -148,7 +148,7 @@ def create_base_app(
#: Wortmarke, ohne Zeile darunter; die Marke selbst zeigen beide #: Wortmarke, ohne Zeile darunter; die Marke selbst zeigen beide
#: Anwendungen. #: Anwendungen.
auth_tagline: str = "", auth_tagline: str = "",
app_version: str = "2.7.3", app_version: str = "2.7.4",
built_in_trusted_keys: tuple[str, ...] = (), built_in_trusted_keys: tuple[str, ...] = (),
enable_license: bool = True, enable_license: bool = True,
template_folder: str | None = None, template_folder: str | None = None,
@@ -1486,7 +1486,7 @@
font-size: 5.6cqw; font-size: 5.6cqw;
line-height: 1.15; line-height: 1.15;
color: #111; 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; padding-top: 1px;
pointer-events: none; pointer-events: none;
white-space: nowrap; white-space: nowrap;
@@ -1581,3 +1581,62 @@
color: var(--danger); color: var(--danger);
background: rgba(201, 42, 42, 0.12); 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;
}
}
@@ -308,11 +308,14 @@ async function nachbearbeiten(
color: PDFLib.rgb(0.1, 0.1, 0.1), 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({ seite.drawLine({
start: { x: eintrag.x, y: eintrag.y - 1 }, start: { x: eintrag.x, y: eintrag.y - 1.5 },
end: { x: eintrag.x + textbreite, y: eintrag.y - 1 }, end: { x: eintrag.x + textbreite, y: eintrag.y - 1.5 },
thickness: 0.5, thickness: 0.9,
color: PDFLib.rgb(0.4, 0.4, 0.4), color: PDFLib.rgb(0.15, 0.15, 0.15),
}); });
} }
} }
@@ -901,6 +904,7 @@ export function initFilePreview(wurzel = document) {
leiste.hidden = art === "text"; leiste.hidden = art === "text";
if (speichern) speichern.hidden = art !== "pdf"; if (speichern) speichern.hidden = art !== "pdf";
if (unterschreibenKnopf) unterschreibenKnopf.hidden = art !== "pdf"; if (unterschreibenKnopf) unterschreibenKnopf.hidden = art !== "pdf";
if (speichern) speichern.hidden = art !== "pdf";
if (unterschriftPanel) unterschriftPanel.hidden = true; if (unterschriftPanel) unterschriftPanel.hidden = true;
}; };
@@ -942,6 +946,15 @@ export function initFilePreview(wurzel = document) {
if (!adresse) return; if (!adresse) return;
try { try {
const stand = await window.tesm.api(adresse); 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") { if (stand.status === "unveraendert") {
pdfBehaelter.classList.add("viewer__pdf--unveraendert"); pdfBehaelter.classList.add("viewer__pdf--unveraendert");
if (pruefzeile) { if (pruefzeile) {
@@ -44,8 +44,11 @@
<a class="btn btn--sm btn--ghost" href="{{ url_for('logs.audit_view') }}">Zurücksetzen</a> <a class="btn btn--sm btn--ghost" href="{{ url_for('logs.audit_view') }}">Zurücksetzen</a>
</form> </form>
{# "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. #}
<div class="table-wrap"> <div class="table-wrap">
<table class="table table--compact" data-behavior="sortable"> <table class="table table--compact table--stapelbar" data-behavior="sortable">
<thead> <thead>
<tr> <tr>
<th class="sortable">Zeit</th> <th class="sortable">Zeit</th>
@@ -60,12 +63,16 @@
<tbody> <tbody>
{% for row in rows %} {% for row in rows %}
<tr> <tr>
<td class="fs-sm nowrap" data-sort-value="{{ row.ts }}">{{ row.ts | dt }}</td> <td class="fs-sm nowrap" data-spalte="Zeit" data-sort-value="{{ row.ts }}">
<td class="fs-sm fw-600">{{ row.actor }}</td> {{ row.ts | dt }}
<td class="mono fs-xs">{{ row.action }}</td> </td>
<td class="fs-sm">{{ row.target }}</td> <td class="fs-sm fw-600" data-spalte="Benutzer">{{ row.actor }}</td>
<td class="fs-sm muted break-all">{{ row.detail | audit_detail }}</td> <td class="mono fs-xs" data-spalte="Aktion">{{ row.action }}</td>
<td> <td class="fs-sm" data-spalte="Ziel">{{ row.target }}</td>
<td class="fs-sm muted break-all td--detail" data-spalte="Detail">
{{ row.detail | audit_detail }}
</td>
<td data-spalte="Stufe">
{# Ampel: Info grün, Hinweis gelb, Warnung rot. Vorher war Info {# Ampel: Info grün, Hinweis gelb, Warnung rot. Vorher war Info
grau und Hinweis blau -- dabei war nicht zu sehen, was harmlos grau und Hinweis blau -- dabei war nicht zu sehen, was harmlos
ist und was Aufmerksamkeit braucht. "kritisch" bekommt eine ist und was Aufmerksamkeit braucht. "kritisch" bekommt eine
@@ -76,7 +83,7 @@
{% elif row.severity == 'notice' %}{{ pill('Hinweis', 'warning') }} {% elif row.severity == 'notice' %}{{ pill('Hinweis', 'warning') }}
{% else %}{{ pill('Info', 'online') }}{% endif %} {% else %}{{ pill('Info', 'online') }}{% endif %}
</td> </td>
<td class="mono fs-xs faint">{{ row.ip or '&ndash;' | safe }}</td> <td class="mono fs-xs faint" data-spalte="Herkunft">{{ row.ip or '&ndash;' | safe }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "tesm-licensing-server" name = "tesm-licensing-server"
version = "2.7.3" version = "2.7.4"
description = "Serverhaelfte des TESM-Lizenzprotokolls: ausstellen, erneuern, antworten" description = "Serverhaelfte des TESM-Lizenzprotokolls: ausstellen, erneuern, antworten"
requires-python = ">=3.11" requires-python = ">=3.11"
dependencies = ["tesm-licensing==2.7.3", "cryptography>=41"] dependencies = ["tesm-licensing==2.7.4", "cryptography>=41"]
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
where = ["src"] where = ["src"]
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "tesm-licensing" name = "tesm-licensing"
version = "2.7.3" version = "2.7.4"
description = "Ed25519-basiertes Lizenz- und Aktivierungsprotokoll fuer TESM und TESM-Lizenzserver" description = "Ed25519-basiertes Lizenz- und Aktivierungsprotokoll fuer TESM und TESM-Lizenzserver"
requires-python = ">=3.11" requires-python = ">=3.11"
dependencies = ["cryptography>=42"] dependencies = ["cryptography>=42"]