mirror of
https://github.com/MeshTender/MeshTender.git
synced 2026-09-09 13:15:33 +00:00
111 lines
5.8 KiB
HTML
111 lines
5.8 KiB
HTML
{{define "title"}}Repeaters · MeshTender{{end}}
|
|
{{define "header"}}
|
|
<div class="row g-2 align-items-center">
|
|
<div class="col">
|
|
<div class="page-pretitle">Your equipment</div>
|
|
<h2 class="page-title">Repeaters</h2>
|
|
</div>
|
|
<div class="col-auto ms-auto d-print-none">
|
|
<a class="btn btn-primary" href="/repeaters/add">{{template "icon-plus" "me-1"}}Add repeater</a>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
{{define "content"}}
|
|
{{if .Error}}<div class="alert alert-danger" role="alert">{{.Error}}</div>{{end}}
|
|
|
|
{{if .Owned}}
|
|
<div class="row row-cards">
|
|
{{range .Owned}}
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-body py-3">
|
|
<div class="d-flex align-items-center gap-3">
|
|
<span class="avatar bg-blue-lt d-none d-sm-flex">{{template "icon-antenna" ""}}</span>
|
|
<div class="flex-fill" style="min-width:0">
|
|
<div class="d-flex align-items-center flex-wrap gap-2">
|
|
<h3 class="m-0 fs-3"><a class="text-reset text-decoration-none" href="/repeaters/{{.PublicID}}">{{.Name}}</a></h3>
|
|
{{template "repstatus" .}}
|
|
{{if index $.Reconsent .ID}}<a class="badge bg-warning-lt" href="/repeaters/{{.PublicID}}/share">re-consent needed</a>{{end}}
|
|
</div>
|
|
<div class="d-flex align-items-center flex-wrap gap-2 mt-1 text-secondary">
|
|
<span class="font-monospace">{{slice .PublicKeyHex 0 8}}…</span>
|
|
<button type="button" class="btn btn-icon btn-sm btn-ghost-secondary" title="Copy public key" aria-label="Copy public key" onclick="navigator.clipboard.writeText('{{.PublicKeyHex}}')">{{template "icon-copy" ""}}</button>
|
|
<span class="ms-1">·</span>
|
|
<span>{{template "sharetext" (index $.ShareCounts .ID)}}</span>
|
|
</div>
|
|
</div>
|
|
<div class="btn-list flex-nowrap">
|
|
<a class="btn btn-outline-primary" href="/repeaters/{{.PublicID}}/console">{{template "icon-terminal" "me-1"}}Console</a>
|
|
<div class="dropdown">
|
|
<button class="btn dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">Manage</button>
|
|
<div class="dropdown-menu dropdown-menu-end">
|
|
<a class="dropdown-item" href="/repeaters/{{.PublicID}}/edit">{{template "icon-pencil" "dropdown-item-icon"}}Edit details</a>
|
|
<a class="dropdown-item" href="/repeaters/{{.PublicID}}/confirm">{{template "icon-antenna" "dropdown-item-icon"}}Confirm access</a>
|
|
<a class="dropdown-item" href="/repeaters/{{.PublicID}}/log">{{template "icon-list" "dropdown-item-icon"}}Logs</a>
|
|
<a class="dropdown-item" href="/repeaters/{{.PublicID}}/share">{{template "icon-share" "dropdown-item-icon"}}Sharing</a>
|
|
<div class="dropdown-divider"></div>
|
|
<a class="dropdown-item text-danger" href="/repeaters/{{.PublicID}}/delete">{{template "icon-trash" "dropdown-item-icon"}}Delete repeater</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{if and .Confirmed .AccessKnown (not .IsAdmin)}}
|
|
<div class="alert alert-warning mt-3 mb-0">
|
|
MeshTender only has <strong>guest</strong> access here. Guest is available to anyone with a blank password, so there's no point operating at this level — re-run <code>setperm <your key> 3</code> on the repeater to grant admin, then re-test.
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{else}}
|
|
<div class="empty">
|
|
<div class="empty-icon">{{template "icon-antenna" ""}}</div>
|
|
<p class="empty-title">No repeaters yet</p>
|
|
<p class="empty-subtitle text-secondary">Add one to grant MeshTender access and test it with a modem.</p>
|
|
<div class="empty-action">
|
|
<a href="/repeaters/add" class="btn btn-primary">{{template "icon-plus" "me-1"}}Add repeater</a>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if .Shared}}
|
|
<h3 class="mt-4 mb-3">Shared with you</h3>
|
|
<div class="row row-cards">
|
|
{{range .Shared}}
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-body py-3">
|
|
<div class="d-flex align-items-center gap-3">
|
|
<span class="avatar bg-blue-lt d-none d-sm-flex">{{template "icon-antenna" ""}}</span>
|
|
<div class="flex-fill" style="min-width:0">
|
|
<div class="d-flex align-items-center flex-wrap gap-2">
|
|
<h3 class="m-0 fs-3"><a class="text-reset text-decoration-none" href="/repeaters/{{.PublicID}}">{{.Name}}</a></h3>
|
|
{{template "repstatus" .}}
|
|
</div>
|
|
<div class="d-flex align-items-center flex-wrap gap-2 mt-1 text-secondary">
|
|
<span class="font-monospace">{{slice .PublicKeyHex 0 8}}…</span>
|
|
<button type="button" class="btn btn-icon btn-sm btn-ghost-secondary" title="Copy public key" aria-label="Copy public key" onclick="navigator.clipboard.writeText('{{.PublicKeyHex}}')">{{template "icon-copy" ""}}</button>
|
|
<span class="ms-1">·</span>
|
|
<span>Shared by {{.OwnerName}}</span>
|
|
</div>
|
|
</div>
|
|
<div class="btn-list flex-nowrap">
|
|
<a class="btn btn-outline-primary" href="/repeaters/{{.PublicID}}/console">{{template "icon-terminal" "me-1"}}Console</a>
|
|
<a class="btn" href="/repeaters/{{.PublicID}}/confirm">Confirm</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
{{end}}
|
|
|
|
{{/* sharetext renders a repeater's sharing summary as plain text: e.g.
|
|
"Shared with 3 users, 2 organizations", omitting a zero count, or
|
|
"Not shared" when both are zero. Dot is a *store.ShareCount {Users, Orgs}. */}}
|
|
{{define "sharetext"}}{{if and (eq .Users 0) (eq .Orgs 0)}}Not shared{{else}}Shared with{{if gt .Users 0}} {{.Users}} user{{if ne .Users 1}}s{{end}}{{end}}{{if and (gt .Users 0) (gt .Orgs 0)}},{{end}}{{if gt .Orgs 0}} {{.Orgs}} organization{{if ne .Orgs 1}}s{{end}}{{end}}{{end}}{{end}}
|