diff --git a/data/activities.py b/data/activities.py index c44e16e..0e5c7c2 100644 --- a/data/activities.py +++ b/data/activities.py @@ -12,6 +12,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { # any spots with "contest" in the comment will get allocated to this activity. comment_names=["CONTEST"], icon="fa-trophy", + alerts_possible=True, ), ActivityName.DXPEDITION: Activity( name=ActivityName.DXPEDITION, @@ -23,6 +24,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { # this activity to a spot other ways. comment_names=[], icon="fa-book-atlas", + alerts_possible=True, ), ActivityName.SATELLITE: Activity( name=ActivityName.SATELLITE, @@ -32,6 +34,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { refs_globally_unique=False, comment_names=[], icon="fa-satellite", + alerts_possible=True, ), ActivityName.EME: Activity( name=ActivityName.EME, @@ -70,6 +73,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { refs_globally_unique=False, comment_names=["QRP"], icon="fa-volume-low", + alerts_possible=True, ), ActivityName.POTA: Activity( name=ActivityName.POTA, @@ -81,6 +85,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { ref_regex=r"[A-Z]{2}\-\d{4,5}|K\-TEST", comment_names=["POTA"], icon="fa-tree", + alerts_possible=True, ), ActivityName.SOTA: Activity( name=ActivityName.SOTA, @@ -92,6 +97,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}", comment_names=["SOTA"], icon="fa-mountain-sun", + alerts_possible=True, ), ActivityName.WWFF: Activity( name=ActivityName.WWFF, @@ -103,6 +109,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { ref_regex=r"[A-Z0-9]{1,3}FF\-\d{4}", comment_names=["WWFF"], icon="fa-seedling", + alerts_possible=True, ), ActivityName.GMA: Activity( name=ActivityName.GMA, @@ -136,6 +143,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{3}\-\d{3}", comment_names=["HEMA"], icon="fa-mound", + alerts_possible=True, ), ActivityName.IOTA: Activity( name=ActivityName.IOTA, @@ -202,6 +210,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { ref_regex=r"[A-Z]{2}\-[A-Z]{3}\d", comment_names=["SIOTA"], icon="fa-wheat-awn", + alerts_possible=True, ), ActivityName.WCA: Activity( name=ActivityName.WCA, @@ -225,6 +234,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { comment_names=["ZLOTA"], icon="fa-kiwi-bird", region_flag="π³πΏ", + alerts_possible=True, ), ActivityName.WOTA: Activity( name=ActivityName.WOTA, @@ -237,6 +247,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { comment_names=["WOTA"], icon="fa-w", region_flag="π¬π§", + alerts_possible=True, ), ActivityName.BOTA: Activity( name=ActivityName.BOTA, @@ -247,6 +258,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { ref_type=ActivityRefType.BEACH, comment_names=[], icon="fa-umbrella-beach", + alerts_possible=True, ), ActivityName.KRMNPA: Activity( name=ActivityName.KRMNPA, @@ -259,6 +271,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { comment_names=["KRMNPA"], icon="fa-earth-oceania", region_flag="π¦πΊ", + alerts_possible=True, ), ActivityName.SANPCPA: Activity( name=ActivityName.SANPCPA, @@ -271,6 +284,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { comment_names=["SANPCPA"], icon="fa-earth-oceania", region_flag="π¦πΊ", + alerts_possible=True, ), ActivityName.LLOTA: Activity( name=ActivityName.LLOTA, @@ -282,6 +296,7 @@ ACTIVITIES: dict[ActivityName, Activity] = { ref_regex=r"LL[A-Z]{2}\-\d{4}", comment_names=["LLOTA"], icon="fa-water", + alerts_possible=True, ), ActivityName.TOWERS: Activity( name=ActivityName.TOWERS, diff --git a/data/activity.py b/data/activity.py index a36efce..c0e2fb0 100644 --- a/data/activity.py +++ b/data/activity.py @@ -43,3 +43,7 @@ class Activity: # Emoji flag for the country or region where this activity is relevant, if any. If None, this implies the # activity is in worldwide usage. region_flag: str | None = None + # Can alerts ever have this activity? A lot of activities can be figured out from spot comments but can never + # occur in alerts, so to avoid showing all activities on the "upcoming" page, we allow it to filter based on + # this. + alerts_possible: bool = False diff --git a/static/apidocs/openapi.yml b/static/apidocs/openapi.yml index ffea99f..7faecb5 100644 --- a/static/apidocs/openapi.yml +++ b/static/apidocs/openapi.yml @@ -20,6 +20,7 @@ info: * 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 :) * Added QRP, RaDAR Rally, /AM and /MM activities + * Added `has_refs` and `alerts_possible` to Activity data ### 2.1 @@ -1604,6 +1605,15 @@ components: specific event (e.g. MOTA). Generally for Spothole's own internal use, clients probably won't need this. Used to group them in the web UI. Still named "sig_type" in the API for backwards compatibility. $ref: "#/components/schemas/ActivityType" + has_refs: + type: boolean + description: > + Whether this activity has a fixed set of references (e.g. parks, summits) with an ID that gets + "activated", as opposed to activities like Contest or DXpedition which don't. + ref_type: + description: > + The type of reference that gets activated for this activity, e.g. Park or Summit. + $ref: "#/components/schemas/ActivityRefType" comment_names: type: array description: > @@ -1639,6 +1649,11 @@ components: Flag emoji, if this activity is specific to a country or region. If null, this activity is treated as worldwide. example: "πΊπ³" + alerts_possible: + type: boolean + description: > + Whether alerts can ever have this activity. While Spothole can assign any activity from spot comments, there + are only a limited set that can ever crop up in alerts, because we don't parse general comments for alerts. SolarConditions: type: object diff --git a/static/js/alerts.js b/static/js/alerts.js index 09a58c7..a8f0c4a 100644 --- a/static/js/alerts.js +++ b/static/js/alerts.js @@ -332,7 +332,8 @@ function loadOptions() { // Populate the filters panel generateMultiToggleFilterCard("#dx_continent_options", "dx_continent", options["continents"]); generateMultiToggleFilterCard("#source-options", "source", options["alert_providers"]); - generateActivitiesMultiToggleFilterCard(options["sigs"]); + // Alerts can only ever be tagged with activities that have an alert source, so only offer those as filters here + generateActivitiesMultiToggleFilterCard(options["sigs"].filter(o => o["alerts_possible"]), false); // Load URL params. These may select things from the various filter & display options, so the function needs // to be called after these are set up, but if the URL params ask for "embedded mode", this will suppress diff --git a/static/js/common.js b/static/js/common.js index b5d50c6..d81d30c 100644 --- a/static/js/common.js +++ b/static/js/common.js @@ -136,8 +136,12 @@ function generateMultiToggleFilterCard(elementID, filterQuery, options) { } // Generate a collapsable section for the activities filter card, and append it to the given list. The section is -// expanded by default if isExpanded is true. -function appendActivityFilterSection($list, sectionId, heading, isExapanded, buildBody) { +// expanded by default if isExpanded is true. If hasContent is false (i.e. there are no activities to show in this +// section), the section is omitted entirely rather than showing an empty collapsible heading. +function appendActivityFilterSection($list, sectionId, heading, isExapanded, hasContent, buildBody) { + if (!hasContent) { + return; + } const collapseId = `activity-options-${sectionId}-collapse`; const $li = $('