Files
MeshTender/internal/web/templates/org_repeaters.html
T
2026-07-30 08:46:19 -04:00

86 lines
3.5 KiB
HTML

{{define "title"}}Repeaters · {{.Org.Name}} · MeshTender{{end}}
{{define "header"}}{{template "org-header" .}}{{end}}
{{/* rep-rows renders the repeater list items; shared by the full page and the
htmx "show more" fragment so appended pages match the first. */}}
{{define "rep-rows"}}
{{range .Reps.Repeaters}}
{{if $.Reps.Full}}
<a class="list-group-item list-group-item-action d-flex align-items-center gap-2" href="/repeaters/{{.RepeaterPublicID}}">
<span class="text-secondary">{{template "icon-antenna" ""}}</span>
<div class="flex-fill text-truncate">
<span class="fw-bold">{{.Name}}</span>
<div class="text-secondary small">owner {{.OwnerName}}</div>
</div>
</a>
{{else}}
<div class="list-group-item d-flex align-items-center gap-2">
<span class="text-secondary">{{template "icon-antenna" ""}}</span>
<div class="flex-fill text-truncate">
<span class="fw-bold">{{.Name}}</span>
</div>
</div>
{{end}}
{{end}}
{{end}}
{{/* rep-more is the public list's "show more" control; replaces itself with the
next page's rows + a fresh control (the cursor carries the keyset position). */}}
{{define "rep-more"}}
<div class="list-group-item text-center" id="rep-more">
<button class="btn btn-outline-secondary" hx-get="/orgs/{{.Org.Slug}}/repeaters?cursor={{.Reps.NextCursor}}" hx-target="#rep-more" hx-swap="outerHTML">
Show more repeaters
</button>
</div>
{{end}}
{{/* rep-frag is the htmx response: rows + next control, no page chrome. */}}
{{define "rep-frag"}}{{template "rep-rows" .}}{{if .Reps.NextCursor}}{{template "rep-more" .}}{{end}}{{end}}
{{define "content"}}
{{template "org-tabs" .Nav}}
<div class="row row-cards">
<!-- Left: list -->
<div class="col-lg-8">
<div class="card">
<div class="card-header"><h2 class="card-title">Shared repeaters</h2></div>
{{if .Reps.Repeaters}}
<div class="list-group list-group-flush" id="rep-list">
{{template "rep-rows" .}}
{{if .Reps.NextCursor}}{{template "rep-more" .}}{{end}}
</div>
{{else}}
<div class="card-body"><p class="text-secondary mb-0">
{{if .Reps.Full}}No repeaters are shared yet. A member's repeaters are shared automatically; they can opt one out from its sharing page.
{{else}}No repeaters are shown publicly. Members can show a repeater on public organization pages when editing it.{{end}}
</p></div>
{{end}}
</div>
</div>
<!-- Right: map -->
<div class="col-lg-4">
<div class="card">
<div class="card-header"><h2 class="card-title">Map</h2></div>
{{if .Reps.HasMap}}
<div class="card-body p-2">
<link rel="stylesheet" href="{{ asset "/static/leaflet.css" }}">
<link rel="stylesheet" href="{{ asset "/static/leaflet.markercluster.css" }}">
<div id="map" style="height:300px" role="region" aria-label="Map of organization repeater locations"></div>
<script src="{{ asset "/static/leaflet.js" }}"></script>
<script src="{{ asset "/static/leaflet.markercluster.js" }}"></script>
<script src="{{ asset "/static/meshmap.js" }}"></script>
<script nonce="{{.Nonce}}">
{{if .MapURL}}meshMapFromURL('map', {{.MapURL}});{{else}}meshMap('map', [
{{range .Reps.MapPoints}}{name: {{.Name}}, lat: {{.Lat}}, lon: {{.Lon}}},{{end}}
]);{{end}}
</script>
</div>
{{else}}
<div class="card-body"><p class="text-secondary mb-0">No repeater locations to map.</p></div>
{{end}}
</div>
</div>
</div>
{{end}}