munin/templates/partials.html
2026-10-19 10:13:56 +02:00

227 lines
10 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{{/*
Gemeinsame Bausteine aller Seiten.
Statt eines verschachtelten Layout-Templates gibt es hier Blöcke, die jede
Seite einbindet. Das ist etwas mehr Tipparbeit je Seite, dafür braucht es
keine Template-Vererbung — und man sieht jeder Seitendatei an, wie sie
aufgebaut ist.
html-anfang / html-ende Dokumentrahmen (auch von der Anmeldeseite genutzt)
kopf / fuss Rahmen, Kopfleiste und Seitenleiste
*/}}
{{define "html-start"}}<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{.Title}} – Munin</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
{{end}}
{{define "html-end"}}
<script src="/static/confirm.js"></script>
<script src="/static/preview.js"></script>
<script src="/static/autocomplete.js"></script>
<script src="/static/graph.js"></script>
<script src="/static/tagfilter.js"></script>
<script src="/static/unsaved.js"></script>
<script src="/static/similar.js"></script>
<script src="/static/shortcuts.js"></script>
</body>
</html>
{{end}}
{{define "header"}}{{template "html-start" .}}
{{/* Schmale Kopfleiste über die ganze Breite: Marke, Workspace-Umschalter,
Hilfe und Abmelden. Alles Weitere steht in der Seitenleiste.
Die Hilfe steht hier oben statt unten in der Seitenleiste: Dort rutschte
sie bei vielen Projekten und Schlagworten aus dem Blick — gerade dann,
wenn man sie sucht.
Der Umschalter steht bewusst hier statt in der Seitenleiste — ein
Plattform-Admin mit mehreren Abteilungen muss auf jeder Seite sehen,
WELCHEN Workspace er gerade bearbeitet, nicht nur auf der Auswahlseite
selbst. Für einen Projekt-Zugang (immer genau ein Workspace) bleibt der
Umschalter weg — WorkspaceName ist dann leer. */}}
<header class="topbar">
<div class="topbar-inner">
<div class="row">
<a class="badge-word" href="/">Munin</a>
{{if .Session.IsPlatformAdmin}}{{if .Session.WorkspaceName}}
<a class="workspace" href="/admin/workspaces">
<span class="workspace-separator" aria-hidden="true">/</span>
<span class="workspace-name">{{.Session.WorkspaceName}}</span>
<span class="workspace-arrow" aria-hidden="true">⌄</span>
</a>
{{end}}{{else if .Session.IsWorkspaceAdmin}}
{{/* Der Workspace-Admin hat genau einen Workspace — der Name steht
zur Orientierung da, ohne Umschalter. */}}
<span class="workspace">
<span class="workspace-separator" aria-hidden="true">/</span>
<span class="workspace-name">{{.Session.WorkspaceName}}</span>
</span>
{{end}}
</div>
<div class="row topbar-actions">
<a href="/hilfe" class="topbar-link{{if eq .Section "hilfe"}} aktiv{{end}}"
{{if eq .Section "hilfe"}}aria-current="page"{{end}}>Hilfe<span class="wide-only"> &amp; Einstieg</span></a>
<form method="POST" action="/logout" class="row">
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<button type="submit" class="link-button">Abmelden</button>
</form>
</div>
</div>
</header>
<div class="layout">
{{/* ── Seitenleiste ──────────────────────────────────────────────────────
Enthält drei Gruppen: die Projekte, die Bereiche des aktuellen Projekts
und dessen Schlagworte. Die Schlagworte stehen hier statt als Filterzeile
über der Liste — sie sind Navigation, und die Liste bekommt so mehr Platz. */}}
<aside class="sidebar">
{{if .Session.CanManageProjects}}
<nav class="nav-group">
<h2 class="nav-title">Projekte</h2>
<ul class="nav-list">
{{$aktuell := .Project.Slug}}
{{range .Nav.Projects}}
<li><a href="/p/{{.Slug}}/" {{if eq $aktuell .Slug}}class="active"{{end}}>{{.Name}}</a></li>
{{end}}
</ul>
<ul class="nav-list quiet">
<li><a href="/admin/projects" {{if eq .Section "projekte"}}class="active"{{end}}>Verwalten…</a></li>
</ul>
</nav>
{{end}}
{{/* Die Bereiche des aktuellen Projekts. Die Überschrift ist der
Projektname — für einen Projekt-Key ist das zugleich die einzige
Ortsangabe, denn eine Projektliste bekommt er nicht zu sehen. */}}
{{if .Project.Slug}}
<nav class="nav-group">
<h2 class="nav-title">{{.Project.Name}}</h2>
<ul class="nav-list">
<li><a href="/p/{{.Project.Slug}}/" {{if eq .Section "eintraege"}}class="active"{{end}}>Einträge</a></li>
<li><a href="/p/{{.Project.Slug}}/graph" {{if eq .Section "graph"}}class="active"{{end}}>Graph</a></li>
{{if .Session.CanManageKeys}}
<li><a href="/p/{{.Project.Slug}}/keys" {{if eq .Section "zugaenge"}}class="active"{{end}}>Zugänge</a></li>
{{end}}
{{if .Session.CanImport}}
<li><a href="/p/{{.Project.Slug}}/import" {{if eq .Section "import"}}class="active"{{end}}>Import</a></li>
{{end}}
<li><a href="/p/{{.Project.Slug}}/usage" {{if eq .Section "nutzung"}}class="active"{{end}}>Nutzung</a></li>
<li><a href="/p/{{.Project.Slug}}/audit" {{if eq .Section "protokoll"}}class="active"{{end}}>Protokoll</a></li>
{{if .Session.CanWrite}}
<li><a href="/p/{{.Project.Slug}}/trash" {{if eq .Section "papierkorb"}}class="active"{{end}}>Papierkorb</a></li>
{{end}}
</ul>
</nav>
{{if .Nav.Tags}}
<nav class="nav-group tags">
<h2 class="nav-title">Schlagworte</h2>
<ul class="nav-list">
{{$slug := .Project.Slug}}{{$tag := .ActiveTag}}
{{range .Nav.Tags}}
<li>
<a href="/p/{{$slug}}/?tag={{.Tag}}" {{if eq $tag .Tag}}class="active"{{end}}>
<span class="nav-text">{{.Tag}}</span>
<span class="nav-count">{{.Count}}</span>
</a>
</li>
{{end}}
</ul>
{{/* Die Seitenleiste zeigt nur die häufigsten Schlagworte (navTagLimit
in internal/web/server.go). Gibt es mehr, führt dieser Link zur
vollständigen, filterbaren Liste. */}}
{{if gt .Nav.TagsTotal (len .Nav.Tags)}}
<ul class="nav-list quiet">
<li><a href="/p/{{.Project.Slug}}/tags" {{if eq .Section "schlagworte"}}class="active"{{end}}>
<span class="nav-text">Alle Schlagworte…</span>
<span class="nav-count">{{.Nav.TagsTotal}}</span>
</a></li>
</ul>
{{end}}
</nav>
{{end}}
{{end}}
{{if .Session.IsPlatformAdmin}}
<nav class="nav-group">
<h2 class="nav-title">Plattform</h2>
<ul class="nav-list">
<li><a href="/admin/overview" {{if eq .Section "ueberblick"}}class="active"{{end}}>Überblick (Workspace)</a></li>
<li><a href="/admin/search" {{if eq .Section "suche"}}class="active"{{end}}>Suche (alle Projekte)</a></li>
<li><a href="/admin/audit">Protokoll (alle)</a></li>
<li><a href="/admin/workspaces" {{if eq .Section "workspaces"}}class="active"{{end}}>Workspaces</a></li>
<li><a href="/admin/system" {{if eq .Section "system"}}class="active"{{end}}>System</a></li>
</ul>
</nav>
{{else if .Session.IsWorkspaceAdmin}}
<nav class="nav-group">
<h2 class="nav-title">Workspace</h2>
<ul class="nav-list">
<li><a href="/admin/overview" {{if eq .Section "ueberblick"}}class="active"{{end}}>Überblick</a></li>
<li><a href="/admin/search" {{if eq .Section "suche"}}class="active"{{end}}>Suche (alle Projekte)</a></li>
<li><a href="/admin/audit">Protokoll (alle)</a></li>
</ul>
</nav>
{{end}}
</aside>
<main class="content">
{{if .Error}}<div class="message error">{{.Error}}</div>{{end}}
{{if .Flash}}<div class="message hint">{{.Flash}}</div>{{end}}
{{end}}
{{/* hilfelink setzt ein kleines "?" neben eine Überschrift oder ein Feld, das
zur passenden Stelle der eingebauten Hilfe führt (AUSBAUSTUFEN.md 5.4).
Aufruf mit dem Ziel unterhalb von /hilfe/, auf Wunsch mit Abschnitt:
{{template "helplink" "weboberflaeche#markdown-im-inhalt"}}
Die Abschnittsnamen entstehen aus den Überschriften der Hilfeseiten
(internal/markdown, anchorIDs). Ein Test in web_test.go prüft, dass jedes
Ziel in den Templates wirklich existiert — wer eine Überschrift umbenennt,
merkt es also.
Die Hilfe öffnet in einem neuen Tab: Wer mitten im Bearbeiten nachschlägt,
soll dabei nicht seinen ungespeicherten Text verlieren. rel="noopener"
verhindert, dass der neue Tab auf das Fenster dieser Seite zugreifen kann. */}}
{{define "helplink"}}<a class="help-link" href="/hilfe/{{.}}" target="_blank" rel="noopener" title="Hilfe zu diesem Thema (neuer Tab)" aria-label="Hilfe zu diesem Thema (öffnet in neuem Tab)">?</a>{{end}}
{{define "footer"}}
</main>
</div>
{{template "html-end" .}}
{{end}}
{{/* Balkendiagramm der System- und Überblicksseite. Die Zahlen rechnet
internal/web/chart.go aus; hier wird nur gezeichnet. */}}
{{define "chart"}}
{{if .Empty}}
<p class="help chart-empty">Keine im ganzen Zeitraum.</p>
{{else}}
<svg class="chart" viewBox="0 0 {{.Width}} {{.Height}}" role="img" aria-label="{{.Title}}">
{{range .Grid}}
<line class="chart-grid" x1="{{$.Links}}" x2="{{$.Right}}" y1="{{.Y}}" y2="{{.Y}}"/>
<text class="chart-text" x="{{$.Links}}" dx="-6" y="{{.Y}}" dy="4" text-anchor="end">{{.Text}}</text>
{{end}}
{{range .Bars}}
<g>
<title>{{.Title}}</title>
<rect class="chart-hitarea" x="{{.X}}" y="0" width="{{.Width}}" height="{{$.Baseline}}"/>
{{range .Parts}}<rect class="{{.Class}}" x="{{.X}}" y="{{.Y}}" width="{{.Width}}" height="{{.Height}}" rx="2"/>{{end}}
</g>
{{end}}
{{range .Axis}}
<text class="chart-text" x="{{.X}}" y="{{$.Height}}" dy="-4" text-anchor="middle">{{.Text}}</text>
{{end}}
</svg>
{{end}}
{{end}}