[feat](trx-frontend-http): add rig source filter to map view

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-21 18:22:55 +01:00
parent 1078fb23ed
commit 9c1c7b9ff1
2 changed files with 64 additions and 1 deletions
@@ -938,6 +938,26 @@ function applyRigList(activeRigId, rigIds, displayNames) {
updateRigSubtitle(activeRigId); updateRigSubtitle(activeRigId);
if (typeof setSchedulerRig === "function") setSchedulerRig(lastActiveRigId); if (typeof setSchedulerRig === "function") setSchedulerRig(lastActiveRigId);
if (typeof setBackgroundDecodeRig === "function") setBackgroundDecodeRig(lastActiveRigId); if (typeof setBackgroundDecodeRig === "function") setBackgroundDecodeRig(lastActiveRigId);
updateMapRigFilter();
}
function updateMapRigFilter() {
const el = document.getElementById("map-rig-filter");
if (!el) return;
const prev = el.value;
while (el.options.length > 1) el.remove(1);
for (const id of lastRigIds) {
const opt = document.createElement("option");
opt.value = id;
opt.textContent = lastRigDisplayNames[id] || id;
el.appendChild(opt);
}
if (prev && lastRigIds.includes(prev)) {
el.value = prev;
} else {
el.value = "";
mapRigFilter = "";
}
} }
async function refreshRigList() { async function refreshRigList() {
@@ -4095,6 +4115,7 @@ const DEFAULT_MAP_SOURCE_FILTER = { ais: true, vdes: true, aprs: true, bookmark:
const mapFilter = { ...DEFAULT_MAP_SOURCE_FILTER }; const mapFilter = { ...DEFAULT_MAP_SOURCE_FILTER };
const mapLocatorFilter = { phase: "band", bands: new Set() }; const mapLocatorFilter = { phase: "band", bands: new Set() };
let mapSearchFilter = ""; let mapSearchFilter = "";
let mapRigFilter = ""; // "" = all rigs
let mapHistoryPruneTimer = null; let mapHistoryPruneTimer = null;
let mapHistoryLimitMinutes = normalizeMapHistoryLimitMinutes( let mapHistoryLimitMinutes = normalizeMapHistoryLimitMinutes(
Number(loadSetting("mapHistoryLimitMinutes", 1440)) Number(loadSetting("mapHistoryLimitMinutes", 1440))
@@ -4248,6 +4269,7 @@ function ensureAisMarker(key, entry) {
.addTo(aprsMap) .addTo(aprsMap)
.bindPopup(buildAisPopupHtml(entry.msg)); .bindPopup(buildAisPopupHtml(entry.msg));
marker.__trxType = "ais"; marker.__trxType = "ais";
marker.__trxRigIds = entry.rigIds || new Set();
marker._aisMmsi = String(key); marker._aisMmsi = String(key);
entry.marker = marker; entry.marker = marker;
mapMarkers.add(marker); mapMarkers.add(marker);
@@ -4262,6 +4284,7 @@ function ensureVdesMarker(key, entry) {
fillOpacity: 0.82, fillOpacity: 0.82,
}).addTo(aprsMap).bindPopup(buildVdesPopupHtml(entry.msg)); }).addTo(aprsMap).bindPopup(buildVdesPopupHtml(entry.msg));
marker.__trxType = "vdes"; marker.__trxType = "vdes";
marker.__trxRigIds = entry.rigIds || new Set();
marker._vdesKey = String(key); marker._vdesKey = String(key);
entry.marker = marker; entry.marker = marker;
mapMarkers.add(marker); mapMarkers.add(marker);
@@ -4277,6 +4300,7 @@ function ensureDecodeLocatorMarker(entry) {
.addTo(aprsMap) .addTo(aprsMap)
.bindPopup(tooltipHtml); .bindPopup(tooltipHtml);
marker.__trxType = entry.sourceType; marker.__trxType = entry.sourceType;
marker.__trxRigIds = entry.rigIds || new Set();
sendLocatorOverlayToBack(marker); sendLocatorOverlayToBack(marker);
assignLocatorMarkerMeta(marker, entry.sourceType, entry.bandMeta); assignLocatorMarkerMeta(marker, entry.sourceType, entry.bandMeta);
entry.marker = marker; entry.marker = marker;
@@ -5575,6 +5599,13 @@ function initAprsMap() {
applyMapFilter(); applyMapFilter();
}); });
} }
const mapRigFilterEl = document.getElementById("map-rig-filter");
if (mapRigFilterEl) {
mapRigFilterEl.addEventListener("change", () => {
mapRigFilter = mapRigFilterEl.value;
applyMapFilter();
});
}
if (mapSearchEl) { if (mapSearchEl) {
mapSearchEl.value = mapSearchFilter; mapSearchEl.value = mapSearchFilter;
mapSearchEl.addEventListener("input", () => { mapSearchEl.addEventListener("input", () => {
@@ -6018,6 +6049,7 @@ function _aprsAddMarkerToMap(call, entry) {
radius: 6, color: "#00d17f", fillColor: "#00d17f", fillOpacity: 0.8 radius: 6, color: "#00d17f", fillColor: "#00d17f", fillOpacity: 0.8
}).addTo(aprsMap).bindPopup(popupContent); }).addTo(aprsMap).bindPopup(popupContent);
marker.__trxType = "aprs"; marker.__trxType = "aprs";
marker.__trxRigIds = entry.rigIds || new Set();
marker._aprsCall = call; marker._aprsCall = call;
entry.marker = marker; entry.marker = marker;
mapMarkers.add(marker); mapMarkers.add(marker);
@@ -6034,6 +6066,10 @@ window.aprsMapAddStation = function(call, lat, lon, info, symbolTable, symbolCod
existing.info = info; existing.info = info;
existing.symbolTable = symbolTable; existing.symbolTable = symbolTable;
existing.symbolCode = symbolCode; existing.symbolCode = symbolCode;
if (lastActiveRigId) {
if (!existing.rigIds) existing.rigIds = new Set();
existing.rigIds.add(lastActiveRigId);
}
if (!Array.isArray(existing.trackHistory)) existing.trackHistory = []; if (!Array.isArray(existing.trackHistory)) existing.trackHistory = [];
const prevPoint = existing.trackHistory[existing.trackHistory.length - 1]; const prevPoint = existing.trackHistory[existing.trackHistory.length - 1];
if (!aprsPositionsEqual(prevPoint, nextPoint)) { if (!aprsPositionsEqual(prevPoint, nextPoint)) {
@@ -6059,6 +6095,7 @@ window.aprsMapAddStation = function(call, lat, lon, info, symbolTable, symbolCod
info, info,
symbolTable, symbolTable,
symbolCode, symbolCode,
rigIds: new Set(lastActiveRigId ? [lastActiveRigId] : []),
}; };
stationMarkers.set(call, entry); stationMarkers.set(call, entry);
pruneAprsEntry(call, entry, mapHistoryCutoffMs()); pruneAprsEntry(call, entry, mapHistoryCutoffMs());
@@ -6156,6 +6193,10 @@ window.aisMapAddVessel = function(msg) {
const existing = aisMarkers.get(key); const existing = aisMarkers.get(key);
if (existing) { if (existing) {
existing.msg = msg; existing.msg = msg;
if (lastActiveRigId) {
if (!existing.rigIds) existing.rigIds = new Set();
existing.rigIds.add(lastActiveRigId);
}
if (!Array.isArray(existing.trackHistory)) existing.trackHistory = []; if (!Array.isArray(existing.trackHistory)) existing.trackHistory = [];
const prevPoint = existing.trackHistory[existing.trackHistory.length - 1]; const prevPoint = existing.trackHistory[existing.trackHistory.length - 1];
if (!aisPositionsEqual(prevPoint, nextPoint)) { if (!aisPositionsEqual(prevPoint, nextPoint)) {
@@ -6175,6 +6216,7 @@ window.aisMapAddVessel = function(msg) {
trackHistory: [{ lat: msg.lat, lon: msg.lon, tsMs }], trackHistory: [{ lat: msg.lat, lon: msg.lon, tsMs }],
trackPoints: [nextPoint], trackPoints: [nextPoint],
msg, msg,
rigIds: new Set(lastActiveRigId ? [lastActiveRigId] : []),
}); });
pruneAisEntry(key, aisMarkers.get(key), mapHistoryCutoffMs()); pruneAisEntry(key, aisMarkers.get(key), mapHistoryCutoffMs());
if (aisMarkers.get(key)?.visibleInHistoryWindow) ensureAisMarker(key, aisMarkers.get(key)); if (aisMarkers.get(key)?.visibleInHistoryWindow) ensureAisMarker(key, aisMarkers.get(key));
@@ -6192,6 +6234,10 @@ window.vdesMapAddPoint = function(msg) {
if (existing) { if (existing) {
existing.msg = msg; existing.msg = msg;
existing.visibleInHistoryWindow = visible; existing.visibleInHistoryWindow = visible;
if (lastActiveRigId) {
if (!existing.rigIds) existing.rigIds = new Set();
existing.rigIds.add(lastActiveRigId);
}
if (!visible) { if (!visible) {
if (!decodeHistoryMapRenderingDeferred()) { if (!decodeHistoryMapRenderingDeferred()) {
setRetainedMapMarkerVisible(existing.marker, false); setRetainedMapMarkerVisible(existing.marker, false);
@@ -6216,6 +6262,7 @@ window.vdesMapAddPoint = function(msg) {
marker: null, marker: null,
msg, msg,
visibleInHistoryWindow: visible, visibleInHistoryWindow: visible,
rigIds: new Set(lastActiveRigId ? [lastActiveRigId] : []),
}; };
vdesMarkers.set(key, entry); vdesMarkers.set(key, entry);
if (!visible) return; if (!visible) return;
@@ -6305,10 +6352,14 @@ function applyMapFilter() {
const sourceVisible = noneSelected const sourceVisible = noneSelected
? DEFAULT_MAP_SOURCE_FILTER[type] !== undefined ? DEFAULT_MAP_SOURCE_FILTER[type] : true ? DEFAULT_MAP_SOURCE_FILTER[type] !== undefined ? DEFAULT_MAP_SOURCE_FILTER[type] : true
: !!mapFilter[type]; : !!mapFilter[type];
const rigVisible = !mapRigFilter
|| marker.__trxType === "bookmark"
|| (marker.__trxRigIds instanceof Set && marker.__trxRigIds.has(mapRigFilter));
const visible = marker.__trxHistoryVisible !== false const visible = marker.__trxHistoryVisible !== false
&& markerPassesSearchFilter(marker) && markerPassesSearchFilter(marker)
&& markerPassesLocatorFilters(marker) && markerPassesLocatorFilters(marker)
&& sourceVisible; && sourceVisible
&& rigVisible;
const onMap = aprsMap.hasLayer(marker); const onMap = aprsMap.hasLayer(marker);
if (visible && !onMap) { if (visible && !onMap) {
marker.addTo(aprsMap); marker.addTo(aprsMap);
@@ -6929,6 +6980,7 @@ window.mapAddLocator = function(message, grids, type = "ft8", station = null, de
dt_s: Number.isFinite(details?.dt_s) ? Number(details.dt_s) : null, dt_s: Number.isFinite(details?.dt_s) ? Number(details.dt_s) : null,
freq_hz: Number.isFinite(details?.freq_hz) ? Number(details.freq_hz) : null, freq_hz: Number.isFinite(details?.freq_hz) ? Number(details.freq_hz) : null,
message: String(details?.message || message || "").trim() || null, message: String(details?.message || message || "").trim() || null,
rig_id: lastActiveRigId || null,
}; };
const detailKey = detailStationId || `${targetId || "decode"}:${detailEntry.message || "decode"}:${detailEntry.ts_ms || Date.now()}`; const detailKey = detailStationId || `${targetId || "decode"}:${detailEntry.message || "decode"}:${detailEntry.ts_ms || Date.now()}`;
const key = `${markerType}:${grid}`; const key = `${markerType}:${grid}`;
@@ -6942,6 +6994,10 @@ window.mapAddLocator = function(message, grids, type = "ft8", station = null, de
} }
existing.allStationDetails.set(detailKey, { ...detailEntry }); existing.allStationDetails.set(detailKey, { ...detailEntry });
existing.sourceType = markerType; existing.sourceType = markerType;
if (lastActiveRigId) {
if (!existing.rigIds) existing.rigIds = new Set();
existing.rigIds.add(lastActiveRigId);
}
pruneLocatorEntry(key, existing, mapHistoryCutoffMs()); pruneLocatorEntry(key, existing, mapHistoryCutoffMs());
if (existing.marker) sendLocatorOverlayToBack(existing.marker); if (existing.marker) sendLocatorOverlayToBack(existing.marker);
scheduleDecodeMapMaintenance(); scheduleDecodeMapMaintenance();
@@ -6958,6 +7014,7 @@ window.mapAddLocator = function(message, grids, type = "ft8", station = null, de
allStationDetails, allStationDetails,
sourceType: markerType, sourceType: markerType,
bandMeta: new Map(), bandMeta: new Map(),
rigIds: new Set(lastActiveRigId ? [lastActiveRigId] : []),
}; };
locatorMarkers.set(key, entry); locatorMarkers.set(key, entry);
pruneLocatorEntry(key, entry, mapHistoryCutoffMs()); pruneLocatorEntry(key, entry, mapHistoryCutoffMs());
@@ -746,6 +746,12 @@
<span class="map-locator-filter-label" id="map-locator-choice-label">Show</span> <span class="map-locator-filter-label" id="map-locator-choice-label">Show</span>
<div id="map-locator-choice-filter" class="map-locator-chip-row"></div> <div id="map-locator-choice-filter" class="map-locator-chip-row"></div>
</div> </div>
<div class="map-locator-filter-group">
<span class="map-locator-filter-label">Rig</span>
<select id="map-rig-filter" class="map-history-select" aria-label="Filter by rig source">
<option value="">All</option>
</select>
</div>
<div class="map-locator-filter-group"> <div class="map-locator-filter-group">
<span class="map-locator-filter-label">Search</span> <span class="map-locator-filter-label">Search</span>
<input type="text" id="map-search-filter" class="map-search-input" placeholder="Callsign, MMSI, locator, message..." /> <input type="text" id="map-search-filter" class="map-search-input" placeholder="Callsign, MMSI, locator, message..." />