Now that SIGs are rebranded as Activities, we can merge DXpedition and Contest into that without it being too weird, and get rid of AlertType #147

This commit is contained in:
Ian Renton
2026-09-18 16:50:00 +01:00
parent bf9b4ac68c
commit cea90695ba
21 changed files with 92 additions and 113 deletions
+9
View File
@@ -11,6 +11,15 @@ def get_ref_regex_for_activity(activity):
return None return None
def get_icon_for_activity(activity):
"""Utility function to get the icon for a named activity. If no match is found, None will be returned."""
for a in ACTIVITIES:
if a.name.upper() == activity.upper():
return a.icon
return None
def get_activity_name_from_comment_name(activity): def get_activity_name_from_comment_name(activity):
"""Utility function to get the name of an activity from its "comment name". Generally these will be the same """Utility function to get the name of an activity from its "comment name". Generally these will be the same
but there are some cases (e.g. is "TOTA" Towers, Tiles or Toilets?) where we need to transform one to the but there are some cases (e.g. is "TOTA" Towers, Tiles or Toilets?) where we need to transform one to the
+16
View File
@@ -12,6 +12,22 @@ HAMQTH_PRG = f"Spothole v{SOFTWARE_VERSION} operated by {SERVER_OWNER_CALLSIGN}"
# Activities # Activities
ACTIVITIES = [ ACTIVITIES = [
Activity(
name="Contest",
comment_names=["CONTEST"],
description="Contest",
sig_type=ActivityType.TRADITIONAL,
icon="fa-trophy",
refs_globally_unique=False,
),
Activity(
name="DXpedition",
comment_names=[],
description="Radio expedition to a remote location",
sig_type=ActivityType.TRADITIONAL,
icon="fa-book-atlas",
refs_globally_unique=False,
),
Activity( Activity(
name="Satellite", name="Satellite",
comment_names=[], comment_names=[],
-9
View File
@@ -112,15 +112,6 @@ class ActivityRefType(str, Enum):
TOILET = "TOILET" TOILET = "TOILET"
class AlertType(str, Enum):
"""Type of an alert."""
XOTA = "XOTA"
SATELLITE = "SATELLITE"
DXPEDITION = "DXPEDITION"
CONTEST = "CONTEST"
class ActivityType(str, Enum): class ActivityType(str, Enum):
"""Type of an activity. Used to group them in the web UI.""" """Type of an activity. Used to group them in the web UI."""
+5 -12
View File
@@ -7,8 +7,9 @@ from datetime import datetime, timedelta
import pytz import pytz
from core.activity_lookup_helper import populate_missing_activity_ref_info from core.activity_lookup_helper import populate_missing_activity_ref_info
from core.activity_utils import get_icon_for_activity
from core.call_lookup_helper import get_call_info from core.call_lookup_helper import get_call_info
from core.enums import AlertType, Continent from core.enums import Continent
from core.utils import get_flag_for_dxcc from core.utils import get_flag_for_dxcc
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -54,8 +55,6 @@ class Alert:
end_time_iso: str | None = None end_time_iso: str | None = None
# Comment made by the alerter, if any # Comment made by the alerter, if any
comment: str | None = None comment: str | None = None
# The type of alert this is: xOTA, DXpedition, or Contest.
alert_type: AlertType | None = None
# A URL link to more information, if any # A URL link to more information, if any
url: str | None = None url: str | None = None
@@ -153,16 +152,10 @@ class Alert:
if self.dx_calls and not self.dx_names: if self.dx_calls and not self.dx_names:
self.dx_names = [get_call_info(c, credentials).name for c in self.dx_calls] self.dx_names = [get_call_info(c, credentials).name for c in self.dx_calls]
# Icon for the spot should be the icon of the first activity ref if present, otherwise a radio tower # Icon for the alert should be the icon of its activity if known, otherwise a radio tower
self.icon = "fa-tower-cell" self.icon = "fa-tower-cell"
if self.alert_type == AlertType.DXPEDITION: if self.sig and (activity_icon := get_icon_for_activity(self.sig)):
self.icon = "fa-globe-africa" self.icon = activity_icon
elif self.alert_type == AlertType.CONTEST:
self.icon = "fa-trophy"
elif self.alert_type == AlertType.SATELLITE:
self.icon = "fa-satellite"
elif self.sig_refs and self.sig_refs[0].icon:
self.icon = self.sig_refs[0].icon
except Exception: except Exception:
logger.exception("Exception while inferring missing data from spot") logger.exception("Exception while inferring missing data from spot")
+8 -13
View File
@@ -13,6 +13,7 @@ from core.activity_lookup_helper import populate_missing_activity_ref_info
from core.activity_utils import ( from core.activity_utils import (
ANY_ACTIVITY_REGEX, ANY_ACTIVITY_REGEX,
get_activity_name_from_comment_name, get_activity_name_from_comment_name,
get_icon_for_activity,
get_ref_regex_for_activity, get_ref_regex_for_activity,
) )
from core.call_lookup_helper import get_call_info from core.call_lookup_helper import get_call_info
@@ -378,16 +379,10 @@ class Spot:
logger.info(f"Seen a new propagation mode tag not yet in the system: {mode_tag}") logger.info(f"Seen a new propagation mode tag not yet in the system: {mode_tag}")
# Set activities based on propagation mode # Set activities based on propagation mode
if self.propagation_mode == "Satellite": if self.propagation_mode == "Satellite" and not self.sig:
if not self.sig: self.sig = "Satellite"
self.sig = "AMSAT" if self.propagation_mode == "Earth-Moon-Earth" and not self.sig:
if not any(activity_ref.sig == "AMSAT" for activity_ref in self.sig_refs): self.sig = "EME"
self.sig_refs.append(ActivityRef(sig="AMSAT"))
if self.propagation_mode == "Earth-Moon-Earth":
if not self.sig:
self.sig = "EME"
if not any(activity_ref.sig == "EME" for activity_ref in self.sig_refs):
self.sig_refs.append(ActivityRef(sig="EME"))
# Parse "de_grid -> dx_grid" structures from the comment # Parse "de_grid -> dx_grid" structures from the comment
if self.comment: if self.comment:
@@ -499,10 +494,10 @@ class Spot:
self.de_longitude = de_call_info.longitude self.de_longitude = de_call_info.longitude
self.de_grid = de_call_info.grid self.de_grid = de_call_info.grid
# Icon for the spot should be the icon of the first activity ref if present, otherwise a radio tower # Icon for the spot should be the icon of its activity if known, otherwise a radio tower
self.icon = "fa-tower-cell" self.icon = "fa-tower-cell"
if self.sig_refs and self.sig_refs[0].icon: if self.sig and (activity_icon := get_icon_for_activity(self.sig)):
self.icon = self.sig_refs[0].icon self.icon = activity_icon
except Exception: except Exception:
logger.exception("Exception while inferring missing data from spot") logger.exception("Exception while inferring missing data from spot")
+1 -2
View File
@@ -3,7 +3,6 @@ from datetime import datetime, timedelta
import pytz import pytz
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from core.enums import AlertType
from data.activity_ref import ActivityRef from data.activity_ref import ActivityRef
from data.alert import Alert from data.alert import Alert
from providers.alert.http_alert_provider import HTTPAlertProvider from providers.alert.http_alert_provider import HTTPAlertProvider
@@ -56,9 +55,9 @@ class BOTA(HTTPAlertProvider):
alert = Alert( alert = Alert(
source=self.name, source=self.name,
dx_calls=[dx_call], dx_calls=[dx_call],
sig="BOTA",
sig_refs=[ActivityRef(id=ref_name, sig="BOTA")], sig_refs=[ActivityRef(id=ref_name, sig="BOTA")],
start_time=date_time.timestamp(), start_time=date_time.timestamp(),
alert_type=AlertType.XOTA,
) )
new_alerts.append(alert) new_alerts.append(alert)
+2 -3
View File
@@ -2,7 +2,6 @@ from datetime import datetime
import pytz import pytz
from core.enums import AlertType
from data.activity_ref import ActivityRef from data.activity_ref import ActivityRef
from data.alert import Alert from data.alert import Alert
from providers.alert.http_alert_provider import HTTPAlertProvider from providers.alert.http_alert_provider import HTTPAlertProvider
@@ -35,10 +34,11 @@ class Hamsat(HTTPAlertProvider):
dx_calls=[source_alert["callsign"].upper()], dx_calls=[source_alert["callsign"].upper()],
freqs_modes=freqs_modes, freqs_modes=freqs_modes,
comment=source_alert["comment"], comment=source_alert["comment"],
sig="Satellite",
# Fudge an activity ref to provide the remaining bits of data we need: the satellite and the operator's grid # Fudge an activity ref to provide the remaining bits of data we need: the satellite and the operator's grid
sig_refs=[ sig_refs=[
ActivityRef( ActivityRef(
sig="AMSAT", sig="Satellite",
id=f"{source_alert['satellite']['name']} from {source_alert['grids'][0]}", id=f"{source_alert['satellite']['name']} from {source_alert['grids'][0]}",
) )
], ],
@@ -48,7 +48,6 @@ class Hamsat(HTTPAlertProvider):
end_time=datetime.strptime(source_alert["los_at"], "%Y-%m-%dT%H:%M:%SZ") end_time=datetime.strptime(source_alert["los_at"], "%Y-%m-%dT%H:%M:%SZ")
.replace(tzinfo=pytz.UTC) .replace(tzinfo=pytz.UTC)
.timestamp(), .timestamp(),
alert_type=AlertType.SATELLITE,
) )
# Add to our list # Add to our list
+1 -2
View File
@@ -6,7 +6,6 @@ import pytz
from rss_parser import Parser from rss_parser import Parser
from rss_parser.models.rss import RSS from rss_parser.models.rss import RSS
from core.enums import AlertType
from data.alert import Alert from data.alert import Alert
from providers.alert.http_alert_provider import HTTPAlertProvider from providers.alert.http_alert_provider import HTTPAlertProvider
@@ -89,7 +88,7 @@ class NG3K(HTTPAlertProvider):
comment=f"{by}; {comment}; {qsl_info}", comment=f"{by}; {comment}; {qsl_info}",
start_time=start_timestamp, start_time=start_timestamp,
end_time=end_timestamp, end_time=end_timestamp,
alert_type=AlertType.DXPEDITION, sig="DXpedition",
) )
# Add to our list. # Add to our list.
+1 -2
View File
@@ -3,7 +3,6 @@ from datetime import datetime
import pytz import pytz
from core.enums import AlertType
from data.activity_ref import ActivityRef from data.activity_ref import ActivityRef
from data.alert import Alert from data.alert import Alert
from providers.alert.http_alert_provider import HTTPAlertProvider from providers.alert.http_alert_provider import HTTPAlertProvider
@@ -50,9 +49,9 @@ class ParksNPeaks(HTTPAlertProvider):
dx_calls=[source_alert["CallSign"].upper()], dx_calls=[source_alert["CallSign"].upper()],
freqs_modes=f"{source_alert['Freq']} {source_alert['MODE']}", freqs_modes=f"{source_alert['Freq']} {source_alert['MODE']}",
comment=source_alert["Comments"], comment=source_alert["Comments"],
sig=activity,
sig_refs=activity_refs, sig_refs=activity_refs,
start_time=start_time, start_time=start_time,
alert_type=AlertType.XOTA,
) )
# Log a warning for the developer if PnP gives us an unknown programme we've never seen before # Log a warning for the developer if PnP gives us an unknown programme we've never seen before
+1 -2
View File
@@ -2,7 +2,6 @@ from datetime import datetime
import pytz import pytz
from core.enums import AlertType
from data.activity_ref import ActivityRef from data.activity_ref import ActivityRef
from data.alert import Alert from data.alert import Alert
from providers.alert.http_alert_provider import HTTPAlertProvider from providers.alert.http_alert_provider import HTTPAlertProvider
@@ -28,6 +27,7 @@ class POTA(HTTPAlertProvider):
dx_calls=[source_alert["activator"].upper()], dx_calls=[source_alert["activator"].upper()],
freqs_modes=source_alert["frequencies"], freqs_modes=source_alert["frequencies"],
comment=source_alert["comments"], comment=source_alert["comments"],
sig="POTA",
sig_refs=[ sig_refs=[
ActivityRef( ActivityRef(
id=source_alert["reference"], id=source_alert["reference"],
@@ -45,7 +45,6 @@ class POTA(HTTPAlertProvider):
end_time=datetime.strptime(source_alert["endDate"] + source_alert["endTime"], "%Y-%m-%d%H:%M") end_time=datetime.strptime(source_alert["endDate"] + source_alert["endTime"], "%Y-%m-%d%H:%M")
.replace(tzinfo=pytz.UTC) .replace(tzinfo=pytz.UTC)
.timestamp(), .timestamp(),
alert_type=AlertType.XOTA,
) )
# Add to our list, but exclude any old spots that POTA can sometimes give us where even the end time is # Add to our list, but exclude any old spots that POTA can sometimes give us where even the end time is
+2 -2
View File
@@ -2,7 +2,7 @@ import re
from icalendar import Event from icalendar import Event
from core.enums import AlertType, Continent from core.enums import Continent
from data.alert import Alert from data.alert import Alert
from providers.alert.ical_alert_provider import ICALAlertProvider from providers.alert.ical_alert_provider import ICALAlertProvider
@@ -69,7 +69,7 @@ class RSGBICALAlertProvider(ICALAlertProvider):
comment=summary, comment=summary,
start_time=start_timestamp, start_time=start_timestamp,
end_time=end_timestamp, end_time=end_timestamp,
alert_type=AlertType.CONTEST, sig="Contest",
) )
return alert return alert
+1 -2
View File
@@ -2,7 +2,6 @@ from datetime import datetime
import pytz import pytz
from core.enums import AlertType
from data.activity_ref import ActivityRef from data.activity_ref import ActivityRef
from data.alert import Alert from data.alert import Alert
from providers.alert.http_alert_provider import HTTPAlertProvider from providers.alert.http_alert_provider import HTTPAlertProvider
@@ -34,6 +33,7 @@ class SOTA(HTTPAlertProvider):
dx_names=[source_alert["activatorName"].upper()], dx_names=[source_alert["activatorName"].upper()],
freqs_modes=source_alert["frequency"], freqs_modes=source_alert["frequency"],
comment=source_alert["comments"], comment=source_alert["comments"],
sig="SOTA",
sig_refs=[ sig_refs=[
ActivityRef( ActivityRef(
id=f"{source_alert['associationCode']}/{source_alert['summitCode']}", id=f"{source_alert['associationCode']}/{source_alert['summitCode']}",
@@ -45,7 +45,6 @@ class SOTA(HTTPAlertProvider):
start_time=datetime.strptime(source_alert["dateActivated"], "%Y-%m-%dT%H:%M:%SZ") start_time=datetime.strptime(source_alert["dateActivated"], "%Y-%m-%dT%H:%M:%SZ")
.replace(tzinfo=pytz.UTC) .replace(tzinfo=pytz.UTC)
.timestamp(), .timestamp(),
alert_type=AlertType.XOTA,
) )
# Add to our list # Add to our list
+1 -2
View File
@@ -1,6 +1,5 @@
from icalendar import Event from icalendar import Event
from core.enums import AlertType
from data.alert import Alert from data.alert import Alert
from providers.alert.ical_alert_provider import ICALAlertProvider from providers.alert.ical_alert_provider import ICALAlertProvider
@@ -35,7 +34,7 @@ class WA7BNM(ICALAlertProvider):
url=url, url=url,
start_time=start_timestamp, start_time=start_timestamp,
end_time=end_timestamp, end_time=end_timestamp,
alert_type=AlertType.CONTEST, sig="Contest",
) )
return alert return alert
+1 -2
View File
@@ -2,7 +2,6 @@ from datetime import datetime
import pytz import pytz
from core.enums import AlertType
from data.activity_ref import ActivityRef from data.activity_ref import ActivityRef
from data.alert import Alert from data.alert import Alert
from providers.alert.http_alert_provider import HTTPAlertProvider from providers.alert.http_alert_provider import HTTPAlertProvider
@@ -28,6 +27,7 @@ class WWFF(HTTPAlertProvider):
dx_calls=[source_alert["activator_call"].upper()], dx_calls=[source_alert["activator_call"].upper()],
freqs_modes=f"{source_alert['band']} {source_alert['mode']}", freqs_modes=f"{source_alert['band']} {source_alert['mode']}",
comment=source_alert["remarks"], comment=source_alert["remarks"],
sig="WWFF",
sig_refs=[ActivityRef(id=source_alert["reference"], sig="WWFF")], sig_refs=[ActivityRef(id=source_alert["reference"], sig="WWFF")],
start_time=datetime.strptime(source_alert["utc_start"], "%Y-%m-%d %H:%M:%S") start_time=datetime.strptime(source_alert["utc_start"], "%Y-%m-%d %H:%M:%S")
.replace(tzinfo=pytz.UTC) .replace(tzinfo=pytz.UTC)
@@ -35,7 +35,6 @@ class WWFF(HTTPAlertProvider):
end_time=datetime.strptime(source_alert["utc_end"], "%Y-%m-%d %H:%M:%S") end_time=datetime.strptime(source_alert["utc_end"], "%Y-%m-%d %H:%M:%S")
.replace(tzinfo=pytz.UTC) .replace(tzinfo=pytz.UTC)
.timestamp(), .timestamp(),
alert_type=AlertType.XOTA,
) )
# Add to our list # Add to our list
+5 -11
View File
@@ -15,6 +15,11 @@ info:
## Changelog ## Changelog
### 2.2
* Renamed AMSAT SIG to "Satellite" as AMSAT is a specific organisation not just a general term for satellite QSOs
* Removed `alert_type` from alert data. Contest, DXpedition and Satellite alerts now give those values in `sig` instead, alongside the existing outdoor activity programmes. Teeeeechnically a breaking change but AlertType is so new I doubt anyone is using it yet, so slipped this one in anyway. Sorry :)
### 2.1 ### 2.1
* Added AMSAT, EME, DTMBA, FEA, BIWOTA, COTA & PGA SIGs * Added AMSAT, EME, DTMBA, FEA, BIWOTA, COTA & PGA SIGs
@@ -952,14 +957,6 @@ components:
- TOILET - TOILET
example: PARK example: PARK
AlertType:
type: string
enum:
- XOTA
- DXPEDITION
- CONTEST
example: XOTA
Continent: Continent:
type: string type: string
enum: enum:
@@ -1489,9 +1486,6 @@ components:
items: items:
$ref: '#/components/schemas/ActivityRef' $ref: '#/components/schemas/ActivityRef'
description: Activity references. We allow multiple here for e.g. n-fer activations, unlike ADIF SIG_INFO. Still named "sig_refs" in the API for backwards compatibility. description: Activity references. We allow multiple here for e.g. n-fer activations, unlike ADIF SIG_INFO. Still named "sig_refs" in the API for backwards compatibility.
alert_type:
description: "The type of alert this is: xOTA, DXpedition, or Contest."
$ref: "#/components/schemas/AlertType"
url: url:
type: string type: string
description: A URL linking to more information about the alert, e.g. DXpedition or contest info. description: A URL linking to more information about the alert, e.g. DXpedition or contest info.
+14 -24
View File
@@ -54,7 +54,7 @@ function updateTable() {
const showDX = $("#tableShowDX")[0].checked; const showDX = $("#tableShowDX")[0].checked;
const showFreqsModes = $("#tableShowFreqsModes")[0].checked; const showFreqsModes = $("#tableShowFreqsModes")[0].checked;
const showComment = $("#tableShowComment")[0].checked; const showComment = $("#tableShowComment")[0].checked;
const showType = $("#tableShowType")[0].checked; const showActivity = $("#tableShowActivity")[0].checked;
const showRef = $("#tableShowRef")[0].checked; const showRef = $("#tableShowRef")[0].checked;
// Populate table with headers // Populate table with headers
@@ -75,11 +75,11 @@ function updateTable() {
if (showComment) { if (showComment) {
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Comment</th>`); table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Comment</th>`);
} }
if (showType) { if (showActivity) {
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Type</th>`); table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Activity</th>`);
} }
if (showRef) { if (showRef) {
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Ref.</th>`); table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Reference</th>`);
} }
table.find('tbody').empty(); table.find('tbody').empty();
@@ -151,7 +151,7 @@ function addAlertRowsToTable(tbody, alerts) {
const showDX = $("#tableShowDX")[0].checked; const showDX = $("#tableShowDX")[0].checked;
const showFreqsModes = $("#tableShowFreqsModes")[0].checked; const showFreqsModes = $("#tableShowFreqsModes")[0].checked;
const showComment = $("#tableShowComment")[0].checked; const showComment = $("#tableShowComment")[0].checked;
const showType = $("#tableShowType")[0].checked; const showActivity = $("#tableShowActivity")[0].checked;
const showRef = $("#tableShowRef")[0].checked; const showRef = $("#tableShowRef")[0].checked;
// Get times for the alert, and convert to local time if necessary. // Get times for the alert, and convert to local time if necessary.
@@ -210,14 +210,14 @@ function addAlertRowsToTable(tbody, alerts) {
if (a["dx_calls"] != null) { if (a["dx_calls"] != null) {
dx_calls_html = a["dx_calls"].map(call => `<a class='dx-link' href='https://qrz.com/db/${call}' target='_new'>${call}</a>`).join(", "); dx_calls_html = a["dx_calls"].map(call => `<a class='dx-link' href='https://qrz.com/db/${call}' target='_new'>${call}</a>`).join(", ");
} }
if (dx_calls_html === "" && a["alert_type"] === "CONTEST") { if (dx_calls_html === "" && a["sig"] === "Contest") {
// Contest = true and no DX callsigns, so display "Contest" // Contest = true and no DX callsigns, so display "Contest"
dx_calls_html = "Contest" dx_calls_html = "Contest"
} }
// Format DXpedition country // Format DXpedition country
let dx_country_html = ""; let dx_country_html = "";
if (a["alert_type"] === "DXPEDITION" && a["dx_country"] != null && a["dx_country"] !== "") { if (a["sig"] === "DXpedition" && a["dx_country"] != null && a["dx_country"] !== "") {
dx_country_html = `<br/>${a["dx_country"]}`; dx_country_html = `<br/>${a["dx_country"]}`;
} }
@@ -250,20 +250,10 @@ function addAlertRowsToTable(tbody, alerts) {
} }
// Type, activity or fallback to source // Activity or fallback to "General DX"
let activityTypeText = a["source"]; let activityText = "General DX";
if (a["alert_type"] === "CONTEST") { if (a["sig"]) {
activityTypeText = "Contest"; activityText = a["sig"];
} else if (a["alert_type"] === "DXPEDITION") {
activityTypeText = "DXpedition";
} else if (a["alert_type"] === "SATELLITE") {
activityTypeText = "Satellite";
} else if (a["alert_type"] === "XOTA") {
if (a["sig"]) {
activityTypeText = a["sig"];
} else {
activityTypeText = "xOTA";
}
} }
// Format activity refs // Format activity refs
@@ -296,8 +286,8 @@ function addAlertRowsToTable(tbody, alerts) {
if (showComment) { if (showComment) {
$tr.append(`<td class='hideonmobile'>${commentText}</td>`); $tr.append(`<td class='hideonmobile'>${commentText}</td>`);
} }
if (showType) { if (showActivity) {
$tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${a["icon"]}'></i></span> ${activityTypeText}</td>`); $tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${a["icon"]}'></i></span> ${activityText}</td>`);
} }
if (showRef) { if (showRef) {
$tr.append(`<td class='hideonmobile'>${activityRefs}</td>`); $tr.append(`<td class='hideonmobile'>${activityRefs}</td>`);
@@ -314,7 +304,7 @@ function addAlertRowsToTable(tbody, alerts) {
} }
const $td2 = $("<td colspan='100'>"); const $td2 = $("<td colspan='100'>");
if (showType) { if (showActivity) {
$td2.append(`<span class='icon-wrapper'><i class='fa-solid ${a["icon"]}'></i></span> `); $td2.append(`<span class='icon-wrapper'><i class='fa-solid ${a["icon"]}'></i></span> `);
} }
if (showRef) { if (showRef) {
+13 -13
View File
@@ -128,7 +128,7 @@ function updateTable() {
const showComment = $("#tableShowComment")[0].checked; const showComment = $("#tableShowComment")[0].checked;
const showBearing = $("#tableShowBearing")[0].checked && userPos != null; const showBearing = $("#tableShowBearing")[0].checked && userPos != null;
const showDistance = $("#tableShowDistance")[0].checked && userPos != null; const showDistance = $("#tableShowDistance")[0].checked && userPos != null;
const showType = $("#tableShowType")[0].checked; const showActivity = $("#tableShowActivity")[0].checked;
const showRef = $("#tableShowRef")[0].checked; const showRef = $("#tableShowRef")[0].checked;
const showDE = $("#tableShowDE")[0].checked; const showDE = $("#tableShowDE")[0].checked;
const showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked; const showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked;
@@ -157,11 +157,11 @@ function updateTable() {
if (showDistance) { if (showDistance) {
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Distance</th>`); table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Distance</th>`);
} }
if (showType) { if (showActivity) {
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Type</th>`); table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Activity</th>`);
} }
if (showRef) { if (showRef) {
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Ref.</th>`); table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>Reference</th>`);
} }
if (showDE) { if (showDE) {
table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>DE</th>`); table.find('thead tr').append(`<th class='bg-primary-subtle hideonmobile'>DE</th>`);
@@ -208,7 +208,7 @@ function createNewTableRowsForSpot(s, highlightNew) {
const showComment = $("#tableShowComment")[0].checked; const showComment = $("#tableShowComment")[0].checked;
const showBearing = $("#tableShowBearing")[0].checked && userPos != null; const showBearing = $("#tableShowBearing")[0].checked && userPos != null;
const showDistance = $("#tableShowDistance")[0].checked && userPos != null; const showDistance = $("#tableShowDistance")[0].checked && userPos != null;
const showType = $("#tableShowType")[0].checked; const showActivity = $("#tableShowActivity")[0].checked;
const showRef = $("#tableShowRef")[0].checked; const showRef = $("#tableShowRef")[0].checked;
const showDE = $("#tableShowDE")[0].checked; const showDE = $("#tableShowDE")[0].checked;
const showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked; const showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked;
@@ -327,10 +327,10 @@ function createNewTableRowsForSpot(s, highlightNew) {
} }
} }
// Format "type" (activity or fallback to source) // Format activity
let typeText = s["source"]; let activityText = "General DX";
if (s["sig"]) { if (s["sig"]) {
typeText = s["sig"]; activityText = s["sig"];
} }
// Format activity refs // Format activity refs
@@ -397,8 +397,8 @@ function createNewTableRowsForSpot(s, highlightNew) {
if (showDistance) { if (showDistance) {
$tr.append(`<td class='nowrap hideonmobile'>${distanceText}</td>`); $tr.append(`<td class='nowrap hideonmobile'>${distanceText}</td>`);
} }
if (showType) { if (showActivity) {
$tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${s["icon"]}'></i></span> ${typeText}</td>`); $tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${s["icon"]}'></i></span> ${activityText}</td>`);
} }
if (showRef) { if (showRef) {
$tr.append(`<td class='hideonmobile' style='max-width: 11em;'>${activityRefs}</td>`); $tr.append(`<td class='hideonmobile' style='max-width: 11em;'>${activityRefs}</td>`);
@@ -410,7 +410,7 @@ function createNewTableRowsForSpot(s, highlightNew) {
$tr.append(`<td class='nowrap hideonmobile'>${workedCheckbox}</td>`); $tr.append(`<td class='nowrap hideonmobile'>${workedCheckbox}</td>`);
} }
// Second row for mobile view only, containing type, ref & comment // Second row for mobile view only, containing activity, ref & comment
const $tr2 = $("<tr class='hidenotonmobile'>"); const $tr2 = $("<tr class='hidenotonmobile'>");
// Apply styles as per the first row // Apply styles as per the first row
@@ -429,8 +429,8 @@ function createNewTableRowsForSpot(s, highlightNew) {
const $td2 = $("<td colspan='100'>"); const $td2 = $("<td colspan='100'>");
const $td2floatleft = $(`<div style="float: left;">`); const $td2floatleft = $(`<div style="float: left;">`);
if (showType) { if (showActivity) {
$td2floatleft.append(`<span class='icon-wrapper'><i class='fa-solid ${s["icon"]}'></i></span> ${typeText} `); $td2floatleft.append(`<span class='icon-wrapper'><i class='fa-solid ${s["icon"]}'></i></span> ${activityText} `);
} }
if (showRef) { if (showRef) {
$td2floatleft.append(`${activityRefs} `); $td2floatleft.append(`${activityRefs} `);
+1 -1
View File
@@ -60,7 +60,7 @@ function generateActivitiesMultiToggleFilterCard(activity_options) {
const domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, ""); const domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
$grid.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-${domSafeName}" value="${o['name']}" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-${domSafeName}" for="filter-button-sig-${domSafeName}" title="${o['description']}"><i class="fa-solid ${o['icon']}"></i> ${o['name']} ${(o["region_flag"] != null) ? o['region_flag'] : ''}</label></div></div>`); $grid.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-${domSafeName}" value="${o['name']}" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-${domSafeName}" for="filter-button-sig-${domSafeName}" title="${o['description']}"><i class="fa-solid ${o['icon']}"></i> ${o['name']} ${(o["region_flag"] != null) ? o['region_flag'] : ''}</label></div></div>`);
}); });
$body.append(`<div class="w-100"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-NO_SIG" value="NO_SIG" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-NO_SIG" for="filter-button-sig-NO_SIG"><i class="fa-solid fa-tower-cell"></i> General DX</label></div></div>`); $body.append(`<div class="w-100 mb-1"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-NO_SIG" value="NO_SIG" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-NO_SIG" for="filter-button-sig-NO_SIG"><i class="fa-solid fa-tower-cell"></i> General DX</label></div></div>`);
$body.append($grid); $body.append($grid);
}); });
+4 -4
View File
@@ -39,16 +39,16 @@
</div> </div>
<div class="col"> <div class="col">
<div class="form-check"> <div class="form-check">
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowType" <input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowActivity"
value="tableShowType" oninput="columnsUpdated();" checked> value="tableShowActivity" oninput="columnsUpdated();" checked>
<label class="form-check-label" for="tableShowType">Source</label> <label class="form-check-label" for="tableShowActivity">Activity</label>
</div> </div>
</div> </div>
<div class="col"> <div class="col">
<div class="form-check"> <div class="form-check">
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowRef" <input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowRef"
value="tableShowRef" oninput="columnsUpdated();" checked> value="tableShowRef" oninput="columnsUpdated();" checked>
<label class="form-check-label" for="tableShowRef">Ref.</label> <label class="form-check-label" for="tableShowRef">Reference</label>
</div> </div>
</div> </div>
</div> </div>
+4 -4
View File
@@ -53,16 +53,16 @@
</div> </div>
<div class="col"> <div class="col">
<div class="form-check"> <div class="form-check">
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowType" <input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowActivity"
value="tableShowType" oninput="columnsUpdated();" checked> value="tableShowActivity" oninput="columnsUpdated();" checked>
<label class="form-check-label" for="tableShowType">Type</label> <label class="form-check-label" for="tableShowActivity">Activity</label>
</div> </div>
</div> </div>
<div class="col"> <div class="col">
<div class="form-check"> <div class="form-check">
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowRef" <input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowRef"
value="tableShowRef" oninput="columnsUpdated();" checked> value="tableShowRef" oninput="columnsUpdated();" checked>
<label class="form-check-label" for="tableShowRef">Ref.</label> <label class="form-check-label" for="tableShowRef">Reference</label>
</div> </div>
</div> </div>
<div class="col"> <div class="col">
+2 -3
View File
@@ -9,7 +9,6 @@ import tornado_eventsource.handler
from tornado import httputil from tornado import httputil
from tornado.web import Application from tornado.web import Application
from core.enums import AlertType
from core.utils import safe_json_dumps from core.utils import safe_json_dumps
from data.lookup_credentials import extract_credentials from data.lookup_credentials import extract_credentials
@@ -169,13 +168,13 @@ def alert_allowed_by_query(alert, query):
# the alert is a dxpedition, or contests_skip_max_duration_check and the alert is a contest, it also # the alert is a dxpedition, or contests_skip_max_duration_check and the alert is a contest, it also
# always passes the check. # always passes the check.
if ( if (
alert.alert_type == AlertType.DXPEDITION alert.sig == "DXpedition"
and "dxpeditions_skip_max_duration_check" in query and "dxpeditions_skip_max_duration_check" in query
and query.get("dxpeditions_skip_max_duration_check").upper() == "TRUE" and query.get("dxpeditions_skip_max_duration_check").upper() == "TRUE"
): ):
continue continue
if ( if (
alert.alert_type == AlertType.CONTEST alert.sig == "Contest"
and "contests_skip_max_duration_check" in query and "contests_skip_max_duration_check" in query
and query.get("contests_skip_max_duration_check").upper() == "TRUE" and query.get("contests_skip_max_duration_check").upper() == "TRUE"
): ):