mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-03-15 20:34:31 +00:00
Compare commits
8 Commits
web_ui_opt
...
9241a26a47
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9241a26a47 | ||
|
|
3be63a8dd6 | ||
|
|
1e3cec1599 | ||
|
|
7b409bcb67 | ||
|
|
47b4ddb5c8 | ||
|
|
94094974d0 | ||
|
|
5230fa535f | ||
|
|
2be1c5b3d3 |
@@ -189,5 +189,14 @@ web-ui-options:
|
|||||||
max-spot-age-default: 30
|
max-spot-age-default: 30
|
||||||
alert-count: [25, 50, 100, 200, 500]
|
alert-count: [25, 50, 100, 200, 500]
|
||||||
alert-count-default: 100
|
alert-count-default: 100
|
||||||
default-color-scheme: "auto"
|
# Default UI colour scheme. Supported values are "light", "dark" and "auto" (i.e. use the browser/OS colour scheme).
|
||||||
default-band-color-scheme: "PSK Reporter (Adjusted)"
|
# Users can still override this in the UI to their own preference.
|
||||||
|
color-scheme-default: "auto"
|
||||||
|
# Default band colour scheme. Supported values are the full names of any band colour scheme shown in the UI.
|
||||||
|
# Users can still override this in the UI to their own preference.
|
||||||
|
band-color-scheme-default: "PSK Reporter (Adjusted)"
|
||||||
|
# Custom HTML insert. This can be any arbitrary HTML. It will be inserted next to the start/stop buttons on the spots
|
||||||
|
# (home) page, although being arbitrary HTML you can also use a div with absolute, relative, float placement etc. This
|
||||||
|
# is designed for a "donate/support the server" type button, though you are free to do whatever you want with it.
|
||||||
|
# As the server owner you are responsible for the safe usage of this option!
|
||||||
|
support-button-html: ""
|
||||||
@@ -2,7 +2,6 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
import tornado
|
import tornado
|
||||||
import json
|
|
||||||
|
|
||||||
from core.config import ALLOW_SPOTTING, WEB_UI_OPTIONS
|
from core.config import ALLOW_SPOTTING, WEB_UI_OPTIONS
|
||||||
from core.constants import SOFTWARE_VERSION
|
from core.constants import SOFTWARE_VERSION
|
||||||
@@ -24,5 +23,5 @@ class PageTemplateHandler(tornado.web.RequestHandler):
|
|||||||
|
|
||||||
# Load named template, and provide variables used in templates
|
# Load named template, and provide variables used in templates
|
||||||
self.render(self.template_name + ".html", software_version=SOFTWARE_VERSION, allow_spotting=ALLOW_SPOTTING,
|
self.render(self.template_name + ".html", software_version=SOFTWARE_VERSION, allow_spotting=ALLOW_SPOTTING,
|
||||||
web_ui_options=json.dumps(WEB_UI_OPTIONS))
|
web_ui_options=WEB_UI_OPTIONS)
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,9 @@
|
|||||||
<p>Spothole collects no data about you, and there is no way to enter personally identifying information into the site apart from by spotting and alerting through Spothole or the various services it connects to. All spots and alerts are "timed out" and deleted from the system after a set interval, which by default is one hour for spots and one week for alerts.</p>
|
<p>Spothole collects no data about you, and there is no way to enter personally identifying information into the site apart from by spotting and alerting through Spothole or the various services it connects to. All spots and alerts are "timed out" and deleted from the system after a set interval, which by default is one hour for spots and one week for alerts.</p>
|
||||||
<p>Settings you select from Spothole's menus are sent to the server, in order to provide the data with the requested filters. They are also stored in your browser's local storage, so that your preferences are remembered between sessions.</p>
|
<p>Settings you select from Spothole's menus are sent to the server, in order to provide the data with the requested filters. They are also stored in your browser's local storage, so that your preferences are remembered between sessions.</p>
|
||||||
<p>There are no trackers, no ads, and no cookies.</p>
|
<p>There are no trackers, no ads, and no cookies.</p>
|
||||||
|
{% if len(web_ui_options["support-button-html"]) > 0 %}
|
||||||
|
<p><strong>Caveat: </strong> The owner of this server has chosen to inject their own content into the "spots" page. This is designed for a "donate" or "support this server" button. The functionality of this injected content is the responsibility of the server owner, rather than the Spothole software.</p>
|
||||||
|
{% end %}
|
||||||
<p>Spothole is open source, so you can audit <a href="https://git.ianrenton.com/ian/spothole">the code</a> if you like.</p>
|
<p>Spothole is open source, so you can audit <a href="https://git.ianrenton.com/ian/spothole">the code</a> if you like.</p>
|
||||||
<h2 class="mt-4">Thanks</h2>
|
<h2 class="mt-4">Thanks</h2>
|
||||||
<p>This project would not have been possible without those volunteers who have taken it upon themselves to run DX clusters, xOTA programmes, DXpedition lists, callsign lookup databases, and other online tools on which Spothole's data is based.</p>
|
<p>This project would not have been possible without those volunteers who have taken it upon themselves to run DX clusters, xOTA programmes, DXpedition lists, callsign lookup databases, and other online tools on which Spothole's data is based.</p>
|
||||||
@@ -63,7 +66,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=7"></script>
|
<script src="/js/common.js?v=8"></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=7"></script>
|
<script src="/js/common.js?v=8"></script>
|
||||||
<script src="/js/add-spot.js?v=7"></script>
|
<script src="/js/add-spot.js?v=8"></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 %}
|
||||||
@@ -2,163 +2,49 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<div id="settingsButtonRow" class="row">
|
<div id="settingsButtonRow" class="row mb-3">
|
||||||
<div class="col-auto me-auto pt-3">
|
<div class="col-auto me-auto pt-3">
|
||||||
<p id="timing-container">Loading...</p>
|
{% module Template("widgets/refresh-timer.html", web_ui_options=web_ui_options) %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<p class="d-inline-flex gap-1">
|
<div class="d-inline-flex gap-1">
|
||||||
<button id="filters-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button" onclick="toggleFiltersPanel();"><i class="fa-solid fa-filter"></i> Filters</button>
|
{% module Template("widgets/filters-display-buttons.html", web_ui_options=web_ui_options) %}
|
||||||
<button id="display-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button" onclick="toggleDisplayPanel();"><i class="fa-solid fa-desktop"></i> Display</button>
|
</div>
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="filters-area" class="appearing-panel card mb-3">
|
<div id="filters-area" class="appearing-panel card mb-3">
|
||||||
<div class="card-header text-white bg-primary">
|
{% module Template("widgets/filters-area-header.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="row">
|
|
||||||
<div class="col-auto me-auto">
|
|
||||||
Filters
|
|
||||||
</div>
|
|
||||||
<div class="col-auto d-inline-flex">
|
|
||||||
<button id="close-filters-button" type="button" class="btn-close btn-close-white" aria-label="Close" onclick="closeFiltersPanel();"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row row-cols-1 row-cols-md-3 g-4">
|
<div class="row row-cols-1 row-cols-md-3 g-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/dx-continent.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">DX Continent</h5>
|
|
||||||
<p id="dx-continent-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/sources.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Sources</h5>
|
|
||||||
<p id="source-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/duration-limit-alerts.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Duration Limit <i class='fa-solid fa-circle-question' title='Some users create long-duration alerts for the period they will be generally in and around xOTA references, when they are not indending to be on the air most of the time. Use this control to restrict the maximum duration of spots that the software will display, and exclude any with a long duration, to avoid these filling up the list. By default, we allow DXpeditions to be displayed even if they are longer than this limit, because on a DXpedition the operators typically ARE on the air most of the time.'></i></h5>
|
|
||||||
<p class="card-text spothole-card-text">
|
|
||||||
Hide any alerts lasting more than:<br/>
|
|
||||||
<select id="max-duration" class="storeable-select form-select" onclick="filtersUpdated();" style="width: 8em; display: inline-block;">
|
|
||||||
<option value="10800">3 hours</option>
|
|
||||||
<option value="43200">12 hours</option>
|
|
||||||
<option value="86400" selected>24 hours</option>
|
|
||||||
<option value="604800">1 week</option>
|
|
||||||
<option value="2419200">4 weeks</option>
|
|
||||||
<option value="9999999999">No limit</option>
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
<p class='card-text spothole-card-text' style='line-height: 1.5em !important;'>
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" value="" onclick="filtersUpdated();" id="dxpeditions_skip_max_duration_check" checked><label class="form-check-label ms-2" for="dxpeditions_skip_max_duration_check">Allow DXpeditions that are longer</label>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="display-area" class="appearing-panel card mb-3">
|
<div id="display-area" class="appearing-panel card mb-3">
|
||||||
<div class="card-header text-white bg-primary">
|
{% module Template("widgets/display-area-header.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="row">
|
|
||||||
<div class="col-auto me-auto">
|
|
||||||
Display
|
|
||||||
</div>
|
|
||||||
<div class="col-auto d-inline-flex">
|
|
||||||
<button id="close-display-button" type="button" class="btn-close btn-close-white" aria-label="Close" onclick="closeDisplayPanel();"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div id="display-container" class="row row-cols-1 row-cols-md-3 g-4">
|
<div id="display-container" class="row row-cols-1 row-cols-md-3 g-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/time-zone.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Time Zone</h5>
|
|
||||||
<p class="card-text spothole-card-text"> Use
|
|
||||||
<select id="timeZone" class="storeable-select form-select ms-2 me-2 d-inline-block" oninput="timeZoneUpdated();" style="width: 8em; display: inline-block;">
|
|
||||||
<option value="UTC" selected>UTC</option>
|
|
||||||
<option value="local">Local time</option>
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/number-of-alerts.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Number of Alerts</h5>
|
|
||||||
<p class="card-text spothole-card-text">Show up to
|
|
||||||
<select id="alerts-to-fetch" class="storeable-select form-select ms-2" oninput="filtersUpdated();" style="width: 5em;display: inline-block;">
|
|
||||||
</select>
|
|
||||||
alerts
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/color-scheme.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Theme</h5>
|
|
||||||
<p class="card-text spothole-card-text">
|
|
||||||
<label class="form-check-label" for="color-scheme">UI color scheme</label>
|
|
||||||
<select id="color-scheme" class="storeable-select form-select d-inline-block" oninput="setColorSchemeFromUI();" style="display: inline-block;">
|
|
||||||
<option value="auto">Automatic</option>
|
|
||||||
<option value="light">Light</option>
|
|
||||||
<option value="dark">Dark</option>
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/table-columns-alerts.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Table Data</h5>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowStartTime" value="tableShowStartTime" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowStartTime">Start Time</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowEndTime" value="tableShowEndTime" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowEndTime">End Time</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowDX" value="tableShowDX" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowDX">DX</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowFreqsModes" value="tableShowFreqsModes" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowFreqsModes">Frequencies & Modes</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowComment" value="tableShowComment" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowComment">Comment</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowSource" value="tableShowSource" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowSource">Source</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowRef" value="tableShowRef" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowRef">Ref.</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -170,8 +56,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/common.js?v=7"></script>
|
<script src="/js/common.js?v=8"></script>
|
||||||
<script src="/js/alerts.js?v=7"></script>
|
<script src="/js/alerts.js?v=8"></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 %}
|
||||||
@@ -2,131 +2,54 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<div id="settingsButtonRow" class="row">
|
<div id="settingsButtonRow" class="row mb-3">
|
||||||
<div class="col-auto me-auto pt-3">
|
<div class="col-auto me-auto pt-3">
|
||||||
<p id="timing-container">Loading...</p>
|
{% module Template("widgets/refresh-timer.html", web_ui_options=web_ui_options) %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<p class="d-inline-flex gap-1">
|
<div class="d-inline-flex gap-1">
|
||||||
<button id="filters-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button" onclick="toggleFiltersPanel();"><i class="fa-solid fa-filter"></i> Filters</button>
|
{% module Template("widgets/filters-display-buttons.html", web_ui_options=web_ui_options) %}
|
||||||
<button id="display-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button" onclick="toggleDisplayPanel();"><i class="fa-solid fa-desktop"></i> Display</button>
|
</div>
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="filters-area" class="appearing-panel card mb-3">
|
<div id="filters-area" class="appearing-panel card mb-3">
|
||||||
<div class="card-header text-white bg-primary">
|
{% module Template("widgets/filters-area-header.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="row">
|
|
||||||
<div class="col-auto me-auto">
|
|
||||||
Filters
|
|
||||||
</div>
|
|
||||||
<div class="col-auto d-inline-flex">
|
|
||||||
<button id="close-filters-button" type="button" class="btn-close btn-close-white" aria-label="Close" onclick="closeFiltersPanel();"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row row-cols-1 g-4 mb-4 row-cols-md-3">
|
<div class="row row-cols-1 g-4 mb-4 row-cols-md-3">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/bands.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Bands</h5>
|
|
||||||
<p id="band-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/sigs.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">SIGs</h5>
|
|
||||||
<p id="sig-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/sources.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Sources</h5>
|
|
||||||
<p id="source-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row row-cols-1 row-cols-md-3 g-4">
|
<div class="row row-cols-1 row-cols-md-3 g-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/dx-continent.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">DX Continent</h5>
|
|
||||||
<p id="dx-continent-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/de-continent.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">DE Continent</h5>
|
|
||||||
<p id="de-continent-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/modes.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Modes</h5>
|
|
||||||
<p id="mode-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="display-area" class="appearing-panel card mb-3">
|
<div id="display-area" class="appearing-panel card mb-3">
|
||||||
<div class="card-header text-white bg-primary">
|
{% module Template("widgets/display-area-header.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="row">
|
|
||||||
<div class="col-auto me-auto">
|
|
||||||
Display
|
|
||||||
</div>
|
|
||||||
<div class="col-auto d-inline-flex">
|
|
||||||
<button id="close-display-button" type="button" class="btn-close btn-close-white" aria-label="Close" onclick="closeDisplayPanel();"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div id="display-container" class="row row-cols-1 row-cols-md-4 g-4">
|
<div id="display-container" class="row row-cols-1 row-cols-md-4 g-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/spot-age.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Spot Age</h5>
|
|
||||||
<p class="card-text spothole-card-text">Last
|
|
||||||
<select id="max-spot-age" class="storeable-select form-select ms-2 me-2 d-inline-block" oninput="filtersUpdated();" style="width: 5em; display: inline-block;">
|
|
||||||
</select>
|
|
||||||
minutes
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/color-scheme-and-band-color-scheme.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Theme</h5>
|
|
||||||
<p class="card-text spothole-card-text">
|
|
||||||
<label class="form-check-label" for="color-scheme">UI color scheme</label>
|
|
||||||
<select id="color-scheme" class="storeable-select form-select d-inline-block" oninput="setColorSchemeFromUI();" style="display: inline-block;">
|
|
||||||
<option value="auto">Automatic</option>
|
|
||||||
<option value="light">Light</option>
|
|
||||||
<option value="dark">Dark</option>
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
<p class="card-text spothole-card-text">
|
|
||||||
<label class="form-check-label" for="band-color-scheme">Band color scheme</label><br/>
|
|
||||||
<select id="band-color-scheme" class="storeable-select form-select d-inline-block" oninput="setBandColorSchemeFromUI();" style="display: inline-block;">
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -136,9 +59,12 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/common.js?v=7"></script>
|
<script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=7"></script>
|
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
||||||
<script src="/js/bands.js?v=7"></script>
|
</script>
|
||||||
|
<script src="/js/common.js?v=8"></script>
|
||||||
|
<script src="/js/spotsbandsandmap.js?v=8"></script>
|
||||||
|
<script src="/js/bands.js?v=8"></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 %}
|
||||||
@@ -46,14 +46,10 @@
|
|||||||
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"></script>
|
||||||
|
|
||||||
<script src="https://misc.ianrenton.com/jsutils/utils.js?v=7"></script>
|
<script src="https://misc.ianrenton.com/jsutils/utils.js?v=8"></script>
|
||||||
<script src="https://misc.ianrenton.com/jsutils/storage.js?v=7"></script>
|
<script src="https://misc.ianrenton.com/jsutils/storage.js?v=8"></script>
|
||||||
<script src="https://misc.ianrenton.com/jsutils/ui-ham.js?v=7"></script>
|
<script src="https://misc.ianrenton.com/jsutils/ui-ham.js?v=8"></script>
|
||||||
<script src="https://misc.ianrenton.com/jsutils/geo.js?v=7"></script>
|
<script src="https://misc.ianrenton.com/jsutils/geo.js?v=8"></script>
|
||||||
<script>
|
|
||||||
// Get Web UI Options from the backend to the frontend as a JS object.
|
|
||||||
let web_ui_options = JSON.parse('{{ web_ui_options }}'.replace(/"/g, '\"'));
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
6
templates/cards/bands.html
Normal file
6
templates/cards/bands.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Bands</h5>
|
||||||
|
<p id="band-options" class="card-text spothole-card-text"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
11
templates/cards/color-scheme-and-band-color-scheme.html
Normal file
11
templates/cards/color-scheme-and-band-color-scheme.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Theme</h5>
|
||||||
|
<p class="card-text spothole-card-text">
|
||||||
|
{% module Template("widgets/color-scheme.html", web_ui_options=web_ui_options) %}
|
||||||
|
</p>
|
||||||
|
<p class="card-text spothole-card-text">
|
||||||
|
{% module Template("widgets/band-color-scheme.html", web_ui_options=web_ui_options) %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
8
templates/cards/color-scheme.html
Normal file
8
templates/cards/color-scheme.html
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Theme</h5>
|
||||||
|
<p class="card-text spothole-card-text">
|
||||||
|
{% module Template("widgets/color-scheme.html", web_ui_options=web_ui_options) %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
6
templates/cards/de-continent.html
Normal file
6
templates/cards/de-continent.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">DE Continent</h5>
|
||||||
|
<p id="de-continent-options" class="card-text spothole-card-text"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
19
templates/cards/duration-limit-alerts.html
Normal file
19
templates/cards/duration-limit-alerts.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Duration Limit <i class='fa-solid fa-circle-question' title='Some users create long-duration alerts for the period they will be generally in and around xOTA references, when they are not indending to be on the air most of the time. Use this control to restrict the maximum duration of spots that the software will display, and exclude any with a long duration, to avoid these filling up the list. By default, we allow DXpeditions to be displayed even if they are longer than this limit, because on a DXpedition the operators typically ARE on the air most of the time.'></i></h5>
|
||||||
|
<p class="card-text spothole-card-text">
|
||||||
|
Hide any alerts lasting more than:<br/>
|
||||||
|
<select id="max-duration" class="storeable-select form-select" onclick="filtersUpdated();" style="width: 8em; display: inline-block;">
|
||||||
|
<option value="10800">3 hours</option>
|
||||||
|
<option value="43200">12 hours</option>
|
||||||
|
<option value="86400" selected>24 hours</option>
|
||||||
|
<option value="604800">1 week</option>
|
||||||
|
<option value="2419200">4 weeks</option>
|
||||||
|
<option value="9999999999">No limit</option>
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
<p class='card-text spothole-card-text' style='line-height: 1.5em !important;'>
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" value="" onclick="filtersUpdated();" id="dxpeditions_skip_max_duration_check" checked><label class="form-check-label ms-2" for="dxpeditions_skip_max_duration_check">Allow DXpeditions that are longer</label>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
6
templates/cards/dx-continent.html
Normal file
6
templates/cards/dx-continent.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">DX Continent</h5>
|
||||||
|
<p id="dx-continent-options" class="card-text spothole-card-text"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
9
templates/cards/location.html
Normal file
9
templates/cards/location.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Location</h5>
|
||||||
|
<div class="form-group spothole-card-text">
|
||||||
|
<label for="userGrid">Your grid:</label>
|
||||||
|
<input type="text" class="storeable-text form-control" id="userGrid" placeholder="AA00aa" oninput="userGridUpdated();" style="width: 10em; display: inline-block;">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
11
templates/cards/map-features.html
Normal file
11
templates/cards/map-features.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Map Features</h5>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="mapShowGeodesics" value="mapShowGeodesics" oninput="displayUpdated();">
|
||||||
|
<label class="form-check-label" for="mapShowGeodesics">Geodesic Lines</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
6
templates/cards/modes.html
Normal file
6
templates/cards/modes.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Modes</h5>
|
||||||
|
<p id="mode-options" class="card-text spothole-card-text"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
13
templates/cards/number-of-alerts.html
Normal file
13
templates/cards/number-of-alerts.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Number of Alerts</h5>
|
||||||
|
<p class="card-text spothole-card-text">Show up to
|
||||||
|
<select id="alerts-to-fetch" class="storeable-select form-select ms-2" oninput="filtersUpdated();" style="width: 5em;display: inline-block;">
|
||||||
|
{% for c in web_ui_options["alert-count"] %}
|
||||||
|
<option value="{{c}}" {% if web_ui_options["alert-count-default"] == c %}selected{% end %}>{{c}}</option>
|
||||||
|
{% end %}
|
||||||
|
</select>
|
||||||
|
alerts
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
13
templates/cards/number-of-spots.html
Normal file
13
templates/cards/number-of-spots.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Number of Spots</h5>
|
||||||
|
<p class="card-text spothole-card-text">Show up to
|
||||||
|
<select id="spots-to-fetch" class="storeable-select form-select ms-2 me-2 d-inline-block" oninput="filtersUpdated();" style="width: 5em; display: inline-block;">
|
||||||
|
{% for c in web_ui_options["spot-count"] %}
|
||||||
|
<option value="{{c}}" {% if web_ui_options["spot-count-default"] == c %}selected{% end %}>{{c}}</option>
|
||||||
|
{% end %}
|
||||||
|
</select>
|
||||||
|
spots
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
6
templates/cards/sigs.html
Normal file
6
templates/cards/sigs.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">SIGs</h5>
|
||||||
|
<p id="sig-options" class="card-text spothole-card-text"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
6
templates/cards/sources.html
Normal file
6
templates/cards/sources.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Sources</h5>
|
||||||
|
<p id="source-options" class="card-text spothole-card-text"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
13
templates/cards/spot-age.html
Normal file
13
templates/cards/spot-age.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Spot Age</h5>
|
||||||
|
<p class="card-text spothole-card-text">Last
|
||||||
|
<select id="max-spot-age" class="storeable-select form-select ms-2 me-2 d-inline-block" oninput="filtersUpdated();" style="width: 5em; display: inline-block;">
|
||||||
|
{% for a in web_ui_options["max-spot-age"] %}
|
||||||
|
<option value="{{a*60}}" {% if web_ui_options["max-spot-age-default"] == a*60 %}selected{% end %}>{{a}}</option>
|
||||||
|
{% end %}
|
||||||
|
</select>
|
||||||
|
minutes
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
35
templates/cards/table-columns-alerts.html
Normal file
35
templates/cards/table-columns-alerts.html
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Table Columns</h5>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowStartTime" value="tableShowStartTime" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowStartTime">Start Time</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowEndTime" value="tableShowEndTime" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowEndTime">End Time</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowDX" value="tableShowDX" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowDX">DX</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowFreqsModes" value="tableShowFreqsModes" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowFreqsModes">Frequencies & Modes</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowComment" value="tableShowComment" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowComment">Comment</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowSource" value="tableShowSource" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowSource">Source</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowRef" value="tableShowRef" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowRef">Ref.</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
47
templates/cards/table-columns-spots.html
Normal file
47
templates/cards/table-columns-spots.html
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Table Columns</h5>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowTime" value="tableShowTime" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowTime">Time</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowDX" value="tableShowDX" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowDX">DX</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowFreq" value="tableShowFreq" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowFreq">Frequency</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowMode" value="tableShowMode" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowMode">Mode</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowComment" value="tableShowComment" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowComment">Comment</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowBearing" value="tableShowBearing" oninput="columnsUpdated();">
|
||||||
|
<label class="form-check-label" for="tableShowBearing">Bearing</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowType" value="tableShowType" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowType">Type</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowRef" value="tableShowRef" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowRef">Ref.</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowDE" value="tableShowDE" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowDE">DE</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowWorkedCheckbox" value="tableShowWorkedCheckbox" oninput="columnsUpdated();" checked>
|
||||||
|
<label class="form-check-label" for="tableShowWorkedCheckbox">Worked?</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
11
templates/cards/time-zone.html
Normal file
11
templates/cards/time-zone.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Time Zone</h5>
|
||||||
|
<p class="card-text spothole-card-text"> Use
|
||||||
|
<select id="timeZone" class="storeable-select form-select ms-2 me-2 d-inline-block" oninput="timeZoneUpdated();" style="width: 8em; display: inline-block;">
|
||||||
|
<option value="UTC" selected>UTC</option>
|
||||||
|
<option value="local">Local time</option>
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
6
templates/cards/worked-calls.html
Normal file
6
templates/cards/worked-calls.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Worked Calls</h5>
|
||||||
|
<button type="button" class="btn btn-primary" onClick="clearWorked();">Clear worked calls</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -3,142 +3,55 @@
|
|||||||
|
|
||||||
<div id="map">
|
<div id="map">
|
||||||
<div id="settingsButtonRowMap" class="mt-3 px-3" style="z-index: 1002; position: relative;">
|
<div id="settingsButtonRowMap" class="mt-3 px-3" style="z-index: 1002; position: relative;">
|
||||||
<div class="row">
|
<div class="row mb-3">
|
||||||
<div class="col-auto me-auto pt-3"></div>
|
<div class="col-auto me-auto pt-3"></div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<p class="d-inline-flex gap-1">
|
<div class="d-inline-flex gap-1">
|
||||||
<button id="filters-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button" onclick="toggleFiltersPanel();"><i class="fa-solid fa-filter"></i> Filters</button>
|
{% module Template("widgets/filters-display-buttons.html", web_ui_options=web_ui_options) %}
|
||||||
<button id="display-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button" onclick="toggleDisplayPanel();"><i class="fa-solid fa-desktop"></i> Display</button>
|
</div>
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="filters-area" class="appearing-panel card mb-3">
|
<div id="filters-area" class="appearing-panel card mb-3">
|
||||||
<div class="card-header text-white bg-primary">
|
{% module Template("widgets/filters-area-header.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="row">
|
|
||||||
<div class="col-auto me-auto">
|
|
||||||
Filters
|
|
||||||
</div>
|
|
||||||
<div class="col-auto d-inline-flex">
|
|
||||||
<button id="close-filters-button" type="button" class="btn-close btn-close-white" aria-label="Close" onclick="closeFiltersPanel();"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row row-cols-1 g-4 mb-4 row-cols-md-3">
|
<div class="row row-cols-1 g-4 mb-4 row-cols-md-3">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/bands.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Bands</h5>
|
|
||||||
<p id="band-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/sigs.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">SIGs</h5>
|
|
||||||
<p id="sig-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/sources.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Sources</h5>
|
|
||||||
<p id="source-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row row-cols-1 row-cols-md-3 g-4">
|
<div class="row row-cols-1 row-cols-md-3 g-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/dx-continent.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">DX Continent</h5>
|
|
||||||
<p id="dx-continent-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/de-continent.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">DE Continent</h5>
|
|
||||||
<p id="de-continent-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/modes.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Modes</h5>
|
|
||||||
<p id="mode-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="display-area" class="appearing-panel card mb-3">
|
<div id="display-area" class="appearing-panel card mb-3">
|
||||||
<div class="card-header text-white bg-primary">
|
{% module Template("widgets/display-area-header.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="row">
|
|
||||||
<div class="col-auto me-auto">
|
|
||||||
Display
|
|
||||||
</div>
|
|
||||||
<div class="col-auto d-inline-flex">
|
|
||||||
<button id="close-display-button" type="button" class="btn-close btn-close-white" aria-label="Close" onclick="closeDisplayPanel();"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div id="display-container" class="row row-cols-1 row-cols-md-4 g-4">
|
<div id="display-container" class="row row-cols-1 row-cols-md-4 g-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/spot-age.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Spot Age</h5>
|
|
||||||
<p class="card-text spothole-card-text">Last
|
|
||||||
<select id="max-spot-age" class="storeable-select form-select ms-2 me-2 d-inline-block" oninput="filtersUpdated();" style="width: 5em; display: inline-block;">
|
|
||||||
</select>
|
|
||||||
minutes
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/map-features.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Map Features</h5>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="mapShowGeodesics" value="mapShowGeodesics" oninput="displayUpdated();">
|
|
||||||
<label class="form-check-label" for="mapShowGeodesics">Geodesic Lines</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/color-scheme-and-band-color-scheme.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Theme</h5>
|
|
||||||
<p class="card-text spothole-card-text">
|
|
||||||
<label class="form-check-label" for="color-scheme">UI color scheme</label>
|
|
||||||
<select id="color-scheme" class="storeable-select form-select d-inline-block" oninput="setColorSchemeFromUI();" style="display: inline-block;">
|
|
||||||
<option value="auto">Automatic</option>
|
|
||||||
<option value="light">Light</option>
|
|
||||||
<option value="dark">Dark</option>
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
<p class="card-text spothole-card-text">
|
|
||||||
<label class="form-check-label" for="band-color-scheme">Band color scheme</label><br/>
|
|
||||||
<select id="band-color-scheme" class="storeable-select form-select d-inline-block" oninput="setBandColorSchemeFromUI();" style="display: inline-block;">
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -154,9 +67,12 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/leaflet.geodesic"></script>
|
<script src="https://cdn.jsdelivr.net/npm/leaflet.geodesic"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@joergdietrich/leaflet.terminator@1.1.0/L.Terminator.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@joergdietrich/leaflet.terminator@1.1.0/L.Terminator.min.js"></script>
|
||||||
|
|
||||||
<script src="/js/common.js?v=7"></script>
|
<script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=7"></script>
|
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
||||||
<script src="/js/map.js?v=7"></script>
|
</script>
|
||||||
|
<script src="/js/common.js?v=8"></script>
|
||||||
|
<script src="/js/spotsbandsandmap.js?v=8"></script>
|
||||||
|
<script src="/js/map.js?v=8"></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 %}
|
||||||
@@ -9,212 +9,70 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<div id="settingsButtonRow" class="row">
|
<div id="settingsButtonRow" class="row mb-3">
|
||||||
<div class="col-4">
|
<div class="col-md-4 mb-3 mb-md-0">
|
||||||
<p class="d-inline-flex gap-1">
|
<div class="d-inline-flex gap-3">
|
||||||
<span class="btn-group" role="group">
|
{% module Template("widgets/run-pause.html", web_ui_options=web_ui_options) %}
|
||||||
<input type="radio" class="btn-check" name="runPause" id="runButton" autocomplete="off" checked>
|
<div class="d-inline-flex">{% raw web_ui_options["support-button-html"] %}</div>
|
||||||
<label class="btn btn-outline-primary" for="runButton"><i class="fa-solid fa-play"></i><span class="hideonmobile"> Run</span></label>
|
</div>
|
||||||
|
|
||||||
<input type="radio" class="btn-check" name="runPause" id="pauseButton" autocomplete="off">
|
|
||||||
<label class="btn btn-outline-primary" for="pauseButton"><i class="fa-solid fa-pause"></i><span class="hideonmobile"> Pause</span></label>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-8 text-end">
|
<div class="col-md-8 text-end">
|
||||||
<p class="d-inline-flex gap-1">
|
<div class="d-inline-flex gap-3">
|
||||||
<span style="position: relative;">
|
{% module Template("widgets/search.html", web_ui_options=web_ui_options) %}
|
||||||
<i id="searchicon" class="fa-solid fa-magnifying-glass"></i>
|
{% module Template("widgets/filters-display-buttons.html", web_ui_options=web_ui_options) %}
|
||||||
<input id="search" type="search" class="form-control" oninput="filtersUpdated();" placeholder="Search">
|
</div>
|
||||||
</span>
|
|
||||||
<button id="filters-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button" onclick="toggleFiltersPanel();"><i class="fa-solid fa-filter"></i><span class="hideonmobile"> Filters</span></button>
|
|
||||||
<button id="display-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button" onclick="toggleDisplayPanel();"><i class="fa-solid fa-desktop"></i><span class="hideonmobile"> Display</span></button>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="filters-area" class="appearing-panel card mb-3">
|
<div id="filters-area" class="appearing-panel card mb-3">
|
||||||
<div class="card-header text-white bg-primary">
|
{% module Template("widgets/filters-area-header.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="row">
|
|
||||||
<div class="col-auto me-auto">
|
|
||||||
Filters
|
|
||||||
</div>
|
|
||||||
<div class="col-auto d-inline-flex">
|
|
||||||
<button id="close-filters-button" type="button" class="btn-close btn-close-white" aria-label="Close" onclick="closeFiltersPanel();"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row row-cols-1 g-4 mb-4 row-cols-md-3">
|
<div class="row row-cols-1 g-4 mb-4 row-cols-md-3">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/bands.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Bands</h5>
|
|
||||||
<p id="band-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/sigs.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">SIGs</h5>
|
|
||||||
<p id="sig-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/sources.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Sources</h5>
|
|
||||||
<p id="source-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row row-cols-1 row-cols-md-3 g-4">
|
<div class="row row-cols-1 row-cols-md-3 g-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/dx-continent.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">DX Continent</h5>
|
|
||||||
<p id="dx-continent-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/de-continent.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">DE Continent</h5>
|
|
||||||
<p id="de-continent-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/modes.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Modes</h5>
|
|
||||||
<p id="mode-options" class="card-text spothole-card-text"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="display-area" class="appearing-panel card mb-3">
|
<div id="display-area" class="appearing-panel card mb-3">
|
||||||
<div class="card-header text-white bg-primary">
|
{% module Template("widgets/display-area-header.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="row">
|
|
||||||
<div class="col-auto me-auto">
|
|
||||||
Display
|
|
||||||
</div>
|
|
||||||
<div class="col-auto d-inline-flex">
|
|
||||||
<button id="close-display-button" type="button" class="btn-close btn-close-white" aria-label="Close" onclick="closeDisplayPanel();"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div id="display-container" class="row row-cols-1 row-cols-md-4 g-4">
|
<div id="display-container" class="row row-cols-1 row-cols-md-4 g-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/time-zone.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Time Zone</h5>
|
|
||||||
<p class="card-text spothole-card-text"> Use
|
|
||||||
<select id="timeZone" class="storeable-select form-select ms-2 me-2 d-inline-block" oninput="timeZoneUpdated();" style="width: 8em; display: inline-block;">
|
|
||||||
<option value="UTC" selected>UTC</option>
|
|
||||||
<option value="local">Local time</option>
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/number-of-spots.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Number of Spots</h5>
|
|
||||||
<p class="card-text spothole-card-text">Show up to
|
|
||||||
<select id="spots-to-fetch" class="storeable-select form-select ms-2 me-2 d-inline-block" oninput="filtersUpdated();" style="width: 5em; display: inline-block;">
|
|
||||||
</select>
|
|
||||||
spots
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/location.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Location</h5>
|
|
||||||
<div class="form-group spothole-card-text">
|
|
||||||
<label for="userGrid">Your grid:</label>
|
|
||||||
<input type="text" class="storeable-text form-control" id="userGrid" placeholder="AA00aa" oninput="userGridUpdated();" style="width: 10em; display: inline-block;">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/worked-calls.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Theme</h5>
|
|
||||||
<p class="card-text spothole-card-text">
|
|
||||||
<label class="form-check-label" for="color-scheme">UI color scheme</label>
|
|
||||||
<select id="color-scheme" class="storeable-select form-select d-inline-block" oninput="setColorSchemeFromUI();" style="display: inline-block;">
|
|
||||||
<option value="auto">Automatic</option>
|
|
||||||
<option value="light">Light</option>
|
|
||||||
<option value="dark">Dark</option>
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
<p class="card-text spothole-card-text">
|
|
||||||
<label class="form-check-label" for="band-color-scheme">Band color scheme</label><br/>
|
|
||||||
<select id="band-color-scheme" class="storeable-select form-select d-inline-block" oninput="setBandColorSchemeFromUI();" style="display: inline-block;">
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
{% module Template("cards/color-scheme-and-band-color-scheme.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="card-body">
|
</div>
|
||||||
<h5 class="card-title">Table Columns</h5>
|
<div class="col">
|
||||||
<div class="form-group">
|
{% module Template("cards/table-columns-spots.html", web_ui_options=web_ui_options) %}
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowTime" value="tableShowTime" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowTime">Time</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowDX" value="tableShowDX" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowDX">DX</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowFreq" value="tableShowFreq" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowFreq">Frequency</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowMode" value="tableShowMode" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowMode">Mode</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowComment" value="tableShowComment" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowComment">Comment</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowBearing" value="tableShowBearing" oninput="columnsUpdated();">
|
|
||||||
<label class="form-check-label" for="tableShowBearing">Bearing</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowType" value="tableShowType" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowType">Type</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowRef" value="tableShowRef" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowRef">Ref.</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input class="form-check-input storeable-checkbox" type="checkbox" id="tableShowDE" value="tableShowDE" oninput="columnsUpdated();" checked>
|
|
||||||
<label class="form-check-label" for="tableShowDE">DE</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -226,9 +84,12 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/common.js?v=7"></script>
|
<script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=7"></script>
|
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
|
||||||
<script src="/js/spots.js?v=7"></script>
|
</script>
|
||||||
|
<script src="/js/common.js?v=8"></script>
|
||||||
|
<script src="/js/spotsbandsandmap.js?v=8"></script>
|
||||||
|
<script src="/js/spots.js?v=8"></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 %}
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
<div id="status-container" class="row row-cols-1 row-cols-md-4 g-4 mt-4"></div>
|
<div id="status-container" class="row row-cols-1 row-cols-md-4 g-4 mt-4"></div>
|
||||||
|
|
||||||
<script src="/js/common.js?v=7"></script>
|
<script src="/js/common.js?v=8"></script>
|
||||||
<script src="/js/status.js?v=7"></script>
|
<script src="/js/status.js?v=8"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-status").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-status").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
13
templates/widgets/band-color-scheme.html
Normal file
13
templates/widgets/band-color-scheme.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<label class="form-check-label" for="band-color-scheme">Band color scheme</label><br/>
|
||||||
|
<select id="band-color-scheme" class="storeable-select form-select d-inline-block" oninput="setBandColorSchemeFromUI();" style="display: inline-block;">
|
||||||
|
<option value="PSK Reporter" {% if web_ui_options["band-color-scheme-default"] == "PSK Reporter" %}selected{% end %}>PSK Reporter</option>
|
||||||
|
<option value="PSK Reporter (Adjusted)" {% if web_ui_options["band-color-scheme-default"] == "PSK Reporter (Adjusted)" %}selected{% end %}>PSK Reporter (Adjusted)</option>
|
||||||
|
<option value="RBN" {% if web_ui_options["band-color-scheme-default"] == "RBN" %}selected{% end %}>RBN</option>
|
||||||
|
<option value="Ham Rainbow" {% if web_ui_options["band-color-scheme-default"] == "Ham Rainbow" %}selected{% end %}>Ham Rainbow</option>
|
||||||
|
<option value="Ham Rainbow (Reverse)" {% if web_ui_options["band-color-scheme-default"] == "Ham Rainbow (Reverse)" %}selected{% end %}>Ham Rainbow (Reverse)</option>
|
||||||
|
<option value="Kate Morley" {% if web_ui_options["band-color-scheme-default"] == "Kate Morley" %}selected{% end %}>Kate Morley</option>
|
||||||
|
<option value="ColorBrewer" {% if web_ui_options["band-color-scheme-default"] == "ColorBrewer" %}selected{% end %}>ColorBrewer</option>
|
||||||
|
<option value="IWantHue" {% if web_ui_options["band-color-scheme-default"] == "IWantHue" %}selected{% end %}>IWantHue</option>
|
||||||
|
<option value="IWantHue (Color Blind)" {% if web_ui_options["band-color-scheme-default"] == "IWantHue (Color Blind)" %}selected{% end %}>IWantHue (Color Blind)</option>
|
||||||
|
<option value="Mokole" {% if web_ui_options["band-color-scheme-default"] == "Mokole" %}selected{% end %}>Mokole</option>
|
||||||
|
</select>
|
||||||
6
templates/widgets/color-scheme.html
Normal file
6
templates/widgets/color-scheme.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<label class="form-check-label" for="color-scheme">UI color scheme</label>
|
||||||
|
<select id="color-scheme" class="storeable-select form-select d-inline-block" oninput="setColorSchemeFromUI();" style="display: inline-block;">
|
||||||
|
<option value="auto" {% if web_ui_options["color-scheme-default"] == "auto" %}selected{% end %}>Automatic</option>
|
||||||
|
<option value="light" {% if web_ui_options["color-scheme-default"] == "light" %}selected{% end %}>Light</option>
|
||||||
|
<option value="dark" {% if web_ui_options["color-scheme-default"] == "dark" %}selected{% end %}>Dark</option>
|
||||||
|
</select>
|
||||||
10
templates/widgets/display-area-header.html
Normal file
10
templates/widgets/display-area-header.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<div class="card-header text-white bg-primary">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-auto me-auto">
|
||||||
|
Display
|
||||||
|
</div>
|
||||||
|
<div class="col-auto d-inline-flex">
|
||||||
|
<button id="close-display-button" type="button" class="btn-close btn-close-white" aria-label="Close" onclick="closeDisplayPanel();"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
10
templates/widgets/filters-area-header.html
Normal file
10
templates/widgets/filters-area-header.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<div class="card-header text-white bg-primary">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-auto me-auto">
|
||||||
|
Filters
|
||||||
|
</div>
|
||||||
|
<div class="col-auto d-inline-flex">
|
||||||
|
<button id="close-filters-button" type="button" class="btn-close btn-close-white" aria-label="Close" onclick="closeFiltersPanel();"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
4
templates/widgets/filters-display-buttons.html
Normal file
4
templates/widgets/filters-display-buttons.html
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<div class="d-inline-flex gap-1">
|
||||||
|
<button id="filters-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button" onclick="toggleFiltersPanel();"><i class="fa-solid fa-filter"></i> Filters</button>
|
||||||
|
<button id="display-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button" onclick="toggleDisplayPanel();"><i class="fa-solid fa-desktop"></i> Display</button>
|
||||||
|
</div>
|
||||||
1
templates/widgets/refresh-timer.html
Normal file
1
templates/widgets/refresh-timer.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<div id="timing-container">Loading...</div>
|
||||||
7
templates/widgets/run-pause.html
Normal file
7
templates/widgets/run-pause.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<span class="btn-group" role="group">
|
||||||
|
<input type="radio" class="btn-check" name="runPause" id="runButton" autocomplete="off" checked>
|
||||||
|
<label class="btn btn-outline-primary" for="runButton"><i class="fa-solid fa-play"></i> Run</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" name="runPause" id="pauseButton" autocomplete="off">
|
||||||
|
<label class="btn btn-outline-primary" for="pauseButton"><i class="fa-solid fa-pause"></i> Pause</label>
|
||||||
|
</span>
|
||||||
4
templates/widgets/search.html
Normal file
4
templates/widgets/search.html
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<span style="position: relative;">
|
||||||
|
<i id="searchicon" class="fa-solid fa-magnifying-glass"></i>
|
||||||
|
<input id="search" type="search" class="form-control" oninput="filtersUpdated();" placeholder="Search">
|
||||||
|
</span>
|
||||||
@@ -483,7 +483,7 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- General
|
- General
|
||||||
summary: Get enumeration options
|
summary: Get enumeration options
|
||||||
description: Retrieves the list of options for various enumerated types, which can be found in the spots and also provided back to the API as query parameters. While these enumerated options are defined in this spec anyway, providing them in an API call allows us to define extra parameters, like the colours associated with bands, and also allows clients to set up their filters and features without having to have internal knowledge about, for example, what bands the server knows about. The call also returns a variety of other parameters that may be of use to a web UI, including the contents of the "web-ui-options" config section, which provides guidance for web UI implementations such as the built-in one on sensible configuration options such as the number of spots/alerts to retrieve, or the maximum age of spots to retrieve.
|
description: Retrieves the list of options for various enumerated types, which can be found in the spots and also provided back to the API as query parameters. While these enumerated options are defined in this spec anyway, providing them in an API call allows us to define extra parameters, like the colours associated with bands, and also allows clients to set up their filters and features without having to have internal knowledge about, for example, what bands the server knows about. The call also returns a variety of other parameters that may be of use to a web UI or other client.
|
||||||
operationId: options
|
operationId: options
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
@@ -535,46 +535,6 @@ paths:
|
|||||||
type: boolean
|
type: boolean
|
||||||
description: Whether the POST /spot call, to add spots to the server directly via its API, is permitted on this server.
|
description: Whether the POST /spot call, to add spots to the server directly via its API, is permitted on this server.
|
||||||
example: true
|
example: true
|
||||||
web-ui-options:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
spot-count:
|
|
||||||
type: array
|
|
||||||
description: An array of suggested "spot counts" that the web UI can retrieve from the API
|
|
||||||
items:
|
|
||||||
type: integer
|
|
||||||
example: 50
|
|
||||||
spot-count-default:
|
|
||||||
type: integer
|
|
||||||
example: 50
|
|
||||||
description: The suggested default "spot count" that the web UI should retrieve from the API
|
|
||||||
max-spot-age:
|
|
||||||
type: array
|
|
||||||
description: An array of suggested "maximum spot ages" that the web UI can retrieve from the API
|
|
||||||
items:
|
|
||||||
type: integer
|
|
||||||
example: 30
|
|
||||||
max-spot-age-default:
|
|
||||||
type: integer
|
|
||||||
example: 30
|
|
||||||
description: The suggested default "maximum spot age" that the web UI should retrieve from the API
|
|
||||||
spot-providers-enabled-by-default:
|
|
||||||
type: array
|
|
||||||
description: A list of the spot providers that should be enabled in the web UI on first load, if the user hasn't already got a localStorage setting that sets their preference. This is to allow some high-volume providers like RBN to be enabled in Spothole's back-end and displayable in the web UI if the user wants, but by default the experience will not include them.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
example: "POTA"
|
|
||||||
alert-count:
|
|
||||||
type: array
|
|
||||||
description: An array of suggested "alert counts" that the web UI can retrieve from the API
|
|
||||||
items:
|
|
||||||
type: integer
|
|
||||||
example: 100
|
|
||||||
alert-count-default:
|
|
||||||
type: integer
|
|
||||||
example: 100
|
|
||||||
description: The suggested default "alert count" that the web UI should retrieve from the API
|
|
||||||
|
|
||||||
|
|
||||||
/lookup/call:
|
/lookup/call:
|
||||||
get:
|
get:
|
||||||
|
|||||||
@@ -82,14 +82,12 @@ div.container {
|
|||||||
|
|
||||||
input#search {
|
input#search {
|
||||||
max-width: 12em;
|
max-width: 12em;
|
||||||
margin-left: 1rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
padding-left: 2em;
|
padding-left: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
i#searchicon {
|
i#searchicon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 1rem;
|
left: 0rem;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|||||||
@@ -285,13 +285,6 @@ function loadOptions() {
|
|||||||
generateMultiToggleFilterCard("#dx-continent-options", "dx_continent", options["continents"]);
|
generateMultiToggleFilterCard("#dx-continent-options", "dx_continent", options["continents"]);
|
||||||
generateMultiToggleFilterCard("#source-options", "source", options["alert_sources"]);
|
generateMultiToggleFilterCard("#source-options", "source", options["alert_sources"]);
|
||||||
|
|
||||||
// Populate the Display panel
|
|
||||||
web_ui_options["alert-count"].forEach(sc => $("#alerts-to-fetch").append($('<option>', {
|
|
||||||
value: sc,
|
|
||||||
text: sc
|
|
||||||
})));
|
|
||||||
$("#alerts-to-fetch").val(web_ui_options["alert-count-default"]);
|
|
||||||
|
|
||||||
// Load URL params. These may select things from the various filter & display options, so the function needs
|
// 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
|
// to be called after these are set up, but if the URL params ask for "embedded mode", this will suppress
|
||||||
// loading settings, so this needs to be called before that.
|
// loading settings, so this needs to be called before that.
|
||||||
@@ -299,6 +292,7 @@ function loadOptions() {
|
|||||||
|
|
||||||
// Load filters from settings storage
|
// Load filters from settings storage
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
setColorScheme($("#color-scheme option:selected").val());
|
||||||
|
|
||||||
// Load alerts and set up the timer
|
// Load alerts and set up the timer
|
||||||
loadAlerts();
|
loadAlerts();
|
||||||
|
|||||||
@@ -145,7 +145,8 @@ function updateBands() {
|
|||||||
|
|
||||||
// Now each spot is tagged with how far down the div it should go, add them to the DOM.
|
// Now each spot is tagged with how far down the div it should go, add them to the DOM.
|
||||||
spotList.forEach(s => {
|
spotList.forEach(s => {
|
||||||
bandSpotsDiv.append(`<div class="band-spot" style="top: ${s['pxDownBandLabel']}px; border-top: 1px solid ${bandToColor(s['band'])}; border-left: 5px solid ${bandToColor(s['band'])}; border-bottom: 1px solid ${bandToColor(s['band'])}; border-right: 1px solid ${bandToColor(s['band'])};"><span class="band-spot-call">${s.dx_call}${s.dx_ssid != null ? "-" + s.dx_ssid : ""}</span><span class="band-spot-info">${s.dx_call}${s.dx_ssid != null ? "-" + s.dx_ssid : ""} ${(s.freq/1000000).toFixed(3)} ${s.mode}</span></div>`);
|
let worked = alreadyWorked(s["dx_call"], s["band"], s["mode"]);
|
||||||
|
bandSpotsDiv.append(`<div class="band-spot" style="top: ${s['pxDownBandLabel']}px; border-top: 1px solid ${bandToColor(s['band'])}; border-left: 5px solid ${bandToColor(s['band'])}; border-bottom: 1px solid ${bandToColor(s['band'])}; border-right: 1px solid ${bandToColor(s['band'])}; text-decoration: ${worked ? 'line-through' : 'none'};"><span class="band-spot-call">${s.dx_call}${s.dx_ssid != null ? "-" + s.dx_ssid : ""}</span><span class="band-spot-info">${s.dx_call}${s.dx_ssid != null ? "-" + s.dx_ssid : ""} ${(s.freq/1000000).toFixed(3)} ${s.mode}</span></div>`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Work out how tall the canvas should be. Normally this is matching the normal band column height, but if some
|
// Work out how tall the canvas should be. Normally this is matching the normal band column height, but if some
|
||||||
@@ -228,20 +229,9 @@ function loadOptions() {
|
|||||||
// Store options
|
// Store options
|
||||||
options = jsonData;
|
options = jsonData;
|
||||||
|
|
||||||
// Populate the Display panel
|
|
||||||
web_ui_options["max-spot-age"].forEach(sc => $("#max-spot-age").append($('<option>', {
|
|
||||||
value: sc * 60,
|
|
||||||
text: sc
|
|
||||||
})));
|
|
||||||
$("#max-spot-age").val(web_ui_options["max-spot-age-default"] * 60);
|
|
||||||
getAvailableBandColorSchemes().forEach(sc => $("#band-color-scheme").append($('<option>', {
|
|
||||||
value: sc,
|
|
||||||
text: sc
|
|
||||||
})));
|
|
||||||
$("#band-color-scheme").val(web_ui_options["default-band-color-scheme"]);
|
|
||||||
|
|
||||||
// First pass loading settings, so we can load the band colour scheme before the filters that need to use it
|
// First pass loading settings, so we can load the band colour scheme before the filters that need to use it
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
setColorScheme($("#color-scheme option:selected").val());
|
||||||
setBandColorScheme($("#band-color-scheme option:selected").val());
|
setBandColorScheme($("#band-color-scheme option:selected").val());
|
||||||
|
|
||||||
// Add CSS for band toggle buttons
|
// Add CSS for band toggle buttons
|
||||||
@@ -253,7 +243,7 @@ function loadOptions() {
|
|||||||
generateMultiToggleFilterCard("#dx-continent-options", "dx_continent", options["continents"]);
|
generateMultiToggleFilterCard("#dx-continent-options", "dx_continent", options["continents"]);
|
||||||
generateMultiToggleFilterCard("#de-continent-options", "de_continent", options["continents"]);
|
generateMultiToggleFilterCard("#de-continent-options", "de_continent", options["continents"]);
|
||||||
generateModesMultiToggleFilterCard(options["modes"]);
|
generateModesMultiToggleFilterCard(options["modes"]);
|
||||||
generateSourcesMultiToggleFilterCard(options["spot_sources"], web_ui_options["spot-providers-enabled-by-default"]);
|
generateSourcesMultiToggleFilterCard(options["spot_sources"], spotProvidersEnabledByDefault);
|
||||||
|
|
||||||
// Load URL params. These may select things from the various filter & display options, so the function needs
|
// 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
|
// to be called after these are set up, but if the URL params ask for "embedded mode", this will suppress
|
||||||
|
|||||||
@@ -144,8 +144,11 @@ function columnsUpdated() {
|
|||||||
|
|
||||||
// Function to set the colour scheme based on the state of the UI select box
|
// Function to set the colour scheme based on the state of the UI select box
|
||||||
function setColorSchemeFromUI() {
|
function setColorSchemeFromUI() {
|
||||||
setColorScheme($("#color-scheme option:selected").val());
|
let theme = $("#color-scheme option:selected").val();
|
||||||
saveSettings();
|
if (theme != "") {
|
||||||
|
setColorScheme(theme);
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to set the color scheme. Supported values: "dark", "light", "auto"
|
// Function to set the color scheme. Supported values: "dark", "light", "auto"
|
||||||
@@ -163,16 +166,12 @@ function setColorScheme(mode) {
|
|||||||
|
|
||||||
// Startup function to determine whether to use light or dark mode, or leave as auto
|
// Startup function to determine whether to use light or dark mode, or leave as auto
|
||||||
function usePreferredTheme() {
|
function usePreferredTheme() {
|
||||||
// Set the value of the select box to the server's default
|
|
||||||
$("#color-scheme").val(web_ui_options["default-color-scheme"]);
|
|
||||||
|
|
||||||
// Work out if we have ever explicitly saved the value of our select box. If so, we set our colour scheme now based
|
// Work out if we have ever explicitly saved the value of our select box. If so, we set our colour scheme now based
|
||||||
// on that. If not, we let the select retain its default value from Spothole config and apply that.
|
// on that. If not, we let the select stay with nothing selected, so that the server sets it to whatever the
|
||||||
|
// server's default is when the options call is retrieved.
|
||||||
let val = localStorage.getItem("#color-scheme:value");
|
let val = localStorage.getItem("#color-scheme:value");
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
setColorScheme(JSON.parse(val));
|
setColorScheme(JSON.parse(val));
|
||||||
} else {
|
|
||||||
setColorSchemeFromUI();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -160,20 +160,9 @@ function loadOptions() {
|
|||||||
// Store options
|
// Store options
|
||||||
options = jsonData;
|
options = jsonData;
|
||||||
|
|
||||||
// Populate the Display panel
|
|
||||||
web_ui_options["max-spot-age"].forEach(sc => $("#max-spot-age").append($('<option>', {
|
|
||||||
value: sc * 60,
|
|
||||||
text: sc
|
|
||||||
})));
|
|
||||||
$("#max-spot-age").val(web_ui_options["max-spot-age-default"] * 60);
|
|
||||||
getAvailableBandColorSchemes().forEach(sc => $("#band-color-scheme").append($('<option>', {
|
|
||||||
value: sc,
|
|
||||||
text: sc
|
|
||||||
})));
|
|
||||||
$("#band-color-scheme").val(web_ui_options["default-band-color-scheme"]);
|
|
||||||
|
|
||||||
// First pass loading settings, so we can load the band colour scheme before the filters that need to use it
|
// First pass loading settings, so we can load the band colour scheme before the filters that need to use it
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
setColorScheme($("#color-scheme option:selected").val());
|
||||||
setBandColorScheme($("#band-color-scheme option:selected").val());
|
setBandColorScheme($("#band-color-scheme option:selected").val());
|
||||||
|
|
||||||
// Add CSS for band toggle buttons
|
// Add CSS for band toggle buttons
|
||||||
@@ -185,7 +174,7 @@ function loadOptions() {
|
|||||||
generateMultiToggleFilterCard("#dx-continent-options", "dx_continent", options["continents"]);
|
generateMultiToggleFilterCard("#dx-continent-options", "dx_continent", options["continents"]);
|
||||||
generateMultiToggleFilterCard("#de-continent-options", "de_continent", options["continents"]);
|
generateMultiToggleFilterCard("#de-continent-options", "de_continent", options["continents"]);
|
||||||
generateModesMultiToggleFilterCard(options["modes"]);
|
generateModesMultiToggleFilterCard(options["modes"]);
|
||||||
generateSourcesMultiToggleFilterCard(options["spot_sources"], web_ui_options["spot-providers-enabled-by-default"]);
|
generateSourcesMultiToggleFilterCard(options["spot_sources"], spotProvidersEnabledByDefault);
|
||||||
|
|
||||||
// Load URL params. These may select things from the various filter & display options, so the function needs
|
// 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
|
// to be called after these are set up, but if the URL params ask for "embedded mode", this will suppress
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ function updateTable() {
|
|||||||
var showType = $("#tableShowType")[0].checked;
|
var showType = $("#tableShowType")[0].checked;
|
||||||
var showRef = $("#tableShowRef")[0].checked;
|
var showRef = $("#tableShowRef")[0].checked;
|
||||||
var showDE = $("#tableShowDE")[0].checked;
|
var showDE = $("#tableShowDE")[0].checked;
|
||||||
|
var showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked;
|
||||||
|
|
||||||
// Populate table with headers
|
// Populate table with headers
|
||||||
let table = $("#table");
|
let table = $("#table");
|
||||||
@@ -136,12 +137,18 @@ function updateTable() {
|
|||||||
if (showDE) {
|
if (showDE) {
|
||||||
table.find('thead tr').append(`<th class='hideonmobile'>DE</th>`);
|
table.find('thead tr').append(`<th class='hideonmobile'>DE</th>`);
|
||||||
}
|
}
|
||||||
|
if (showWorkedCheckbox) {
|
||||||
|
table.find('thead tr').append(`<th class='hideonmobile'></th>`);
|
||||||
|
}
|
||||||
|
|
||||||
table.find('tbody').empty();
|
table.find('tbody').empty();
|
||||||
if (spots.length == 0) {
|
if (spots.length == 0) {
|
||||||
table.find('tbody').append('<tr class="table-danger"><td colspan="100" style="text-align:center;">No spots match your filters.</td></tr>');
|
table.find('tbody').append('<tr class="table-danger"><td colspan="100" style="text-align:center;">No spots match your filters.</td></tr>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We are regenerating the entire table not just adding a new row, so reset the row counter
|
||||||
|
rowCount = 0;
|
||||||
|
|
||||||
let spotsNewestFirst = spots.toReversed();
|
let spotsNewestFirst = spots.toReversed();
|
||||||
spotsNewestFirst.forEach(s => addSpotToTopOfTable(s, false));
|
spotsNewestFirst.forEach(s => addSpotToTopOfTable(s, false));
|
||||||
}
|
}
|
||||||
@@ -174,6 +181,7 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
var showType = $("#tableShowType")[0].checked;
|
var showType = $("#tableShowType")[0].checked;
|
||||||
var showRef = $("#tableShowRef")[0].checked;
|
var showRef = $("#tableShowRef")[0].checked;
|
||||||
var showDE = $("#tableShowDE")[0].checked;
|
var showDE = $("#tableShowDE")[0].checked;
|
||||||
|
var showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked;
|
||||||
|
|
||||||
// Create row
|
// Create row
|
||||||
let $tr = $('<tr>');
|
let $tr = $('<tr>');
|
||||||
@@ -185,8 +193,9 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
$tr.addClass("table-active");
|
$tr.addClass("table-active");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show faded out if QRT
|
// Show faded out if QRT or already worked
|
||||||
if (s["qrt"] == true) {
|
let alreadyWorkedThis = alreadyWorked(s["dx_call"], s["band"], s["mode"]);
|
||||||
|
if (s["qrt"] == true || alreadyWorkedThis) {
|
||||||
$tr.addClass("table-faded");
|
$tr.addClass("table-faded");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,6 +317,9 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
// Format band name
|
// Format band name
|
||||||
var bandFullName = s['band'] ? s['band'] + " band": "Unknown band";
|
var bandFullName = s['band'] ? s['band'] + " band": "Unknown band";
|
||||||
|
|
||||||
|
// Format "worked" checkbox
|
||||||
|
var workedCheckbox = `<input type="checkbox" ${alreadyWorkedThis ? "checked" : ""} onClick="setWorkedState('${s['dx_call']}', '${s['band']}', '${s['mode']}', ${alreadyWorkedThis ? "false" : "true"});" title="Check this box to record that you have worked this callsign on their current band and mode.">`;
|
||||||
|
|
||||||
// Populate the row
|
// Populate the row
|
||||||
if (showTime) {
|
if (showTime) {
|
||||||
$tr.append(`<td class='nowrap'>${time_formatted}</td>`);
|
$tr.append(`<td class='nowrap'>${time_formatted}</td>`);
|
||||||
@@ -336,6 +348,9 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
if (showDE) {
|
if (showDE) {
|
||||||
$tr.append(`<td class='nowrap hideonmobile'><span class='flag-wrapper' title='${de_country}'>${de_flag}</span>${de_call}</td>`);
|
$tr.append(`<td class='nowrap hideonmobile'><span class='flag-wrapper' title='${de_country}'>${de_flag}</span>${de_call}</td>`);
|
||||||
}
|
}
|
||||||
|
if (showWorkedCheckbox) {
|
||||||
|
$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 type, ref & comment
|
||||||
$tr2 = $("<tr class='hidenotonmobile'>");
|
$tr2 = $("<tr class='hidenotonmobile'>");
|
||||||
@@ -344,7 +359,7 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
if (rowCount % 2 == 1) {
|
if (rowCount % 2 == 1) {
|
||||||
$tr2.addClass("table-active");
|
$tr2.addClass("table-active");
|
||||||
}
|
}
|
||||||
if (s["qrt"] == true) {
|
if (s["qrt"] == true || alreadyWorkedThis) {
|
||||||
$tr2.addClass("table-faded");
|
$tr2.addClass("table-faded");
|
||||||
}
|
}
|
||||||
if (highlightNew) {
|
if (highlightNew) {
|
||||||
@@ -367,6 +382,9 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
if (showDE) {
|
if (showDE) {
|
||||||
$td2floatright.append(` de ${de_call} `);
|
$td2floatright.append(` de ${de_call} `);
|
||||||
}
|
}
|
||||||
|
if (showWorkedCheckbox) {
|
||||||
|
$td2floatright.append(` ${workedCheckbox} `);
|
||||||
|
}
|
||||||
$td2.append($td2floatright);
|
$td2.append($td2floatright);
|
||||||
$td2.append(`</div><div style="clear: both;"></div>`);
|
$td2.append(`</div><div style="clear: both;"></div>`);
|
||||||
if (showComment) {
|
if (showComment) {
|
||||||
@@ -386,21 +404,9 @@ function loadOptions() {
|
|||||||
// Store options
|
// Store options
|
||||||
options = jsonData;
|
options = jsonData;
|
||||||
|
|
||||||
// Populate the Display panel
|
|
||||||
web_ui_options["spot-count"].forEach(sc => $("#spots-to-fetch").append($('<option>', {
|
|
||||||
value: sc,
|
|
||||||
text: sc,
|
|
||||||
selected: sc == web_ui_options["spot-count-default"] // todo remove this?
|
|
||||||
})));
|
|
||||||
$("#spots-to-fetch").val(web_ui_options["spot-count-default"]); // todo setting val doesn't update UI?
|
|
||||||
getAvailableBandColorSchemes().forEach(sc => $("#band-color-scheme").append($('<option>', {
|
|
||||||
value: sc,
|
|
||||||
text: sc
|
|
||||||
})));
|
|
||||||
$("#band-color-scheme").val(web_ui_options["default-band-color-scheme"]);
|
|
||||||
|
|
||||||
// First pass loading settings, so we can load the band colour scheme before the filters that need to use it
|
// First pass loading settings, so we can load the band colour scheme before the filters that need to use it
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
setColorScheme($("#color-scheme option:selected").val());
|
||||||
setBandColorScheme($("#band-color-scheme option:selected").val());
|
setBandColorScheme($("#band-color-scheme option:selected").val());
|
||||||
|
|
||||||
// Add CSS for band toggle buttons
|
// Add CSS for band toggle buttons
|
||||||
@@ -412,7 +418,7 @@ function loadOptions() {
|
|||||||
generateMultiToggleFilterCard("#dx-continent-options", "dx_continent", options["continents"]);
|
generateMultiToggleFilterCard("#dx-continent-options", "dx_continent", options["continents"]);
|
||||||
generateMultiToggleFilterCard("#de-continent-options", "de_continent", options["continents"]);
|
generateMultiToggleFilterCard("#de-continent-options", "de_continent", options["continents"]);
|
||||||
generateModesMultiToggleFilterCard(options["modes"]);
|
generateModesMultiToggleFilterCard(options["modes"]);
|
||||||
generateSourcesMultiToggleFilterCard(options["spot_sources"], web_ui_options["spot-providers-enabled-by-default"]);
|
generateSourcesMultiToggleFilterCard(options["spot_sources"], spotProvidersEnabledByDefault);
|
||||||
|
|
||||||
// Load URL params. These may select things from the various filter & display options, so the function needs
|
// 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
|
// to be called after these are set up, but if the URL params ask for "embedded mode", this will suppress
|
||||||
@@ -493,6 +499,27 @@ function displayIntroBox() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark a callsign-band-mode combination as worked (or unmark it). Persist this to localStorage.
|
||||||
|
function setWorkedState(callsign, band, mode, nowWorked) {
|
||||||
|
let combo = callsign + "-" + band + "-" + mode;
|
||||||
|
if (nowWorked && !worked.includes(combo)) {
|
||||||
|
worked.push(combo);
|
||||||
|
updateTable();
|
||||||
|
localStorage.setItem("worked", JSON.stringify(worked));
|
||||||
|
} else if (!nowWorked && worked.includes(combo)) {
|
||||||
|
worked.splice(worked.indexOf(combo), 1);
|
||||||
|
updateTable();
|
||||||
|
localStorage.setItem("worked", JSON.stringify(worked));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the list of worked calls
|
||||||
|
function clearWorked() {
|
||||||
|
worked = [];
|
||||||
|
updateTable();
|
||||||
|
localStorage.setItem("worked", JSON.stringify(worked));
|
||||||
|
}
|
||||||
|
|
||||||
// Startup
|
// Startup
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Call loadOptions(), this will then trigger loading spots and setting up timers.
|
// Call loadOptions(), this will then trigger loading spots and setting up timers.
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
// Storage for the spot data that the server gives us.
|
// Storage for the spot data that the server gives us.
|
||||||
var spots = []
|
var spots = []
|
||||||
|
// List of people the user has worked. Each entry has the format callsign-band-mode. These can be added to the list by
|
||||||
|
// ticking the checkbox on a row of the table, and cleared from the Display menu. Where a row would be added to the
|
||||||
|
// table and the callsign-band-mode is in this list, it is shown struck through as already worked. This is persisted
|
||||||
|
// to localStorage.
|
||||||
|
let worked = []
|
||||||
|
|
||||||
// Dynamically add CSS code for the band toggle buttons to be in the appropriate colour.
|
// Dynamically add CSS code for the band toggle buttons to be in the appropriate colour.
|
||||||
// Some band names contain decimal points which are not allowed in CSS classes, so we text-replace them to "p".
|
// Some band names contain decimal points which are not allowed in CSS classes, so we text-replace them to "p".
|
||||||
@@ -118,6 +123,11 @@ function setBandColorSchemeFromUI() {
|
|||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Query if a callsign-band-mode combination as has already been worked
|
||||||
|
function alreadyWorked(callsign, band, mode) {
|
||||||
|
return worked.includes(callsign + "-" + band + "-" + mode);
|
||||||
|
}
|
||||||
|
|
||||||
// Reload spots on becoming visible. This forces a refresh when used as a PWA and the user switches back to the PWA
|
// Reload spots on becoming visible. This forces a refresh when used as a PWA and the user switches back to the PWA
|
||||||
// after some time has passed with it in the background.
|
// after some time has passed with it in the background.
|
||||||
addEventListener("visibilitychange", (event) => {
|
addEventListener("visibilitychange", (event) => {
|
||||||
@@ -125,3 +135,12 @@ addEventListener("visibilitychange", (event) => {
|
|||||||
loadSpots();
|
loadSpots();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Startup
|
||||||
|
$(document).ready(function() {
|
||||||
|
// Load worked list
|
||||||
|
var tmpWorked = JSON.parse(localStorage.getItem("worked"));
|
||||||
|
if (tmpWorked) {
|
||||||
|
worked = tmpWorked;
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user