diff --git a/server/webserver.py b/server/webserver.py index 91cc741..4e34811 100644 --- a/server/webserver.py +++ b/server/webserver.py @@ -207,6 +207,11 @@ class WebServer: needs_sig = query.get(k).upper() == "TRUE" if needs_sig: spots = [s for s in spots if s.sig] + case "needs_sig_ref": + # If true, at least one sig ref is required, regardless of what it is, it just can't be missing. + needs_sig_ref = query.get(k).upper() == "TRUE" + if needs_sig_ref: + spots = [s for s in spots if s.sig_refs and len(s.sig_refs) > 0] case "band": bands = query.get(k).split(",") spots = [s for s in spots if s.band and s.band in bands] @@ -230,11 +235,11 @@ class WebServer: prevent_qrt = query.get(k).upper() == "FALSE" if prevent_qrt: spots = [s for s in spots if not s.qrt or s.qrt == False] - case "needs_location": - # If true, spots require a location to be returned - needs_location = query.get(k).upper() == "TRUE" - if needs_location: - spots = [s for s in spots if s.latitude and s.longitude] + case "needs_good_location": + # If true, spots require a "good" location to be returned + needs_good_location = query.get(k).upper() == "TRUE" + if needs_good_location: + spots = [s for s in spots if s.dx_location_good] case "dedupe": # Ensure only the latest spot of each callsign is present in the list. This relies on the list being # in reverse time order, so if any future change allows re-ordering the list, that should be done diff --git a/webassets/apidocs/openapi.yml b/webassets/apidocs/openapi.yml index 44b508a..6b36373 100644 --- a/webassets/apidocs/openapi.yml +++ b/webassets/apidocs/openapi.yml @@ -85,7 +85,14 @@ paths: - IOTA - name: needs_sig in: query - description: "Limit the spots to only ones from a Special Interest Grous such as POTA. Because supplying all known SIGs as a `sigs` parameter is unwieldy, and leaving `sigs` blank will also return spots with *no* SIG, this parameter can be set true to return only spots with a SIG, regardless of what it is, so long as it's not blank. This is what Field Spotter uses to exclude generic cluster spots and only retrieve xOTA things." + description: "Limit the spots to only ones with a Special Interest Group such as POTA. Because supplying all known SIGs as a `sigs` parameter is unwieldy, and leaving `sigs` blank will also return spots with *no* SIG, this parameter can be set true to return only spots with a SIG, regardless of what it is, so long as it's not blank. This is what Field Spotter uses to exclude generic cluster spots and only retrieve xOTA things." + required: false + schema: + type: boolean + default: false + - name: needs_sig_ref + in: query + description: "Limit the spots to only ones which have at least one reference (e.g. a park reference) for Special Interest Groups such as POTA." required: false schema: type: boolean @@ -195,9 +202,9 @@ paths: required: false schema: type: string - - name: needs_location + - name: needs_good_location in: query - description: Return only spots with a location set. + description: "Return only spots with a 'good' location. (See the spot `dx_location_good` parameter for details. Useful for map-based clients, to avoid spots with 'bad' locations e.g. loads of cluster spots ending up in the centre of the DXCC entitity.)" required: false schema: type: boolean diff --git a/webassets/css/style.css b/webassets/css/style.css index 9f2ebd7..33e2a41 100644 --- a/webassets/css/style.css +++ b/webassets/css/style.css @@ -150,6 +150,110 @@ div#map { } +/* BANDS PANEL */ + +div#bands-container { + margin: 0; + padding: 0; + overflow-x: auto; + overflow-y: auto; + white-space: nowrap; + display: flex; + overscroll-behavior-x: none; +} + +/* Bands panel inner layout */ +div.bandCol { + height: 100%; + min-width: 8em; + display: flex; + flex-flow: column; + overflow-y: clip; +} + +div.bandColHeader { + flex: 0 1 auto; +} + +div.bandColMiddle { + flex: 1 1 auto; +} + +div.bandColMiddle ul { + display: table; + table-layout: fixed; + width: 100%; + min-height: 100%; + margin: 0; + padding: 0; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +div.bandColMiddle ul li { + display: table-row; + line-height: 0.5em; +} + +/*noinspection CssUnusedSymbol*/ +div.bandColMiddle ul li.withSpots { + line-height: 1em; +} + +div.bandColMiddle ul li span { + display: table-cell; + vertical-align: middle; +} + +div.bandColMiddle ul { + display: table; + table-layout: fixed; + width: 100%; + height: 100%; + margin: 0; + padding: 0; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-left: 2px dotted; +} + +div.bandColHeader { + text-align: center; + font-weight: bold; + padding: 0.5em; +} + +div.bandColMiddle { + margin-left: 3px; + border-left: 2px dotted var(--text); +} + +div.bandColSpot { + display: block; + border-radius: 3px; + padding: 3px; + background: lightyellow; + margin-right: 2em; +} + +span.bandColSpot { + vertical-align: bottom; + display: inline !important; +} + +/* Don't wrap frequencies */ +span.bandColSpotFreq { + white-space: nowrap; + display: inline !important; +} + +span.bandColSpotMode { + padding-left: 0.5em; + font-size: 0.8em; + line-height: 0.4em; +} + + /* GENERAL MOBILE SUPPORT */ @media (max-width: 991.99px) { diff --git a/webassets/js/bands.js b/webassets/js/bands.js index 4129333..ffcda9a 100644 --- a/webassets/js/bands.js +++ b/webassets/js/bands.js @@ -30,22 +30,20 @@ function updateBands() { // Stop here if nothing to display var bandsPanel = $("#bands-container"); if (spots.length === 0) { - // todo bootstrapify - bandsPanel.html("
There are no spots matching your filters.
"); + bandsPanel.html("