diff --git a/data/spot.py b/data/spot.py
index eae7187..07cc16a 100644
--- a/data/spot.py
+++ b/data/spot.py
@@ -102,6 +102,8 @@ class Spot:
sig_refs: list = None
# SIG reference names
sig_refs_names: list = None
+ # SIG reference URLs
+ sig_refs_urls: list = None
# Activation score. SOTA only
activation_score: int = None
diff --git a/spotproviders/gma.py b/spotproviders/gma.py
index f306972..c744127 100644
--- a/spotproviders/gma.py
+++ b/spotproviders/gma.py
@@ -36,6 +36,7 @@ class GMA(HTTPSpotProvider):
comment=source_spot["TEXT"],
sig_refs=[source_spot["REF"]],
sig_refs_names=[source_spot["NAME"]],
+ sig_refs_urls=["https://www.cqgma.org/zinfo.php?ref=" + source_spot["REF"]],
time=datetime.strptime(source_spot["DATE"] + source_spot["TIME"], "%Y%m%d%H%M").replace(
tzinfo=pytz.UTC).timestamp(),
dx_latitude=float(source_spot["LAT"]) if (source_spot["LAT"] and source_spot["LAT"] != "") else None,
diff --git a/spotproviders/pota.py b/spotproviders/pota.py
index ac2a90a..4a07c28 100644
--- a/spotproviders/pota.py
+++ b/spotproviders/pota.py
@@ -29,6 +29,7 @@ class POTA(HTTPSpotProvider):
sig="POTA",
sig_refs=[source_spot["reference"]],
sig_refs_names=[source_spot["name"]],
+ sig_refs_urls=["https://pota.app/#/park/" + source_spot["reference"]],
icon="tree",
time=datetime.strptime(source_spot["spotTime"], "%Y-%m-%dT%H:%M:%S").replace(tzinfo=pytz.UTC).timestamp(),
dx_grid=source_spot["grid6"],
diff --git a/spotproviders/sota.py b/spotproviders/sota.py
index 104b75d..ae6573d 100644
--- a/spotproviders/sota.py
+++ b/spotproviders/sota.py
@@ -50,6 +50,7 @@ class SOTA(HTTPSpotProvider):
sig="SOTA",
sig_refs=[source_spot["summitCode"]],
sig_refs_names=[source_spot["summitName"]],
+ sig_refs_urls=["https://www.sotadata.org.uk/en/summit/" + source_spot["summitCode"]],
icon="mountain-sun",
time=datetime.fromisoformat(source_spot["timeStamp"]).timestamp(),
activation_score=source_spot["points"])
diff --git a/spotproviders/wwbota.py b/spotproviders/wwbota.py
index 4906089..bf73da0 100644
--- a/spotproviders/wwbota.py
+++ b/spotproviders/wwbota.py
@@ -18,9 +18,16 @@ class WWBOTA(SSESpotProvider):
# n-fer activations.
refs = []
ref_names = []
+ ref_urls = []
for ref in source_spot["references"]:
refs.append(ref["reference"])
ref_names.append(ref["name"])
+ # Bunkerbase URLs only work for UK bunkers, so only add a URL if we have a B/G prefix. In theory this could
+ # lead to array alignment mismatches if there was e.g. a B/F bunker followed by a B/G one, we'd end up with
+ # the B/G URL in index 0. But in practice there are no overlaps between B/G bunkers and any others, so an
+ # activation will either be entirely B/G or not B/G at all.
+ if ref["reference"].startswith("B/G"):
+ ref_urls.append("https://bunkerwiki.org/?s=" + ref["reference"])
spot = Spot(source=self.name,
dx_call=source_spot["call"].upper(),
diff --git a/spotproviders/wwff.py b/spotproviders/wwff.py
index 4b089f7..60b8cb5 100644
--- a/spotproviders/wwff.py
+++ b/spotproviders/wwff.py
@@ -29,6 +29,7 @@ class WWFF(HTTPSpotProvider):
sig="WWFF",
sig_refs=[source_spot["reference"]],
sig_refs_names=[source_spot["reference_name"]],
+ sig_refs_urls=["https://wwff.co/directory/?showRef=" + source_spot["reference"]],
icon="seedling",
time=datetime.fromtimestamp(source_spot["spot_time"], tz=pytz.UTC).timestamp(),
dx_latitude=source_spot["latitude"],
diff --git a/webassets/apidocs/openapi.yml b/webassets/apidocs/openapi.yml
index a14e8e6..7d8d910 100644
--- a/webassets/apidocs/openapi.yml
+++ b/webassets/apidocs/openapi.yml
@@ -680,6 +680,12 @@ components:
type: string
description: SIG reference names
example: Null Country Park
+ sig_refs_urls:
+ type: array
+ items:
+ type: string
+ description: SIG reference URLs, which the user can look up for more information
+ example: "https://pota.app/#/park/GB-0001"
activation_score:
type: integer
description: Activation score. SOTA only
diff --git a/webassets/css/style.css b/webassets/css/style.css
index b993e2c..b827ee3 100644
--- a/webassets/css/style.css
+++ b/webassets/css/style.css
@@ -92,10 +92,13 @@ span.icon-wrapper {
}
span.freq-mhz {
+ font-weight: bold;
+}
+
+span.freq-mhz-pad {
display: inline-block;
min-width: 1.7em;
text-align: right;
- font-weight: bold;
}
span.freq-khz {
@@ -117,6 +120,10 @@ a.dx-link {
text-decoration: none;
font-weight: bold;
}
+a.sig-ref-link {
+ color: var(--bs-emphasis-color);
+ text-decoration: none;
+}
/* QRT/faded styles */
tr.table-faded td {
@@ -142,12 +149,6 @@ div#map {
font-family: var(--bs-body-font-family) !important;
}
-a.leaflet-popup-callsign-link {
- color: black;
- font-weight: bold;
- text-decoration: none;
-}
-
/* GENERAL MOBILE SUPPORT */
diff --git a/webassets/js/map.js b/webassets/js/map.js
index f8f8cae..41463c7 100644
--- a/webassets/js/map.js
+++ b/webassets/js/map.js
@@ -100,7 +100,13 @@ function getTooltipText(s) {
// Format sig_refs
var sig_refs = "";
- if (s["sig_refs"]) {
+ if (s["sig_refs"] && s["sig_refs_urls"] && s["sig_refs"].length == s["sig_refs_urls"].length) {
+ items = s["sig_refs"].map(s => `${s}`)
+ for (var i = 0; i < items.length; i++) {
+ items[i] = `${items[i]}`
+ }
+ sig_refs = items.join(", ");
+ } else if (s["sig_refs"]) {
sig_refs = s["sig_refs"].map(s => `${s}`).join(", ");
}
@@ -108,10 +114,13 @@ function getTooltipText(s) {
const shortCall = s["dx_call"].split("/").sort(function (a, b) {
return b.length - a.length;
})[0];
- ttt = `${dx_flag}
`;
+ ttt = `${dx_flag} ${s["dx_call"]}
`;
// Frequency & band
- ttt += ` ${freq_string} (${s["band"]})`;
+ ttt += ` ${freq_string}`;
+ if (s["band"] != null) {
+ ttt += ` (${s["band"]})`;
+ }
// Mode
if (s["mode"] != null) {
ttt += ` ${s["mode"]}`;
@@ -119,14 +128,14 @@ function getTooltipText(s) {
ttt += "
";
// Source / SIG / Ref
- ttt += ` ${sigSourceText} ${sig_refs}
`;
+ ttt += ` ${sigSourceText} ${sig_refs}
`;
// Time
- ttt += ` ${moment.unix(s["time"]).fromNow()}`;
+ ttt += ` ${moment.unix(s["time"]).fromNow()}`;
// Comment
if (commentText.length > 0) {
- ttt += `
${commentText}`;
+ ttt += `
${commentText}`;
}
return ttt;
diff --git a/webassets/js/spots.js b/webassets/js/spots.js
index 0e18287..4c5dabb 100644
--- a/webassets/js/spots.js
+++ b/webassets/js/spots.js
@@ -109,7 +109,7 @@ function updateTable() {
var khz = Math.floor((s["freq"] - (mhz * 1000000.0)) / 1000.0);
var hz = Math.floor(s["freq"] - (mhz * 1000000.0) - (khz * 1000.0));
var hz_string = (hz > 0) ? hz.toFixed(0)[0] : "";
- var freq_string = `${mhz.toFixed(0)}${khz.toFixed(0).padStart(3, '0')}${hz_string}`
+ var freq_string = `${mhz.toFixed(0)}${khz.toFixed(0).padStart(3, '0')}${hz_string}`
// Format the mode
mode_string = s["mode"];
@@ -148,7 +148,13 @@ function updateTable() {
// Format sig_refs
var sig_refs = "";
- if (s["sig_refs"]) {
+ if (s["sig_refs"] && s["sig_refs_urls"] && s["sig_refs"].length == s["sig_refs_urls"].length) {
+ items = s["sig_refs"].map(s => `${s}`)
+ for (var i = 0; i < items.length; i++) {
+ items[i] = `${items[i]}`
+ }
+ sig_refs = items.join(", ");
+ } else if (s["sig_refs"]) {
sig_refs = s["sig_refs"].map(s => `${s}`).join(", ");
}