This commit is contained in:
Dobromir Popov
2026-07-09 12:16:12 +02:00
parent 1d3fb060ae
commit 3abd4176d7
6 changed files with 300 additions and 5 deletions

View File

@@ -4,6 +4,8 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>meshnet tracker</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="alternate icon" href="/favicon.ico">
<style>
:root { --bg:#0d1117; --panel:#161b22; --border:#30363d; --fg:#e6edf3;
--dim:#8b949e; --accent:#58a6ff; --ok:#3fb950; --bad:#f85149; --warn:#d29922;

View File

@@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" role="img" aria-label="meshnet">
<rect width="32" height="32" rx="7" fill="#0d1117"/>
<g stroke="#58a6ff" stroke-width="1.8" stroke-linecap="round">
<line x1="16" y1="7" x2="7" y2="24"/>
<line x1="16" y1="7" x2="25" y2="24"/>
<line x1="7" y1="24" x2="25" y2="24"/>
</g>
<circle cx="16" cy="7" r="3.2" fill="#58a6ff"/>
<circle cx="7" cy="24" r="3.2" fill="#3fb950"/>
<circle cx="25" cy="24" r="3.2" fill="#58a6ff"/>
</svg>

After

Width:  |  Height:  |  Size: 506 B

View File

@@ -2733,6 +2733,8 @@ class _TrackerHandler(http.server.BaseHTTPRequestHandler):
self._handle_registry_wallets()
elif parsed.path in ("/dashboard", "/dashboard/"):
self._handle_dashboard()
elif parsed.path in ("/favicon.svg", "/favicon.ico"):
self._handle_favicon()
elif parsed.path == "/v1/health":
self._send_json(200, {"status": "ok"})
else:
@@ -4302,14 +4304,20 @@ class _TrackerHandler(http.server.BaseHTTPRequestHandler):
def _handle_dashboard(self):
"""Serve the read-only web dashboard (US-035). Any tracker in the
mesh — leader or follower — serves it from its replicated state."""
self._serve_package_asset("dashboard.html", "text/html; charset=utf-8")
def _handle_favicon(self) -> None:
"""Serve the dashboard favicon (SVG; ICO path aliases the same asset)."""
self._serve_package_asset("favicon.svg", "image/svg+xml")
def _serve_package_asset(self, filename: str, content_type: str) -> None:
try:
html = files("meshnet_tracker").joinpath("dashboard.html").read_text()
body = files("meshnet_tracker").joinpath(filename).read_bytes()
except (FileNotFoundError, OSError):
self._send_json(404, {"error": "dashboard asset missing"})
self._send_json(404, {"error": f"{filename} missing"})
return
body = html.encode()
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Type", content_type)
self.send_header("Content-Length", str(len(body)))
self.end_headers()
try: