Add "Only show MQTT neighbors" map option

Adds a sub-option under "Show all neighbors" that filters neighbor lines
to only direct (MQTT) connections, hiding multi-hop path connections.
Defaults to off. Also hides the path-traffic gradient legend rows when
the option is enabled, leaving the "MQTT connections" entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alex Vanderpot
2026-06-19 01:52:19 -04:00
parent 819b81d899
commit 8c3eb6ccc7
3 changed files with 62 additions and 33 deletions
@@ -189,6 +189,24 @@ export default function MapLayerSettingsComponent({ onSettingsChange }: MapLayer
</span>
</label>
{/* Only show MQTT neighbors - indented sub-option */}
<label className="flex items-center gap-2 ml-6 cursor-pointer">
<input
type="checkbox"
checked={settings.onlyMqttNeighbors}
onChange={(e) => updateSetting('onlyMqttNeighbors', e.target.checked)}
disabled={!settings.showAllNeighbors}
className="rounded"
/>
<span className={`text-sm ${
settings.showAllNeighbors
? 'text-gray-700 dark:text-gray-300'
: 'text-gray-400 dark:text-gray-500'
}`}>
Only show MQTT neighbors
</span>
</label>
{/* Minimum packet count - indented sub-option */}
<div className="ml-6 mb-3">
<label className={`block text-sm ${
+42 -33
View File
@@ -420,13 +420,15 @@ function AllNeighborLines({
nodes,
useColors = true,
minPacketCount = 1,
strokeWidth = 2
}: {
connections: AllNeighborsConnection[];
strokeWidth = 2,
onlyMqtt = false
}: {
connections: AllNeighborsConnection[];
nodes: NodePosition[];
useColors?: boolean;
minPacketCount?: number;
strokeWidth?: number;
onlyMqtt?: boolean;
}) {
if (connections.length === 0) return null;
@@ -435,10 +437,11 @@ function AllNeighborLines({
// Filter connections to only show lines between nodes that are visible on the map
// and meet the minimum packet count threshold
const visibleConnections = connections.filter(connection =>
visibleNodeIds.has(connection.source_node) &&
const visibleConnections = connections.filter(connection =>
visibleNodeIds.has(connection.source_node) &&
visibleNodeIds.has(connection.target_node) &&
connection.packet_count >= minPacketCount
connection.packet_count >= minPacketCount &&
(!onlyMqtt || connection.connection_type === 'direct')
);
// Calculate logarithmic thresholds based on packet counts for path connections
@@ -548,6 +551,7 @@ export default function MapView({ target = '_self' }: MapViewProps = {}) {
tileLayer: "openstreetmap",
showAllNeighbors: false,
useColors: true,
onlyMqttNeighbors: false,
nodeTypes: ["meshcore"],
showMeshcoreCoverageOverlay: false,
minPacketCount: 1,
@@ -891,6 +895,7 @@ export default function MapView({ target = '_self' }: MapViewProps = {}) {
useColors={mapLayerSettings.useColors}
minPacketCount={mapLayerSettings.minPacketCount}
strokeWidth={mapLayerSettings.strokeWidth}
onlyMqtt={mapLayerSettings.onlyMqttNeighbors}
/>
)}
</MapContainer>
@@ -920,7 +925,7 @@ export default function MapView({ target = '_self' }: MapViewProps = {}) {
t4: Math.round(Math.pow(10, logMin + logRange * 0.8)),
max
};
})() : null;
})() : (mapLayerSettings.onlyMqttNeighbors ? { min: 1, t1: 1, t2: 1, t3: 1, t4: 1, max: 1 } : null);
return legendThresholds && (
<div style={{
@@ -936,34 +941,38 @@ export default function MapView({ target = '_self' }: MapViewProps = {}) {
fontFamily: 'monospace'
}}>
<div style={{ fontWeight: 'bold', marginBottom: '8px' }}>
Path Traffic
{mapLayerSettings.onlyMqttNeighbors ? 'Neighbors' : 'Path Traffic'}
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#dc2626' }}></div>
<span>High: {legendThresholds.t4}+ packets</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#ea580c' }}></div>
<span>Med-High: {legendThresholds.t3}-{legendThresholds.t4 - 1}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#f59e0b' }}></div>
<span>Medium: {legendThresholds.t2}-{legendThresholds.t3 - 1}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#eab308' }}></div>
<span>Low-Med: {legendThresholds.t1}-{legendThresholds.t2 - 1}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#84cc16' }}></div>
<span>Low: {legendThresholds.min + 1}-{legendThresholds.t1 - 1}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#6b7280' }}></div>
<span>Minimal: {legendThresholds.min}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginTop: '4px', paddingTop: '4px', borderTop: '1px solid #e5e7eb' }}>
{!mapLayerSettings.onlyMqttNeighbors && (
<>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#dc2626' }}></div>
<span>High: {legendThresholds.t4}+ packets</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#ea580c' }}></div>
<span>Med-High: {legendThresholds.t3}-{legendThresholds.t4 - 1}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#f59e0b' }}></div>
<span>Medium: {legendThresholds.t2}-{legendThresholds.t3 - 1}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#eab308' }}></div>
<span>Low-Med: {legendThresholds.t1}-{legendThresholds.t2 - 1}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#84cc16' }}></div>
<span>Low: {legendThresholds.min + 1}-{legendThresholds.t1 - 1}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#6b7280' }}></div>
<span>Minimal: {legendThresholds.min}</span>
</div>
</>
)}
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', ...(mapLayerSettings.onlyMqttNeighbors ? {} : { marginTop: '4px', paddingTop: '4px', borderTop: '1px solid #e5e7eb' }) }}>
<div style={{ width: '20px', height: '2px', backgroundColor: '#8b5cf6' }}></div>
<span>MQTT connections</span>
</div>
@@ -10,6 +10,7 @@ export interface MapLayerSettings {
tileLayer: string;
showAllNeighbors: boolean;
useColors: boolean;
onlyMqttNeighbors: boolean;
nodeTypes: NodeType[];
showMeshcoreCoverageOverlay: boolean;
minPacketCount: number;
@@ -23,6 +24,7 @@ const DEFAULT_MAP_LAYER_SETTINGS: MapLayerSettings = {
tileLayer: "openstreetmap",
showAllNeighbors: false,
useColors: true,
onlyMqttNeighbors: false,
nodeTypes: ["meshcore"],
showMeshcoreCoverageOverlay: false,
minPacketCount: 1,