diff --git a/meshview/templates/reach.html b/meshview/templates/reach.html
index 2fd9542..36b53a8 100644
--- a/meshview/templates/reach.html
+++ b/meshview/templates/reach.html
@@ -75,6 +75,21 @@
font-size: 0.9rem;
}
+.reach-gateway-panels {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 10px;
+ margin-top: 10px;
+}
+
+.reach-gateway-panel {
+ overflow-x: auto;
+}
+
+.reach-gateway-table {
+ min-width: 0;
+}
+
.reach-table th,
.reach-table td {
vertical-align: top;
@@ -116,6 +131,12 @@
.reach-muted {
color: rgba(255, 255, 255, 0.62);
}
+
+@media (max-width: 600px) {
+ .reach-gateway-panels {
+ grid-template-columns: 1fr;
+ }
+}
{% endblock %}
{% block body %}
@@ -170,22 +191,39 @@
-
-
-
-
- | Gateway |
- Heard Packets |
- Total Packets |
- Reach |
-
-
-
-
- | Loading packets... |
-
-
-
+
+
+
+
+
+ | Gateway |
+ Heard |
+ Reach |
+
+
+
+
+ | Loading packets... |
+
+
+
+
+
+
+
+
+ | Gateway |
+ Heard |
+ Reach |
+
+
+
+
+ | Loading packets... |
+
+
+
+
@@ -258,15 +296,23 @@ async function loadReachReport(nodeId = reachNodeId) {
reachNodeId = Number(nodeId);
const packetCountEl = document.getElementById("reach-packet-count");
const gatewayCountEl = document.getElementById("reach-gateway-count");
- const bodyEl = document.getElementById("reach-packet-body");
+ const bodyEls = [
+ document.getElementById("reach-packet-body-left"),
+ document.getElementById("reach-packet-body-right"),
+ ];
const bucketBodyEl = document.getElementById("reach-bucket-body");
const selectedNodeEl = document.getElementById("reach-node-id");
+ const setGatewayTables = html => {
+ bodyEls.forEach(el => {
+ el.innerHTML = html;
+ });
+ };
selectedNodeEl.textContent = reachNodeId;
packetCountEl.textContent = "...";
gatewayCountEl.textContent = "...";
bucketBodyEl.innerHTML = '
| Loading statistics... |
';
- bodyEl.innerHTML = '
| Loading packets... |
';
+ setGatewayTables('
| Loading packets... |
');
try {
const [packetData] = await Promise.all([
@@ -281,7 +327,7 @@ async function loadReachReport(nodeId = reachNodeId) {
if (packets.length === 0) {
gatewayCountEl.textContent = "0";
bucketBodyEl.innerHTML = '
| No packets found. |
';
- bodyEl.innerHTML = '
| No packets found. |
';
+ setGatewayTables('
| No packets found. |
');
return;
}
@@ -341,22 +387,26 @@ async function loadReachReport(nodeId = reachNodeId) {
`;
}).join("");
- bodyEl.innerHTML = gatewayRows.length
- ? gatewayRows.map(row => `
+ const renderGatewayRows = rows => rows.length
+ ? rows.map(row => `
| ${escapeHtml(gatewayLabel(row.nodeId, nodesById))} |
${row.heardCount} |
- ${packets.length} |
${row.percent.toFixed(1)}% |
`).join("")
- : '
| No gateways heard these packets. |
';
+ : '
| No gateways heard these packets. |
';
+ const splitIndex = Math.ceil(gatewayRows.length / 2);
+ bodyEls[0].innerHTML = renderGatewayRows(gatewayRows.slice(0, splitIndex));
+ bodyEls[1].innerHTML = gatewayRows.length > 1
+ ? renderGatewayRows(gatewayRows.slice(splitIndex))
+ : '
| No additional gateways. |
';
} catch (err) {
console.error("Failed to load reach report:", err);
packetCountEl.textContent = "!";
gatewayCountEl.textContent = "!";
bucketBodyEl.innerHTML = '
| Failed to load statistics. |
';
- bodyEl.innerHTML = '
| Failed to load report. |
';
+ setGatewayTables('
| Failed to load report. |
');
}
}
@@ -368,8 +418,10 @@ document.addEventListener("DOMContentLoaded", async () => {
if (!nodeId) {
document.getElementById("reach-bucket-body").innerHTML =
'
| Enter a valid node ID or select a node. |
';
- document.getElementById("reach-packet-body").innerHTML =
- '
| Enter a valid node ID or select a node. |
';
+ document.getElementById("reach-packet-body-left").innerHTML =
+ '
| Enter a valid node ID or select a node. |
';
+ document.getElementById("reach-packet-body-right").innerHTML =
+ '
| Enter a valid node ID or select a node. |
';
return;
}