Files
MeshTender/internal/web/templates/base.html
T

228 lines
10 KiB
HTML
Raw 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.
{{define "base"}}<!doctype html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<link rel="icon" href="/static/favicon.svg" type="image/svg+xml">
<title>{{block "title" .}}MeshTender{{end}}</title>
<link rel="stylesheet" href="/static/tabler.min.css">
<link rel="stylesheet" href="/static/app.css">
<script src="/static/tabler.min.js" defer></script>
<script src="/static/htmx.min.js" defer></script>
</head>
<body>
<a href="#main-content" class="visually-hidden-focusable btn btn-primary position-absolute top-0 start-0 m-2" style="z-index:1080">Skip to main content</a>
<div class="page">
<header class="navbar navbar-expand-md d-print-none">
<div class="container-xl">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-menu" aria-controls="navbar-menu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a href="{{if .UserName}}{{.AppURL}}{{else}}{{.RootURL}}{{end}}/" class="navbar-brand navbar-brand-autodark d-flex align-items-center text-reset text-decoration-none pe-0 pe-md-3">
{{template "icon-logo" "me-1"}}<span class="fw-bold fs-3">MeshTender</span>
</a>
<div class="navbar-nav flex-row order-md-last align-items-center gap-2">
{{if .UserName}}
<div class="nav-item dropdown">
<a href="#" class="nav-link d-flex lh-1 p-0 px-2" data-bs-toggle="dropdown" aria-label="Open user menu">
<span class="avatar avatar-sm">{{template "icon-user" ""}}</span>
<div class="d-none d-xl-block ps-2"><div>{{.UserName}}</div></div>
</a>
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
<a class="dropdown-item" href="{{.AuthURL}}/account">{{template "icon-settings" "dropdown-item-icon"}}Account settings</a>
<div class="dropdown-divider"></div>
<form method="post" action="{{.AppURL}}/logout" class="m-0">
<button type="submit" class="dropdown-item text-danger">{{template "icon-logout" "dropdown-item-icon"}}Sign out</button>
</form>
</div>
</div>
{{else}}
<a href="{{.AppURL}}/login" class="btn btn-primary">{{template "icon-login" "me-1"}}Sign in</a>
{{end}}
</div>
<div class="collapse navbar-collapse" id="navbar-menu">
<ul class="navbar-nav">
{{if .UserName}}
<li class="nav-item">
<a class="nav-link" href="{{.AppURL}}/">
<span class="nav-link-icon d-md-none d-lg-inline-block">{{template "icon-home" ""}}</span>
<span class="nav-link-title">Dashboard</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{.AppURL}}/repeaters">
<span class="nav-link-icon d-md-none d-lg-inline-block">{{template "icon-antenna" ""}}</span>
<span class="nav-link-title">Repeaters</span>
</a>
</li>
{{end}}
<li class="nav-item">
<a class="nav-link" href="{{if .UserName}}{{.AppURL}}{{else}}{{.RootURL}}{{end}}/orgs">
<span class="nav-link-icon d-md-none d-lg-inline-block">{{template "icon-world" ""}}</span>
<span class="nav-link-title">Organizations</span>
</a>
</li>
{{if .CanAdmin}}
<li class="nav-item">
<a class="nav-link" href="{{.AppURL}}/admin">
<span class="nav-link-icon d-md-none d-lg-inline-block">{{template "icon-settings" ""}}</span>
<span class="nav-link-title">Admin</span>
</a>
</li>
{{end}}
</ul>
</div>
</div>
</header>
<div class="page-wrapper">
<div class="page-header d-print-none" aria-label="Page header">
<div class="container-xl">
{{block "header" .}}
<div class="row g-2 align-items-center">
<div class="col">
<h2 class="page-title">MeshTender</h2>
</div>
</div>
{{end}}
</div>
</div>
<div class="page-body">
<div class="container-xl" id="main-content" tabindex="-1">
{{block "content" .}}{{end}}
</div>
</div>
<footer class="footer footer-transparent d-print-none">
<div class="container-xl">
<div class="row text-center align-items-center flex-row-reverse">
<div class="col-12 col-lg-auto mt-3 mt-lg-0">
<span class="text-secondary">MeshTender &mdash; tend your mesh.</span>
</div>
</div>
</div>
</footer>
</div>
</div>
</body>
</html>{{end}}
{{/* authbase is a standalone, centered layout for the sign-in / sign-up pages —
no navbar or page chrome, just a brand logo above the page's content card.
Pages opt in with {{define "base"}}{{template "authbase" .}}{{end}}. */}}
{{define "authbase"}}<!doctype html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<link rel="icon" href="/static/favicon.svg" type="image/svg+xml">
<title>{{template "title" .}}</title>
<link rel="stylesheet" href="/static/tabler.min.css">
<link rel="stylesheet" href="/static/app.css">
<script src="/static/tabler.min.js" defer></script>
</head>
<body class="d-flex flex-column">
<div class="page page-center">
<div class="container container-tight py-4">
<div class="text-center mb-4">
<a href="/" class="navbar-brand navbar-brand-autodark d-inline-flex align-items-center text-reset text-decoration-none">
{{template "icon-logo" "me-1"}}<span class="fw-bold fs-2">MeshTender</span>
</a>
</div>
{{template "content" .}}
</div>
</div>
</body>
</html>{{end}}
{{/* landingbase is the public marketing layout: a transparent navbar with
sign-in / sign-up actions, the page content, and a simple footer. Pages opt
in via the "Layout":"landingbase" render key. */}}
{{define "landingbase"}}<!doctype html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<link rel="icon" href="/static/favicon.svg" type="image/svg+xml">
<title>{{template "title" .}}</title>
<link rel="stylesheet" href="/static/tabler.min.css">
<link rel="stylesheet" href="/static/app.css">
<script src="/static/tabler.min.js" defer></script>
</head>
<body>
<header class="navbar navbar-expand-md navbar-transparent py-3">
<div class="container">
<a href="/" class="navbar-brand navbar-brand-autodark d-flex align-items-center text-reset text-decoration-none">
{{template "icon-logo" "me-1"}}<span class="fw-bold fs-3">MeshTender</span>
</a>
<div class="navbar-nav flex-row order-md-last align-items-center gap-2">
<a href="{{.AppURL}}/login" class="btn btn-ghost-secondary">Sign in</a>
<a href="{{.AppURL}}/signup" class="btn btn-primary">Create account</a>
</div>
</div>
</header>
{{template "content" .}}
<footer class="footer footer-transparent">
<div class="container">
<div class="row align-items-center justify-content-center">
<div class="col-auto text-secondary">MeshTender &mdash; tend your mesh.</div>
</div>
</div>
</footer>
</body>
</html>{{end}}
{{/* revokedoc explains how to revoke MeshTender's access. Dot is the revoke command string. */}}
{{define "revokedoc"}}
<details class="mt-3">
<summary class="text-secondary" style="cursor:pointer">How to revoke MeshTender's access later</summary>
<p class="text-secondary mt-2">
Granting access is a standing trust: MeshTender keeps admin on your repeater until <strong>you</strong>
remove it — deleting the repeater from this site does <strong>not</strong> revoke it. To revoke, run this
on the repeater (via its BLE/USB companion app or another admin client):
</p>
<div class="input-group">
<code class="form-control font-monospace text-secondary">{{.}}</code>
<button type="button" class="btn" onclick="navigator.clipboard.writeText(this.previousElementSibling.textContent)">{{template "icon-copy" ""}}Copy</button>
</div>
<p class="text-secondary mt-2 mb-0">With no level argument, that <strong>removes MeshTender from the repeater's ACL entirely</strong>.</p>
</details>
{{end}}
{{/* feature-table renders a []featureRow (commands grouped by feature × operation)
for permission review/consent. Dot is the slice of rows. */}}
{{define "feature-table"}}
<div class="table-responsive">
<table class="table table-vcenter">
<thead><tr>
<th>Feature</th><th>Read</th><th>Write</th><th>Delete</th><th>Action</th>
</tr></thead>
<tbody>
{{range .}}
<tr>
<td class="fw-bold align-top">{{.Feature}}</td>
{{template "feature-cell" .Read}}
{{template "feature-cell" .Write}}
{{template "feature-cell" .Delete}}
{{template "feature-cell" .Action}}
</tr>
{{end}}
</tbody>
</table>
</div>
{{end}}
{{/* feature-cell renders one cell of the feature table (a []cmdCell). Hovering a
command shows its description via the title tooltip. */}}
{{define "feature-cell"}}
<td class="align-top">
{{- if . }}{{range .}}<div class="mb-1"><code title="{{.Description}}" style="cursor:help">{{.Template}}</code>{{if .Risky}} <span class="badge bg-warning-lt">risky</span>{{end}}</div>{{end}}{{else}}<span class="text-secondary"></span>{{end -}}
</td>
{{end}}
{{/* repstatus renders confirmation provenance + access badges for a *store.Repeater. */}}
{{define "repstatus"}}
{{- if not .Confirmed -}}
<span class="badge bg-yellow-lt" title="No one has reached this repeater through MeshTender yet">Unconfirmed</span>
{{- end -}}
{{- if and .AccessKnown (not .IsAdmin)}}<span class="badge bg-warning-lt">guest only</span>{{end -}}
{{end}}