mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-05-30 17:35:11 +00:00
Bug fixes and performance improvements
This commit is contained in:
@@ -40,7 +40,7 @@ class HTTPAlertProvider(AlertProvider):
|
|||||||
try:
|
try:
|
||||||
# Request data from API
|
# Request data from API
|
||||||
logging.debug("Polling " + self.name + " alert API...")
|
logging.debug("Polling " + self.name + " alert API...")
|
||||||
http_response = requests.get(self._url, headers=HTTP_HEADERS)
|
http_response = requests.get(self._url, headers=HTTP_HEADERS, timeout=(5, 30))
|
||||||
# Pass off to the subclass for processing
|
# Pass off to the subclass for processing
|
||||||
new_alerts = self._http_response_to_alerts(http_response)
|
new_alerts = self._http_response_to_alerts(http_response)
|
||||||
# Submit the new alerts for processing. There might not be any alerts for the less popular programs.
|
# Submit the new alerts for processing. There might not be any alerts for the less popular programs.
|
||||||
|
|||||||
@@ -70,27 +70,24 @@ def populate_sig_ref_info(sig_ref):
|
|||||||
elif sig.upper() == "WWFF":
|
elif sig.upper() == "WWFF":
|
||||||
wwff_csv_data = SEMI_STATIC_URL_DATA_CACHE.get("https://wwff.co/wwff-data/wwff_directory.csv",
|
wwff_csv_data = SEMI_STATIC_URL_DATA_CACHE.get("https://wwff.co/wwff-data/wwff_directory.csv",
|
||||||
headers=HTTP_HEADERS)
|
headers=HTTP_HEADERS)
|
||||||
wwff_dr = csv.DictReader(wwff_csv_data.content.decode().splitlines())
|
wwff_index = {row["reference"]: row for row in csv.DictReader(wwff_csv_data.content.decode().splitlines())}
|
||||||
for row in wwff_dr:
|
row = wwff_index.get(ref_id)
|
||||||
if row["reference"] == ref_id:
|
if row:
|
||||||
sig_ref.name = row["name"] if "name" in row else None
|
sig_ref.name = row["name"] if "name" in row else None
|
||||||
sig_ref.url = "https://wwff.co/directory/?showRef=" + ref_id
|
sig_ref.url = "https://wwff.co/directory/?showRef=" + ref_id
|
||||||
sig_ref.grid = row["iaruLocator"] if "iaruLocator" in row and row["iaruLocator"] != "-" else None
|
sig_ref.grid = row["iaruLocator"] if "iaruLocator" in row and row["iaruLocator"] != "-" else None
|
||||||
sig_ref.latitude = float(row["latitude"]) if "latitude" in row and row["latitude"] != "-" else None
|
sig_ref.latitude = float(row["latitude"]) if "latitude" in row and row["latitude"] != "-" else None
|
||||||
sig_ref.longitude = float(row["longitude"]) if "longitude" in row and row[
|
sig_ref.longitude = float(row["longitude"]) if "longitude" in row and row["longitude"] != "-" else None
|
||||||
"longitude"] != "-" else None
|
|
||||||
break
|
|
||||||
elif sig.upper() == "SIOTA":
|
elif sig.upper() == "SIOTA":
|
||||||
siota_csv_data = SEMI_STATIC_URL_DATA_CACHE.get("https://www.silosontheair.com/data/silos.csv",
|
siota_csv_data = SEMI_STATIC_URL_DATA_CACHE.get("https://www.silosontheair.com/data/silos.csv",
|
||||||
headers=HTTP_HEADERS)
|
headers=HTTP_HEADERS)
|
||||||
siota_dr = csv.DictReader(siota_csv_data.content.decode().splitlines())
|
siota_index = {row["SILO_CODE"]: row for row in csv.DictReader(siota_csv_data.content.decode().splitlines())}
|
||||||
for row in siota_dr:
|
row = siota_index.get(ref_id)
|
||||||
if row["SILO_CODE"] == ref_id:
|
if row:
|
||||||
sig_ref.name = row["NAME"] if "NAME" in row else None
|
sig_ref.name = row["NAME"] if "NAME" in row else None
|
||||||
sig_ref.grid = row["LOCATOR"] if "LOCATOR" in row else None
|
sig_ref.grid = row["LOCATOR"] if "LOCATOR" in row else None
|
||||||
sig_ref.latitude = float(row["LAT"]) if "LAT" in row else None
|
sig_ref.latitude = float(row["LAT"]) if "LAT" in row else None
|
||||||
sig_ref.longitude = float(row["LNG"]) if "LNG" in row else None
|
sig_ref.longitude = float(row["LNG"]) if "LNG" in row else None
|
||||||
break
|
|
||||||
elif sig.upper() == "WOTA":
|
elif sig.upper() == "WOTA":
|
||||||
data = SEMI_STATIC_URL_DATA_CACHE.get("https://www.wota.org.uk/mapping/data/summits.json",
|
data = SEMI_STATIC_URL_DATA_CACHE.get("https://www.wota.org.uk/mapping/data/summits.json",
|
||||||
headers=HTTP_HEADERS).json()
|
headers=HTTP_HEADERS).json()
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ class APISpotHandler(tornado.web.RequestHandler):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Reject if format not json
|
# Reject if format not json
|
||||||
if 'Content-Type' not in self.request.headers or self.request.headers.get(
|
if not self.request.headers.get('Content-Type', '').startswith("application/json"):
|
||||||
'Content-Type') != "application/json":
|
|
||||||
self.set_status(415)
|
self.set_status(415)
|
||||||
self.write(
|
self.write(
|
||||||
json.dumps("Error - request Content-Type must be application/json", default=serialize_everything))
|
json.dumps("Error - request Content-Type must be application/json", default=serialize_everything))
|
||||||
@@ -139,7 +138,7 @@ class APISpotHandler(tornado.web.RequestHandler):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
self.write(json.dumps("Error - " + str(e), default=serialize_everything))
|
self.write(json.dumps("Error - an internal server error occurred.", default=serialize_everything))
|
||||||
self.set_status(500)
|
self.set_status(500)
|
||||||
self.set_header("Cache-Control", "no-store")
|
self.set_header("Cache-Control", "no-store")
|
||||||
self.set_header("Content-Type", "application/json")
|
self.set_header("Content-Type", "application/json")
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class APIAlertsHandler(tornado.web.RequestHandler):
|
|||||||
self.set_status(400)
|
self.set_status(400)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
self.write(json.dumps("Error - " + str(e), default=serialize_everything))
|
self.write(json.dumps("Error - an internal server error occurred.", default=serialize_everything))
|
||||||
self.set_status(500)
|
self.set_status(500)
|
||||||
self.set_header("Cache-Control", "no-store")
|
self.set_header("Cache-Control", "no-store")
|
||||||
self.set_header("Content-Type", "application/json")
|
self.set_header("Content-Type", "application/json")
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class APILookupCallHandler(tornado.web.RequestHandler):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
self.write(json.dumps("Error - " + str(e), default=serialize_everything))
|
self.write(json.dumps("Error - an internal server error occurred.", default=serialize_everything))
|
||||||
self.set_status(500)
|
self.set_status(500)
|
||||||
|
|
||||||
self.set_header("Cache-Control", "no-store")
|
self.set_header("Cache-Control", "no-store")
|
||||||
@@ -119,7 +119,7 @@ class APILookupSIGRefHandler(tornado.web.RequestHandler):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
self.write(json.dumps("Error - " + str(e), default=serialize_everything))
|
self.write(json.dumps("Error - an internal server error occurred.", default=serialize_everything))
|
||||||
self.set_status(500)
|
self.set_status(500)
|
||||||
|
|
||||||
self.set_header("Cache-Control", "no-store")
|
self.set_header("Cache-Control", "no-store")
|
||||||
@@ -177,7 +177,7 @@ class APILookupGridHandler(tornado.web.RequestHandler):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
self.write(json.dumps("Error - " + str(e), default=serialize_everything))
|
self.write(json.dumps("Error - an internal server error occurred.", default=serialize_everything))
|
||||||
self.set_status(500)
|
self.set_status(500)
|
||||||
|
|
||||||
self.set_header("Cache-Control", "no-store")
|
self.set_header("Cache-Control", "no-store")
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class APISpotsHandler(tornado.web.RequestHandler):
|
|||||||
self.set_status(400)
|
self.set_status(400)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
self.write(json.dumps("Error - " + str(e), default=serialize_everything))
|
self.write(json.dumps("Error - an internal server error occurred.", default=serialize_everything))
|
||||||
self.set_status(500)
|
self.set_status(500)
|
||||||
self.set_header("Cache-Control", "no-store")
|
self.set_header("Cache-Control", "no-store")
|
||||||
self.set_header("Content-Type", "application/json")
|
self.set_header("Content-Type", "application/json")
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class HTTPSolarConditionsProvider(SolarConditionsProvider):
|
|||||||
def _poll(self):
|
def _poll(self):
|
||||||
try:
|
try:
|
||||||
logging.debug("Polling " + self.name + " solar conditions API...")
|
logging.debug("Polling " + self.name + " solar conditions API...")
|
||||||
http_response = requests.get(self._url, headers=HTTP_HEADERS)
|
http_response = requests.get(self._url, headers=HTTP_HEADERS, timeout=(5, 30))
|
||||||
new_data = self._http_response_to_solar_conditions(http_response)
|
new_data = self._http_response_to_solar_conditions(http_response)
|
||||||
self.update_data(new_data)
|
self.update_data(new_data)
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class HEMA(HTTPSpotProvider):
|
|||||||
new_spots = []
|
new_spots = []
|
||||||
# OK, if the spot seed actually changed, now we make the real request for data.
|
# OK, if the spot seed actually changed, now we make the real request for data.
|
||||||
if spot_seed_changed:
|
if spot_seed_changed:
|
||||||
source_data = requests.get(self.SPOTS_URL, headers=HTTP_HEADERS)
|
source_data = requests.get(self.SPOTS_URL, headers=HTTP_HEADERS, timeout=(5, 30))
|
||||||
source_data_items = source_data.text.split("=")
|
source_data_items = source_data.text.split("=")
|
||||||
# Iterate through source data items.
|
# Iterate through source data items.
|
||||||
for source_spot in source_data_items:
|
for source_spot in source_data_items:
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class HTTPSpotProvider(SpotProvider):
|
|||||||
try:
|
try:
|
||||||
# Request data from API
|
# Request data from API
|
||||||
logging.debug("Polling " + self.name + " spot API...")
|
logging.debug("Polling " + self.name + " spot API...")
|
||||||
http_response = requests.get(self._url, headers=HTTP_HEADERS)
|
http_response = requests.get(self._url, headers=HTTP_HEADERS, timeout=(5, 30))
|
||||||
# Pass off to the subclass for processing
|
# Pass off to the subclass for processing
|
||||||
new_spots = self._http_response_to_spots(http_response)
|
new_spots = self._http_response_to_spots(http_response)
|
||||||
# Submit the new spots for processing. There might not be any spots for the less popular programs.
|
# Submit the new spots for processing. There might not be any spots for the less popular programs.
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class SOTA(HTTPSpotProvider):
|
|||||||
new_spots = []
|
new_spots = []
|
||||||
# OK, if the epoch actually changed, now we make the real request for data.
|
# OK, if the epoch actually changed, now we make the real request for data.
|
||||||
if epoch_changed:
|
if epoch_changed:
|
||||||
source_data = requests.get(self.SPOTS_URL, headers=HTTP_HEADERS).json()
|
source_data = requests.get(self.SPOTS_URL, headers=HTTP_HEADERS, timeout=(5, 30)).json()
|
||||||
# Iterate through source data
|
# Iterate through source data
|
||||||
for source_spot in source_data:
|
for source_spot in source_data:
|
||||||
# Convert to our spot format
|
# Convert to our spot format
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
<p>This software is dedicated to the memory of Tom G1PJB, SK, a friend and colleague who sadly passed away around the time I started writing it in Autumn 2025. I was looking forward to showing it to you when it was done.</p>
|
<p>This software is dedicated to the memory of Tom G1PJB, SK, a friend and colleague who sadly passed away around the time I started writing it in Autumn 2025. I was looking forward to showing it to you when it was done.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/common.js?v=1778343015"></script>
|
<script src="/js/common.js?v=1778407061"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-about").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-about").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
@@ -69,8 +69,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/common.js?v=1778343015"></script>
|
<script src="/js/common.js?v=1778407061"></script>
|
||||||
<script src="/js/add-spot.js?v=1778343015"></script>
|
<script src="/js/add-spot.js?v=1778407061"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-add-spot").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-add-spot").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
@@ -70,8 +70,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/common.js?v=1778343015"></script>
|
<script src="/js/common.js?v=1778407061"></script>
|
||||||
<script src="/js/alerts.js?v=1778343015"></script>
|
<script src="/js/alerts.js?v=1778407061"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-alerts").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-alerts").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
@@ -76,9 +76,9 @@
|
|||||||
<script>
|
<script>
|
||||||
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
||||||
</script>
|
</script>
|
||||||
<script src="/js/common.js?v=1778343015"></script>
|
<script src="/js/common.js?v=1778407061"></script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=1778343015"></script>
|
<script src="/js/spotsbandsandmap.js?v=1778407061"></script>
|
||||||
<script src="/js/bands.js?v=1778343015"></script>
|
<script src="/js/bands.js?v=1778407061"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-bands").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-bands").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
<title>Spothole</title>
|
<title>Spothole</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="/css/style.css?v=1778343015" type="text/css">
|
<link rel="stylesheet" href="/css/style.css?v=1778407061" type="text/css">
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet"
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
||||||
<link href="/fa/css/fontawesome.min.css" rel="stylesheet" />
|
<link href="/fa/css/fontawesome.min.css" rel="stylesheet" />
|
||||||
@@ -39,16 +39,22 @@
|
|||||||
|
|
||||||
<link rel="manifest" href="manifest.webmanifest">
|
<link rel="manifest" href="manifest.webmanifest">
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"
|
||||||
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.4/moment.min.js"></script>
|
integrity="sha384-1H217gwSVyLSIfaLxHbE7dRb3v4mYCKbpQvzx0cegeju1MVsGrX5xXxAvs/HgeFs"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.4/moment.min.js"
|
||||||
|
integrity="sha384-N1xdnJwBzqfCpEDxEeSQzv4NPVPViBQq2NLbzth3YA1pLvR9mtf+TV5g6O+KLkPY"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
|
||||||
integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
|
integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
|
||||||
crossorigin="anonymous"></script>
|
crossorigin="anonymous"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/tinycolor2@1.6.0/cjs/tinycolor.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/tinycolor2@1.6.0/cjs/tinycolor.min.js"
|
||||||
|
integrity="sha384-L1eE4eD41kpBIWe2I0eHy+GnEUC4RIpcvibVW2JCminuPlTl+2Bc528iPdVMg5Dn"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
|
||||||
<script src="https://misc.ianrenton.com/jsutils/utils.js?v=1778343015"></script>
|
<script src="https://misc.ianrenton.com/jsutils/utils.js?v=1778407061"></script>
|
||||||
<script src="https://misc.ianrenton.com/jsutils/ui-ham.js?v=1778343015"></script>
|
<script src="https://misc.ianrenton.com/jsutils/ui-ham.js?v=1778407061"></script>
|
||||||
<script src="https://misc.ianrenton.com/jsutils/geo.js?v=1778343015"></script>
|
<script src="https://misc.ianrenton.com/jsutils/geo.js?v=1778407061"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
<label for="hamqth-enabled" class="form-check-label">Use data from HamQTH</label>
|
<label for="hamqth-enabled" class="form-check-label">Use data from HamQTH</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<input type="text" class="storeable-text form-control form-control-sm" id="hamqth-username" placeholder="Username (Callsign)" onchange="saveSettings();" autocomplete="username">
|
<input type="text" class="storeable-text form-control" id="hamqth-username" placeholder="Username (Callsign)" onchange="saveSettings();" autocomplete="username">
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<input type="password" class="password-field form-control form-control-sm" id="hamqth-password" placeholder="Password" data-remember-checkbox="hamqth-remember-password" onchange="saveSettings();" autocomplete="current-password">
|
<input type="password" class="password-field form-control" id="hamqth-password" placeholder="Password" data-remember-checkbox="hamqth-remember-password" onchange="saveSettings();" autocomplete="current-password">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input type="checkbox" class="storeable-checkbox form-check-input" id="hamqth-remember-password" onchange="saveSettings();">
|
<input type="checkbox" class="storeable-checkbox form-check-input" id="hamqth-remember-password" onchange="saveSettings();">
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
<label for="qrz-enabled" class="form-check-label">Use data from QRZ.com</label>
|
<label for="qrz-enabled" class="form-check-label">Use data from QRZ.com</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<input type="text" class="storeable-text form-control form-control-sm" id="qrz-username" placeholder="Username (Callsign)" onchange="saveSettings();" autocomplete="username">
|
<input type="text" class="storeable-text form-control" id="qrz-username" placeholder="Username (Callsign)" onchange="saveSettings();" autocomplete="username">
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<input type="password" class="password-field form-control form-control-sm" id="qrz-password" placeholder="Password" data-remember-checkbox="qrz-remember-password" onchange="saveSettings();" autocomplete="current-password">
|
<input type="password" class="password-field form-control" id="qrz-password" placeholder="Password" data-remember-checkbox="qrz-remember-password" onchange="saveSettings();" autocomplete="current-password">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input type="checkbox" class="storeable-checkbox form-check-input" id="qrz-remember-password" onchange="saveSettings();">
|
<input type="checkbox" class="storeable-checkbox form-check-input" id="qrz-remember-password" onchange="saveSettings();">
|
||||||
|
|||||||
@@ -230,8 +230,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.9/dist/chart.umd.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.9/dist/chart.umd.min.js"></script>
|
||||||
<script src="/js/common.js?v=1778343015"></script>
|
<script src="/js/common.js?v=1778407061"></script>
|
||||||
<script src="/js/conditions.js?v=1778343015"></script>
|
<script src="/js/conditions.js?v=1778407061"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-conditions").addClass("active");
|
$("#nav-link-conditions").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.css">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet-extra-markers@1.2.2/dist/css/leaflet.extra-markers.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet-extra-markers@1.2.2/dist/css/leaflet.extra-markers.min.css">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/overlapping-marker-spiderfier-leaflet/dist/oms.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/leaflet-providers@2.0.0/leaflet-providers.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/leaflet-providers@2.0.0/leaflet-providers.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/leaflet-extra-markers@1.2.2/src/assets/js/leaflet.extra-markers.min.js" type="module"></script>
|
<script src="https://cdn.jsdelivr.net/npm/leaflet-extra-markers@1.2.2/src/assets/js/leaflet.extra-markers.min.js" type="module"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/leaflet.geodesic"></script>
|
<script src="https://cdn.jsdelivr.net/npm/leaflet.geodesic"></script>
|
||||||
@@ -93,9 +94,9 @@
|
|||||||
<script>
|
<script>
|
||||||
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
||||||
</script>
|
</script>
|
||||||
<script src="/js/common.js?v=1778343015"></script>
|
<script src="/js/common.js?v=1778407061"></script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=1778343015"></script>
|
<script src="/js/spotsbandsandmap.js?v=1778407061"></script>
|
||||||
<script src="/js/map.js?v=1778343015"></script>
|
<script src="/js/map.js?v=1778407061"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-map").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-map").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
@@ -104,9 +104,9 @@
|
|||||||
<script>
|
<script>
|
||||||
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
||||||
</script>
|
</script>
|
||||||
<script src="/js/common.js?v=1778343015"></script>
|
<script src="/js/common.js?v=1778407061"></script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=1778343015"></script>
|
<script src="/js/spotsbandsandmap.js?v=1778407061"></script>
|
||||||
<script src="/js/spots.js?v=1778343015"></script>
|
<script src="/js/spots.js?v=1778407061"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-spots").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-spots").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
@@ -59,8 +59,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/common.js?v=1778343015"></script>
|
<script src="/js/common.js?v=1778407061"></script>
|
||||||
<script src="/js/status.js?v=1778343015"></script>
|
<script src="/js/status.js?v=1778407061"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() { $("#nav-link-status").addClass("active"); }); <!-- highlight active page in nav -->
|
$(document).ready(function() { $("#nav-link-status").addClass("active"); }); <!-- highlight active page in nav -->
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -103,7 +103,11 @@ function addSpot() {
|
|||||||
|
|
||||||
// Show an "add spot" error.
|
// Show an "add spot" error.
|
||||||
function showAddSpotError(text) {
|
function showAddSpotError(text) {
|
||||||
$("#result-bad").html("<div class='alert alert-danger alert-dismissible fade show mb-0 mt-4' role='alert'><i class='fa-solid fa-triangle-exclamation'></i> " + text + "<button type='button' class='btn-close' data-bs-dismiss='alert' aria-label='Close'></button></div>");
|
var div = $("<div class='alert alert-danger alert-dismissible fade show mb-0 mt-4' role='alert'></div>");
|
||||||
|
div.append("<i class='fa-solid fa-triangle-exclamation'></i> ");
|
||||||
|
div.append(document.createTextNode(text));
|
||||||
|
div.append("<button type='button' class='btn-close' data-bs-dismiss='alert' aria-label='Close'></button>");
|
||||||
|
$("#result-bad").empty().append(div);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force callsign and mode capitalisation
|
// Force callsign and mode capitalisation
|
||||||
|
|||||||
@@ -219,9 +219,9 @@ function addAlertRowsToTable(tbody, alerts) {
|
|||||||
var items = []
|
var items = []
|
||||||
for (var i = 0; i < a["sig_refs"].length; i++) {
|
for (var i = 0; i < a["sig_refs"].length; i++) {
|
||||||
if (a["sig_refs"][i]["url"] != null) {
|
if (a["sig_refs"][i]["url"] != null) {
|
||||||
items[i] = `<a href='${a["sig_refs"][i]["url"]}' title='${a["sig_refs"][i]["name"]}' target='_new' class='sig-ref-link'>${a["sig_refs"][i]["id"]}</a>`
|
items[i] = `<a href='${encodeURI(a["sig_refs"][i]["url"])}' title='${escapeHtml(a["sig_refs"][i]["name"])}' target='_new' class='sig-ref-link'>${escapeHtml(a["sig_refs"][i]["id"])}</a>`
|
||||||
} else {
|
} else {
|
||||||
items[i] = `${a["sig_refs"][i]["id"]}`
|
items[i] = `${escapeHtml(a["sig_refs"][i]["id"])}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sig_refs = items.join(", ");
|
sig_refs = items.join(", ");
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ const WAB_WAI_GRID_COLOR_DARK = 'rgba(60, 60, 120, 1.0)';
|
|||||||
var backgroundTileLayer;
|
var backgroundTileLayer;
|
||||||
var markersLayer;
|
var markersLayer;
|
||||||
var geodesicsLayer;
|
var geodesicsLayer;
|
||||||
|
var oms;
|
||||||
var terminator;
|
var terminator;
|
||||||
var maidenheadGrid;
|
var maidenheadGrid;
|
||||||
var cqZones;
|
var cqZones;
|
||||||
@@ -48,7 +49,7 @@ function buildQueryString() {
|
|||||||
});
|
});
|
||||||
str = str + "max_age=" + $("#max-spot-age option:selected").val();
|
str = str + "max_age=" + $("#max-spot-age option:selected").val();
|
||||||
// Additional filters for the map view: No dupes, no QRT, only spots with good locations
|
// Additional filters for the map view: No dupes, no QRT, only spots with good locations
|
||||||
str = str + "&dedupe=true&allow_qrt=false&needs_good_location=true";
|
str = str + "&dedupe=true&allow_qrt=false";
|
||||||
str = str + getCredentialQueryString();
|
str = str + getCredentialQueryString();
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
@@ -58,12 +59,14 @@ function updateMap() {
|
|||||||
// Clear existing content
|
// Clear existing content
|
||||||
markersLayer.clearLayers();
|
markersLayer.clearLayers();
|
||||||
geodesicsLayer.clearLayers();
|
geodesicsLayer.clearLayers();
|
||||||
|
oms.clearMarkers();
|
||||||
|
|
||||||
// Make new markers for all spots that match the filter
|
// Make new markers for all spots that match the filter
|
||||||
spots.forEach(function (s) {
|
spots.forEach(function (s) {
|
||||||
var m = L.marker([s["dx_latitude"], s["dx_longitude"]], {icon: getIcon(s)});
|
var m = L.marker([s["dx_latitude"], s["dx_longitude"]], {icon: getIcon(s)});
|
||||||
m.bindPopup(getTooltipText(s));
|
m.bindPopup(getTooltipText(s));
|
||||||
markersLayer.addLayer(m);
|
markersLayer.addLayer(m);
|
||||||
|
oms.addMarker(m);
|
||||||
|
|
||||||
// Create geodesics if required
|
// Create geodesics if required
|
||||||
if ($("#mapShowGeodesics")[0].checked && s["de_latitude"] != null && s["de_longitude"] != null) {
|
if ($("#mapShowGeodesics")[0].checked && s["de_latitude"] != null && s["de_longitude"] != null) {
|
||||||
@@ -414,6 +417,12 @@ function setUpMap() {
|
|||||||
markersLayer = new L.LayerGroup();
|
markersLayer = new L.LayerGroup();
|
||||||
markersLayer.addTo(map);
|
markersLayer.addTo(map);
|
||||||
|
|
||||||
|
// Set up spiderfy for overlapping markers
|
||||||
|
oms = new OverlappingMarkerSpiderfier(map, {keepSpiderfied: true});
|
||||||
|
oms.addListener('click', function(marker) {
|
||||||
|
marker.openPopup();
|
||||||
|
});
|
||||||
|
|
||||||
// Add geodesic layer
|
// Add geodesic layer
|
||||||
geodesicsLayer = new L.LayerGroup();
|
geodesicsLayer = new L.LayerGroup();
|
||||||
geodesicsLayer.addTo(map);
|
geodesicsLayer.addTo(map);
|
||||||
|
|||||||
@@ -290,9 +290,9 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
var items = []
|
var items = []
|
||||||
for (var i = 0; i < s["sig_refs"].length; i++) {
|
for (var i = 0; i < s["sig_refs"].length; i++) {
|
||||||
if (s["sig_refs"][i]["url"] != null) {
|
if (s["sig_refs"][i]["url"] != null) {
|
||||||
items[i] = `<span style="white-space: nowrap;"><a href='${s["sig_refs"][i]["url"]}' title='${s["sig_refs"][i]["name"]}' target='_new' class='sig-ref-link'>${s["sig_refs"][i]["id"]}</a></span>`
|
items[i] = `<span style="white-space: nowrap;"><a href='${encodeURI(s["sig_refs"][i]["url"])}' title='${escapeHtml(s["sig_refs"][i]["name"])}' target='_new' class='sig-ref-link'>${escapeHtml(s["sig_refs"][i]["id"])}</a></span>`
|
||||||
} else {
|
} else {
|
||||||
items[i] = `<span style="white-space: nowrap;">${s["sig_refs"][i]["id"]}</span>`
|
items[i] = `<span style="white-space: nowrap;">${escapeHtml(s["sig_refs"][i]["id"])}</span>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sig_refs = items.join(", ");
|
sig_refs = items.join(", ");
|
||||||
|
|||||||
Reference in New Issue
Block a user