Files
MeshTender/internal/core/templates/share.html
T

156 lines
6.8 KiB
HTML

{{define "title"}}Sharing · {{.Repeater.Name}} · MeshTender{{end}}
{{define "header"}}{{template "repeater-header" .Nav}}{{end}}
{{define "content"}}
{{template "repeater-tabs" .Nav}}
{{if .Error}}<div class="alert alert-danger">{{.Error}}</div>{{end}}
<div class="card">
<div class="card-body">
<p class="text-secondary mb-0">
Decide who can operate this repeater. Everyone you grant access uses MeshTender's single identity, so
you never hand out keys — and you can revoke or withdraw at any time.
</p>
</div>
</div>
<div class="row row-cards mt-1">
<div class="col-lg-7">
<div class="card">
<div class="card-header">
<h2 class="card-title">Share links</h2>
<div class="card-actions">
<button type="button" class="btn btn-primary" data-testid="new-invite"
data-bs-toggle="modal" data-bs-target="#invite-modal"
hx-get="/repeaters/{{.Repeater.PublicID}}/share/link/new"
hx-target="#invite-modal-content" hx-swap="innerHTML">{{template "icon-plus" "me-1"}}Create link</button>
</div>
</div>
<div class="card-body">
<p class="text-secondary mb-0">
Invite specific people with single-use links: the recipient signs in and accepts to control this
repeater from their own browser-connected KISS modem. Each link works once and disappears when it's
used — create one per person, label it, and choose what they can do. Links also
<strong>expire {{.InviteTTLDays}} days</strong> after you create them, so an unused one can't be
redeemed by whoever finds it later.
</p>
{{if .Invites}}
<div class="list-group list-group-flush mt-3">
{{range .Invites}}
<div class="list-group-item px-0" data-testid="invite-row">
<div class="d-flex align-items-center gap-2 mb-1">
<span class="fw-bold">{{if .Description}}{{.Description}}{{else}}(no label){{end}}</span>
{{if .Expired}}
<span class="badge bg-red-lt" data-testid="invite-expired">Expired</span>
{{else}}
<span class="badge bg-yellow-lt">Unused</span>
{{end}}
</div>
{{if .Expired}}
{{/* No copy control for a dead link — handing out a token that can't be
redeemed just produces a confused recipient. */}}
<p class="text-secondary mb-2">
Expired {{ ts .ExpiresAt "datetime" }} and can no longer be accepted. Create a new link instead.
</p>
{{else}}
<div class="input-group mb-2">
<code class="form-control font-monospace" id="link-{{.ID}}">{{$.BaseURL}}/invite/{{.Token}}</code>
<button type="button" class="btn" data-copy-target="#link-{{.ID}}">{{template "icon-copy" ""}}Copy</button>
</div>
<p class="text-secondary small mb-2">Expires {{ ts .ExpiresAt "datetime" }}</p>
{{end}}
<form method="post" action="/repeaters/{{$.Repeater.PublicID}}/share/link/delete" class="m-0">
<input type="hidden" name="invite_id" value="{{.ID}}">
<button type="submit" class="btn btn-sm btn-ghost-danger">
{{if .Expired}}Remove{{else}}Revoke link{{end}}
</button>
</form>
</div>
{{end}}
</div>
{{else}}
<p class="text-secondary mt-3 mb-0">No pending links.</p>
{{end}}
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h2 class="card-title">People with access</h2>
<div class="card-actions">
<button type="button" class="btn" data-testid="transfer-ownership"
data-bs-toggle="modal" data-bs-target="#transfer-modal"
hx-get="/repeaters/{{.Repeater.PublicID}}/transfer"
hx-target="#transfer-modal-content" hx-swap="innerHTML">Transfer ownership</button>
</div>
</div>
<div class="card-body">
<p class="text-secondary">
Mark a trusted person a <strong>steward</strong> to make them a co-operator: they can run
<strong>every</strong> command (including risky ones), just like you, and they're listed as a
backup maintainer on this repeater's public page — so the network knows who can service it if
you can't. Everyone else only gets the specific commands you grant them.
</p>
{{if .Shares}}
<div class="list-group list-group-flush">
{{range .Shares}}
<div class="list-group-item d-flex align-items-center gap-2 flex-wrap px-0" data-testid="share-person-row">
<span class="fw-bold">{{.Name}}</span>
<span class="text-secondary">@{{.Username}}</span>
{{if .Steward}}<span class="badge bg-azure-lt" title="Co-operator: can run every command, including risky ones">Steward · full access</span>{{end}}
<button type="button" class="btn btn-sm ms-auto" data-bs-toggle="modal" data-bs-target="#person-modal"
data-testid="manage-person"
hx-get="/repeaters/{{$.Repeater.PublicID}}/share/{{.UserID}}/access"
hx-target="#person-modal-content" hx-swap="innerHTML">Manage access</button>
</div>
{{end}}
</div>
{{else}}
<p class="text-secondary">No one has accepted yet.</p>
{{end}}
</div>
</div>
</div>
<div class="col-lg-5">
<div class="card">
<div class="card-body">
<h2 class="card-title">Organizations</h2>
<p class="text-secondary">
This repeater is shared with every organization you belong to, so their admins and members can run the
commands those organizations are permitted to run on it. Use <strong>Manage access</strong> to opt it
out of an organization or limit which commands that organization may run on <em>this</em> repeater.
</p>
{{if .Orgs}}
{{template "org-access-rows" .}}
{{else}}
<p class="text-secondary">Join an organization to share this repeater with it.</p>
{{end}}
</div>
</div>
</div>
</div>
<!-- Shared modals; the "Create single-use link", per-person "Manage access",
and "Transfer ownership" buttons load their fragments here via htmx. -->
<div class="modal modal-blur fade" id="invite-modal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-lg" role="document">
<div class="modal-content" id="invite-modal-content"></div>
</div>
</div>
<div class="modal modal-blur fade" id="person-modal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-lg" role="document">
<div class="modal-content" id="person-modal-content"></div>
</div>
</div>
<div class="modal modal-blur fade" id="transfer-modal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" role="document">
<div class="modal-content" id="transfer-modal-content"></div>
</div>
</div>
{{template "limits-modal-shell" .}}
<a class="back-link mt-3" href="/">{{template "icon-arrow-left" "me-1"}}Back to dashboard</a>
{{end}}