diff --git a/README.md b/README.md index 6362800..e97a875 100644 --- a/README.md +++ b/README.md @@ -31,3 +31,11 @@ If you're extending the `HTTPProvider` class, you will need to provide a URI to When constructing spots, use the comments in the Spot class and the existing implementations as an example. All parameters are optional, but you will at least want to provide a `time` (which must be timezone-aware) and a `dx_call`. Finally, simply add the appropriate config to the `providers` section of `config.yml`, and your provider should be instantiated on startup. + +### Third Party Libraries + +The project contains a self-hosted copy of Font Awesome's free library, in the `/fa/` directory. This is subject to Font Awesome's licence and is not covered by the overall licence declared in the `LICENSE` file. This approach was taken in preference to using their hosted kits due to the popularity of this project exceeding the page view limit for their free hosted offering. + +TODO JS & Python libs... + +This project would not have been possible without these libraries, so many thanks to their developers. diff --git a/data/spot.py b/data/spot.py index e28e0c4..59e3851 100644 --- a/data/spot.py +++ b/data/spot.py @@ -73,6 +73,8 @@ class Spot: sig_refs_names: list = None # Activation score. SOTA only activation_score: int = None + # Icon, from the Font Awesome set. This is fairly opinionated but is here to help the Spothole web UI and Field Spotter. Does not include the "fa-" prefix. + icon: str = "question" # Maidenhead grid locator for the spot. This could be from a geographical reference e.g. POTA, or just from the country grid: str = None # Latitude & longitude, in degrees. This could be from a geographical reference e.g. POTA, or from a QRZ lookup diff --git a/providers/aprsis.py b/providers/aprsis.py index 4ece117..4915e70 100644 --- a/providers/aprsis.py +++ b/providers/aprsis.py @@ -47,6 +47,7 @@ class APRSIS(Provider): comment=data["comment"] if "comment" in data else None, latitude=data["latitude"] if "latitude" in data else None, longitude=data["longitude"] if "longitude" in data else None, + icon="tower-cell", time=datetime.now(pytz.UTC)) # APRS-IS spots are live so we can assume spot time is "now" # Add to our list diff --git a/providers/dxcluster.py b/providers/dxcluster.py index 0647b92..54e7735 100644 --- a/providers/dxcluster.py +++ b/providers/dxcluster.py @@ -69,6 +69,7 @@ class DXCluster(Provider): de_call=match.group(1), freq=float(match.group(2)), comment=match.group(4).strip(), + icon="desktop", time=spot_datetime) # Add to our list diff --git a/providers/gma.py b/providers/gma.py index 5d6a67b..e5a98b8 100644 --- a/providers/gma.py +++ b/providers/gma.py @@ -32,6 +32,7 @@ class GMA(HTTPProvider): comment=source_spot["TEXT"], sig_refs=[source_spot["REF"]], sig_refs_names=[source_spot["NAME"]], + icon="person-hiking", time=datetime.strptime(source_spot["DATE"] + source_spot["TIME"], "%Y%m%d%H%M").replace(tzinfo=pytz.UTC), latitude=float(source_spot["LAT"]) if (source_spot["LAT"] != "") else None, # Seen GMA spots with no lat/lon longitude=float(source_spot["LON"]) if (source_spot["LON"] != "") else None) diff --git a/providers/hema.py b/providers/hema.py index fa23cff..261ba8a 100644 --- a/providers/hema.py +++ b/providers/hema.py @@ -54,6 +54,7 @@ class HEMA(HTTPProvider): sig="HEMA", sig_refs=[spot_items[3].upper()], sig_refs_names=[spot_items[4]], + icon="person-hiking", time=datetime.strptime(spot_items[0], "%d/%m/%Y %H:%M").replace(tzinfo=pytz.UTC), latitude=float(spot_items[7]), longitude=float(spot_items[8])) diff --git a/providers/parksnpeaks.py b/providers/parksnpeaks.py index 1bc585d..5ece5c3 100644 --- a/providers/parksnpeaks.py +++ b/providers/parksnpeaks.py @@ -29,6 +29,7 @@ class ParksNPeaks(HTTPProvider): comment=source_spot["actComments"], sig=source_spot["actClass"], sig_refs=[source_spot["actSiteID"]], + icon="question", # todo determine from actClass time=datetime.strptime(source_spot["actTime"], "%Y-%m-%d %H:%M:%S").replace(tzinfo=pytz.UTC)) # If this is POTA, SOTA or WWFF data we already have it through other means, so ignore. diff --git a/providers/pota.py b/providers/pota.py index 6921de2..e5ba12d 100644 --- a/providers/pota.py +++ b/providers/pota.py @@ -29,6 +29,7 @@ class POTA(HTTPProvider): sig="POTA", sig_refs=[source_spot["reference"]], sig_refs_names=[source_spot["name"]], + icon="tree", time=datetime.strptime(source_spot["spotTime"], "%Y-%m-%dT%H:%M:%S").replace(tzinfo=pytz.UTC), grid=source_spot["grid6"], latitude=source_spot["latitude"], diff --git a/providers/rbn.py b/providers/rbn.py index f66f910..0a7b727 100644 --- a/providers/rbn.py +++ b/providers/rbn.py @@ -70,6 +70,7 @@ class RBN(Provider): de_call=match.group(1), freq=float(match.group(2)), comment=match.group(4).strip(), + icon="tower-cell", time=spot_datetime) # Add to our list diff --git a/providers/sota.py b/providers/sota.py index e529c27..9d0233b 100644 --- a/providers/sota.py +++ b/providers/sota.py @@ -48,6 +48,7 @@ class SOTA(HTTPProvider): sig="SOTA", sig_refs=[source_spot["summitCode"]], sig_refs_names=[source_spot["summitName"]], + icon="mountain-sun", time=datetime.fromisoformat(source_spot["timeStamp"]), activation_score=source_spot["points"]) diff --git a/providers/wwbota.py b/providers/wwbota.py index 4ba21dc..d9e9e00 100644 --- a/providers/wwbota.py +++ b/providers/wwbota.py @@ -32,6 +32,7 @@ class WWBOTA(HTTPProvider): sig="WWBOTA", sig_refs=refs, sig_refs_names=ref_names, + icon="radiation", time=datetime.fromisoformat(source_spot["time"]), # WWBOTA spots can contain multiple references for bunkers being activated simultaneously. For # now, we will just pick the first one to use as our grid, latitude and longitude. diff --git a/providers/wwff.py b/providers/wwff.py index 03ffafa..a75081f 100644 --- a/providers/wwff.py +++ b/providers/wwff.py @@ -29,6 +29,7 @@ class WWFF(HTTPProvider): sig="WWFF", sig_refs=[source_spot["reference"]], sig_refs_names=[source_spot["reference_name"]], + icon="seedling", time=datetime.fromtimestamp(source_spot["spot_time"]).replace(tzinfo=pytz.UTC), latitude=source_spot["latitude"], longitude=source_spot["longitude"]) diff --git a/views/webpage_base.tpl b/views/webpage_base.tpl index c36ad07..0d1dbc6 100644 --- a/views/webpage_base.tpl +++ b/views/webpage_base.tpl @@ -6,15 +6,17 @@ (S)pothole - + + + - - - - - + + + + + diff --git a/webassets/apidocs/openapi.yml b/webassets/apidocs/openapi.yml index 762a052..2b37540 100644 --- a/webassets/apidocs/openapi.yml +++ b/webassets/apidocs/openapi.yml @@ -493,6 +493,10 @@ components: type: integer description: Activation score. SOTA only example: 0 + icon: + type: string + descripton: Icon, from the Font Awesome set. This is fairly opinionated but is here to help the Spothole web UI and Field Spotter. Does not include the "fa-" prefix. + example: tree grid: type: string description: Maidenhead grid locator for the spot. This could be from a geographical reference e.g. POTA, or just from the country diff --git a/webassets/css/style.css b/webassets/css/style.css index 16d2711..5d067b5 100644 --- a/webassets/css/style.css +++ b/webassets/css/style.css @@ -7,4 +7,10 @@ max-width: 60em; margin: 0 auto; } +} + +span.icon-wrapper { + display: inline-block; + width: 1.5em; + text-align: center; } \ No newline at end of file diff --git a/webassets/js/code.js b/webassets/js/code.js index b43350a..b228d6c 100644 --- a/webassets/js/code.js +++ b/webassets/js/code.js @@ -36,7 +36,7 @@ function loadSpots() { $tr.append(`${row["freq"]}`); $tr.append(`${row["mode"]}`); $tr.append('' + escapeHtml(`${row["comment"]}`) + ''); - $tr.append(`${row["source"]}`); + $tr.append(` ${row["source"]}`); $tr.append(`${row["de_flag"]} ${row["de_call"]}`); table.find('tbody').append($tr); });