Version 2.7.4: Unterschriften in der Sicherung, unterschrieben ist abgeschlossen
This commit is contained in:
1 parent
ce22239d78
commit
ad0195bab0
10 files changed
+168
-21
No files matched your search
@@ -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 = [
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -44,8 +44,11 @@
|
||||
<a class="btn btn--sm btn--ghost" href="{{ url_for('logs.audit_view') }}">Zurücksetzen</a>
|
||||
</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">
|
||||
<table class="table table--compact" data-behavior="sortable">
|
||||
<table class="table table--compact table--stapelbar" data-behavior="sortable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sortable">Zeit</th>
|
||||
@@ -60,12 +63,16 @@
|
||||
<tbody>
|
||||
{% for row in rows %}
|
||||
<tr>
|
||||
<td class="fs-sm nowrap" data-sort-value="{{ row.ts }}">{{ row.ts | dt }}</td>
|
||||
<td class="fs-sm fw-600">{{ row.actor }}</td>
|
||||
<td class="mono fs-xs">{{ row.action }}</td>
|
||||
<td class="fs-sm">{{ row.target }}</td>
|
||||
<td class="fs-sm muted break-all">{{ row.detail | audit_detail }}</td>
|
||||
<td>
|
||||
<td class="fs-sm nowrap" data-spalte="Zeit" data-sort-value="{{ row.ts }}">
|
||||
{{ row.ts | dt }}
|
||||
</td>
|
||||
<td class="fs-sm fw-600" data-spalte="Benutzer">{{ row.actor }}</td>
|
||||
<td class="mono fs-xs" data-spalte="Aktion">{{ row.action }}</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
|
||||
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 %}
|
||||
</td>
|
||||
<td class="mono fs-xs faint">{{ row.ip or '–' | safe }}</td>
|
||||
<td class="mono fs-xs faint" data-spalte="Herkunft">{{ row.ip or '–' | safe }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
Reference in new issue
Block a user