227 lines
10 KiB
HTML
227 lines
10 KiB
HTML
{{/*
|
||
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"> & 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}}
|