Files
MeshTender/internal/core/templates/console.html
T
2026-07-05 17:37:35 -04:00

111 lines
5.6 KiB
HTML

{{define "title"}}Console · {{.Repeater.Name}} · MeshTender{{end}}
{{define "header"}}
<div class="row g-2 align-items-center">
<div class="col">
<div class="page-pretitle">Console</div>
<h2 class="page-title">{{.Repeater.Name}}</h2>
</div>
</div>
{{end}}
{{define "content"}}
<div class="alert alert-info" role="alert">
Connect a MeshCore KISS modem and send commands to this repeater. You can run the commands in the
Allowed commands list; the server enforces what you're allowed to send.
</div>
<div class="row row-cards">
<div class="col-12 col-lg-8">
<div class="card">
<div class="card-header"><h3 class="card-title">Console</h3></div>
<div class="card-body">
<div id="unsupported" class="alert alert-danger" role="alert" hidden>
This browser does not support WebSerial. Use Chrome, Edge, or another Chromium-based browser over HTTPS or on localhost.
</div>
<div class="mb-3">
<label class="form-label" for="path">Path <span class="form-label-description">optional</span></label>
<input type="text" class="form-control font-monospace" id="path" placeholder="e.g. 11, 22, 33" autocomplete="off" spellcheck="false">
<small class="form-hint">Hex hops from your modem to the repeater, in order, same length each (e.g. <code>11, 22, 33</code>). Leave blank to reach it by flood.</small>
</div>
<div class="btn-list">
<button id="connect" class="btn btn-primary" type="button">{{template "icon-plug" "me-1"}}Connect modem</button>
{{if .ShowConfig}}
<button type="button" class="btn btn-outline-primary" data-bs-toggle="collapse" data-bs-target="#config-panel" aria-expanded="false" aria-controls="config-panel" data-testid="apply-config">{{template "icon-settings" "me-1"}}Apply organization configuration…</button>
{{end}}
</div>
<ul id="log" class="evlog console mt-3" role="log" aria-live="polite" aria-label="Console activity"></ul>
<form id="cmdform" class="input-group mt-3" autocomplete="off" hidden>
<input type="text" id="cmdinput" class="form-control font-monospace" placeholder="type a command, e.g. ver" aria-label="Command to send">
<button type="submit" id="cmdsend" class="btn btn-primary">Send</button>
</form>
</div>
</div>
{{if .ShowConfig}}
<div class="collapse mt-3" id="config-panel"
data-config-url="/repeaters/{{.Repeater.PublicID}}/config.json"
data-location-url="/repeaters/{{.Repeater.PublicID}}/location">
<div class="card">
<div class="card-header"><h3 class="card-title">Apply organization configuration</h3></div>
<div class="card-body">
<p class="text-secondary">
Pick an organization and profile to see its recommended configuration for this repeater. Every command is
listed; the ones you're allowed to send show a Run button. Connect the modem to run them — results appear in
the console log above and next to each command.
</p>
<div class="row g-2 mb-3">
<div class="col-sm-6">
<label class="form-label" for="cfg-org">Organization</label>
<select id="cfg-org" class="form-select" data-cfg="org"></select>
</div>
<div class="col-sm-6">
<label class="form-label" for="cfg-profile">Profile</label>
<select id="cfg-profile" class="form-select" data-cfg="profile"></select>
</div>
</div>
<div data-cfg="location"></div>
<div id="config-map" data-cfg="map" style="height:220px;display:none" class="mb-3 rounded" role="region" aria-label="Pick the repeater's location"></div>
<div data-cfg="commands" data-testid="config-commands"></div>
</div>
<div class="card-footer d-flex align-items-center">
<span data-cfg="hint" class="text-secondary small" data-testid="config-hint"></span>
<div class="btn-list ms-auto">
<button type="button" class="btn btn-primary" data-cfg="connect" data-testid="config-connect">{{template "icon-plug" "me-1"}}<span data-cfg="connect-label">Connect modem</span></button>
<button type="button" class="btn btn-primary" data-cfg="run-all" data-testid="config-run-all">Run all</button>
</div>
</div>
</div>
</div>
{{end}}
</div>
<div class="col-12 col-lg-4">
<div class="card" data-testid="allowed-commands">
<div class="card-header"><h3 class="card-title">Allowed commands</h3></div>
<div class="card-body">
{{if .Commands}}
<div class="d-flex flex-wrap gap-1" style="max-height:360px;overflow-y:auto">
{{range .Commands}}
<button type="button" class="chip btn btn-sm{{if .Risky}} btn-outline-danger{{end}}" data-template="{{.Template}}" title="{{.Args}}">{{.Template}}</button>
{{end}}
</div>
{{else}}
<p class="text-secondary mb-0">No commands allowed here yet.</p>
{{end}}
</div>
</div>
</div>
</div>
<a class="back-link mt-3" href="/">{{template "icon-arrow-left" "me-1"}}Back to dashboard</a>
{{if .ShowConfig}}
<link rel="stylesheet" href="/static/leaflet.css">
<script src="/static/leaflet.js"></script>
<script src="/static/regionmap.js"></script>
<script src="/static/console-config.js"></script>
{{end}}
<script nonce="{{.Nonce}}">
window.MESHTENDER_WS = (location.protocol === "https:" ? "wss://" : "ws://") + location.host + "/repeaters/{{.Repeater.PublicID}}/console/ws";
</script>
<script src="/static/console.js"></script>
{{end}}