mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2025-10-27 08:49:27 +00:00
Provide UTC/local toggle. Closes #32
This commit is contained in:
@@ -138,35 +138,35 @@ class WebServer:
|
||||
match k:
|
||||
case "since":
|
||||
since = datetime.fromtimestamp(int(query.get(k)), pytz.UTC)
|
||||
spots = [s for s in spots if s.time > since]
|
||||
spots = [s for s in spots if s.time and s.time > since]
|
||||
case "max_age":
|
||||
max_age = int(query.get(k))
|
||||
since = datetime.now(pytz.UTC) - timedelta(seconds=max_age)
|
||||
spots = [s for s in spots if s.time > since]
|
||||
spots = [s for s in spots if s.time and s.time > since]
|
||||
case "received_since":
|
||||
since = datetime.fromtimestamp(int(query.get(k)), pytz.UTC)
|
||||
spots = [s for s in spots if s.received_time > since]
|
||||
spots = [s for s in spots if s.received_time and s.received_time > since]
|
||||
case "source":
|
||||
sources = query.get(k).split(",")
|
||||
spots = [s for s in spots if s.source in sources]
|
||||
spots = [s for s in spots if s.source and s.source in sources]
|
||||
case "sig":
|
||||
sigs = query.get(k).split(",")
|
||||
spots = [s for s in spots if s.sig in sigs]
|
||||
spots = [s for s in spots if s.sig and s.sig in sigs]
|
||||
case "band":
|
||||
bands = query.get(k).split(",")
|
||||
spots = [s for s in spots if s.band in bands]
|
||||
spots = [s for s in spots if s.band and s.band in bands]
|
||||
case "mode":
|
||||
modes = query.get(k).split(",")
|
||||
spots = [s for s in spots if s.mode in modes]
|
||||
case "mode_type":
|
||||
mode_families = query.get(k).split(",")
|
||||
spots = [s for s in spots if s.mode_type in mode_families]
|
||||
spots = [s for s in spots if s.mode_type and s.mode_type in mode_families]
|
||||
case "dx_continent":
|
||||
dxconts = query.get(k).split(",")
|
||||
spots = [s for s in spots if s.dx_continent in dxconts]
|
||||
spots = [s for s in spots if s.dx_continent and s.dx_continent in dxconts]
|
||||
case "de_continent":
|
||||
deconts = query.get(k).split(",")
|
||||
spots = [s for s in spots if s.de_continent in deconts]
|
||||
spots = [s for s in spots if s.de_continent and s.de_continent in deconts]
|
||||
# If we have a "limit" parameter, we apply that last, regardless of where it appeared in the list of keys.
|
||||
if "limit" in query.keys():
|
||||
spots = spots[:int(query.get("limit"))]
|
||||
@@ -195,7 +195,7 @@ class WebServer:
|
||||
match k:
|
||||
case "received_since":
|
||||
since = datetime.fromtimestamp(int(query.get(k)), pytz.UTC)
|
||||
alerts = [a for a in alerts if a.received_time > since]
|
||||
alerts = [a for a in alerts if a.received_time and a.received_time > since]
|
||||
case "max_duration":
|
||||
max_duration = int(query.get(k))
|
||||
# Check the duration if end_time is provided. If end_time is not provided, assume the activation is
|
||||
@@ -204,13 +204,13 @@ class WebServer:
|
||||
not a.end_time]
|
||||
case "source":
|
||||
sources = query.get(k).split(",")
|
||||
alerts = [a for a in alerts if a.source in sources]
|
||||
alerts = [a for a in alerts if a.source and a.source in sources]
|
||||
case "sig":
|
||||
sigs = query.get(k).split(",")
|
||||
alerts = [a for a in alerts if a.sig in sigs]
|
||||
alerts = [a for a in alerts if a.sig and a.sig in sigs]
|
||||
case "dx_continent":
|
||||
dxconts = query.get(k).split(",")
|
||||
alerts = [a for a in alerts if a.dx_continent in dxconts]
|
||||
alerts = [a for a in alerts if a.dx_continent and a.dx_continent in dxconts]
|
||||
# If we have a "limit" parameter, we apply that last, regardless of where it appeared in the list of keys.
|
||||
if "limit" in query.keys():
|
||||
alerts = alerts[:int(query.get("limit"))]
|
||||
|
||||
@@ -7,38 +7,44 @@
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<p class="d-inline-flex gap-1">
|
||||
<button id="settings-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button">Settings</button>
|
||||
<button id="filters-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button">Filters</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="settings-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">
|
||||
<div class="row">
|
||||
<div class="col-auto me-auto">
|
||||
Settings
|
||||
filters
|
||||
</div>
|
||||
<div class="col-auto d-inline-flex">
|
||||
<button id="close-settings-button" type="button" class="btn-close btn-close-white" aria-label="Close"></button>
|
||||
<button id="close-filters-button" type="button" class="btn-close btn-close-white" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="settings-container" class="row row-cols-1 row-cols-md-3 g-4"></div>
|
||||
<div id="filters-container" class="row row-cols-1 row-cols-md-3 g-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="table-container"></div>
|
||||
|
||||
<p>Alerts to view:
|
||||
<select id="alerts-to-fetch" class="storeable-select form-select ms-2" onclick="filtersUpdated();" style="width: 5em;display: inline-block;">
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100" selected>100</option>
|
||||
<option value="200">200</option>
|
||||
<option value="500">500</option>
|
||||
</select>
|
||||
<p>
|
||||
<span class="form-check form-switch d-inline-block">
|
||||
<input class="form-check-input storeable-checkbox" type="checkbox" role="switch" id="useLocalTime" onclick="localTimeUpdated();">
|
||||
<label class="form-check-label" for="useLocalTime">Local time</label>
|
||||
</span>
|
||||
<span class="ms-5">Alerts to view:
|
||||
<select id="alerts-to-fetch" class="storeable-select form-select ms-2" onclick="filtersUpdated();" style="width: 5em;display: inline-block;">
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100" selected>100</option>
|
||||
<option value="200">200</option>
|
||||
<option value="500">500</option>
|
||||
</select>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -22,38 +22,44 @@
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<p class="d-inline-flex gap-1">
|
||||
<button id="settings-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button">Settings</button>
|
||||
<button id="filters-button" type="button" class="btn btn-outline-primary" data-bs-toggle="button">Filters</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="settings-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">
|
||||
<div class="row">
|
||||
<div class="col-auto me-auto">
|
||||
Settings
|
||||
filters
|
||||
</div>
|
||||
<div class="col-auto d-inline-flex">
|
||||
<button id="close-settings-button" type="button" class="btn-close btn-close-white" aria-label="Close"></button>
|
||||
<button id="close-filters-button" type="button" class="btn-close btn-close-white" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="settings-container-1" class="row row-cols-1 g-4 mb-4"></div>
|
||||
<div id="settings-container-2" class="row row-cols-1 row-cols-md-4 g-4"></div>
|
||||
<div id="filters-container-1" class="row row-cols-1 g-4 mb-4"></div>
|
||||
<div id="filters-container-2" class="row row-cols-1 row-cols-md-4 g-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="table-container"></div>
|
||||
|
||||
<p>Spots to view:
|
||||
<select id="spots-to-fetch" class="storeable-select form-select ms-2" onclick="filtersUpdated();" style="width: 5em;display: inline-block;">
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50" selected>50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
<p>
|
||||
<span class="form-check form-switch d-inline-block">
|
||||
<input class="form-check-input storeable-checkbox" type="checkbox" role="switch" id="useLocalTime" onclick="localTimeUpdated();">
|
||||
<label class="form-check-label" for="useLocalTime">Local time</label>
|
||||
</span>
|
||||
<span class="ms-5">Spots to view:
|
||||
<select id="spots-to-fetch" class="storeable-select form-select ms-2 d-inline-block" onclick="filtersUpdated();" style="width: 5em;">
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50" selected>50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -35,10 +35,13 @@ function buildQueryString() {
|
||||
|
||||
// Update the alerts table
|
||||
function updateTable() {
|
||||
// Use local time instead of UTC?
|
||||
var useLocalTime = $("#useLocalTime")[0].checked;
|
||||
|
||||
// Populate table with headers
|
||||
let table = $('<table class="table table-striped-custom table-hover">').append('<thead><tr class="table-primary"></tr></thead><tbody></tbody>');
|
||||
table.find('thead tr').append(`<th>Start UTC</th>`);
|
||||
table.find('thead tr').append(`<th>End UTC</th>`);
|
||||
table.find('thead tr').append(`<th>${useLocalTime ? "Start (Local)" : "Start UTC"}</th>`);
|
||||
table.find('thead tr').append(`<th>${useLocalTime ? "End (Local)" : "End UTC"}</th>`);
|
||||
table.find('thead tr').append(`<th>DX</th>`);
|
||||
table.find('thead tr').append(`<th class='hideonmobile'>Freq<span class='hideonmobile'>uencie</span>s & Modes</th>`);
|
||||
table.find('thead tr').append(`<th class='hideonmobile'>Comment</th>`);
|
||||
@@ -82,18 +85,31 @@ function addAlertRowsToTable(tbody, alerts) {
|
||||
// Create row
|
||||
let $tr = $('<tr>');
|
||||
|
||||
// Format UTC times for display. Start time is displayed as e.g. 7 Oct 12:34 unless the time is in a different
|
||||
// year to the current year, in which case the year is inserted between month and hour.
|
||||
// Use local time instead of UTC?
|
||||
var useLocalTime = $("#useLocalTime")[0].checked;
|
||||
|
||||
// Get times for the alert, and convert to local time if necessary.
|
||||
var start_time = moment.unix(a["start_time"]).utc();
|
||||
if (useLocalTime) {
|
||||
start_time = start_time.local();
|
||||
}
|
||||
var end_time_unix = moment.unix(a["end_time"]);
|
||||
var end_time = end_time_unix.utc();
|
||||
if (useLocalTime) {
|
||||
end_time = end_time.local();
|
||||
}
|
||||
|
||||
// Format the times for display. Start time is displayed as e.g. 7 Oct 12:34 unless the time is in a
|
||||
// different year to the current year, in which case the year is inserted between month and hour.
|
||||
// If the time is set to local not UTC, and the date in local time is "today", we display that instead.
|
||||
// End time is displayed the same as above, except if the end date is the same as the start date, in which case
|
||||
// just e.g. 23:45 is used. Finally, if there is no end date set, "---" is displayed.
|
||||
var start_time = moment.unix(a["start_time"]).utc();
|
||||
var start_time_formatted = start_time.format("D MMM HH:mm");
|
||||
if (start_time.format("YYYY") != moment().format("YYYY")) {
|
||||
start_time_formatted = start_time.format("D MMM YYYY HH:mm");
|
||||
} else if (useLocalTime && start_time.format("D MMM YYYY") == moment().format("D MMM YYYY")) {
|
||||
start_time_formatted = start_time.format("[Today] HH:mm");
|
||||
}
|
||||
|
||||
var end_time_unix = moment.unix(a["end_time"]);
|
||||
var end_time = end_time_unix.utc();
|
||||
var end_time_formatted = "---";
|
||||
if (end_time_unix != null && end_time_unix > 0 && end_time != null) {
|
||||
var end_time_formatted = end_time.format("HH:mm");
|
||||
@@ -166,14 +182,14 @@ function loadOptions() {
|
||||
options = jsonData;
|
||||
|
||||
// Populate the filters panel
|
||||
$("#settings-container").append(generateMultiToggleFilterCard("DX Continent", "dx_continent", options["continents"]));
|
||||
$("#settings-container").append(generateMultiToggleFilterCard("Sources", "source", options["alert_sources"]));
|
||||
$("#filters-container").append(generateMultiToggleFilterCard("DX Continent", "dx_continent", options["continents"]));
|
||||
$("#filters-container").append(generateMultiToggleFilterCard("Sources", "source", options["alert_sources"]));
|
||||
|
||||
// Options doesn't give us anything for Max Duration as it's a free numeric input, but we generate our own
|
||||
// filter card for this.
|
||||
$("#settings-container").append(generateMaxDurationDropdownFilterCard(options["alert_sources"]));
|
||||
$("#filters-container").append(generateMaxDurationDropdownFilterCard(options["alert_sources"]));
|
||||
|
||||
// Load settings from settings storage
|
||||
// Load filters from settings storage
|
||||
loadSettings();
|
||||
|
||||
// Load alerts and set up the timer
|
||||
@@ -213,12 +229,12 @@ function filtersUpdated() {
|
||||
}
|
||||
// Set up UI element event listeners, after the document is ready
|
||||
function setUpEventListeners() {
|
||||
$("#settings-button").click(function() {
|
||||
$("#settings-area").toggle();
|
||||
$("#filters-button").click(function() {
|
||||
$("#filters-area").toggle();
|
||||
});
|
||||
$("#close-settings-button").click(function() {
|
||||
$("#settings-button").button("toggle");
|
||||
$("#settings-area").hide();
|
||||
$("#close-filters-button").click(function() {
|
||||
$("#filters-button").button("toggle");
|
||||
$("#filters-area").hide();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +97,12 @@ function escapeHtml(str) {
|
||||
return str.replace(/[&<>"'`]/g, escapeCharacter);
|
||||
}
|
||||
|
||||
// When the "use local time" field is changed, reload the table and save settings
|
||||
function localTimeUpdated() {
|
||||
updateTable();
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
// Save settings to local storage
|
||||
function saveSettings() {
|
||||
// Find all storeable UI elements, store a key of "element id:property name" mapped to the value of that
|
||||
|
||||
@@ -31,9 +31,12 @@ function buildQueryString() {
|
||||
|
||||
// Update the spots table
|
||||
function updateTable() {
|
||||
// Use local time instead of UTC?
|
||||
var useLocalTime = $("#useLocalTime")[0].checked;
|
||||
|
||||
// Populate table with headers
|
||||
let table = $('<table class="table table-striped-custom table-hover">').append('<thead><tr class="table-primary"></tr></thead><tbody></tbody>');
|
||||
table.find('thead tr').append(`<th>UTC</th>`);
|
||||
table.find('thead tr').append(`<th>${useLocalTime ? "Local" : "UTC"}</th>`);
|
||||
table.find('thead tr').append(`<th>DX</th>`);
|
||||
table.find('thead tr').append(`<th>Freq<span class='hideonmobile'>uency</span></th>`);
|
||||
table.find('thead tr').append(`<th>Mode</th>`);
|
||||
@@ -55,8 +58,11 @@ function updateTable() {
|
||||
$tr.addClass("table-faded");
|
||||
}
|
||||
|
||||
// Format a UTC time for display
|
||||
// Format a UTC or local time for display
|
||||
var time = moment.unix(s["time"]).utc();
|
||||
if (useLocalTime) {
|
||||
time = time.local();
|
||||
}
|
||||
var time_formatted = time.format("HH:mm");
|
||||
|
||||
// Format DX flag
|
||||
@@ -157,13 +163,13 @@ function loadOptions() {
|
||||
addBandColourCSS(options["bands"]);
|
||||
|
||||
// Populate the filters panel
|
||||
$("#settings-container-1").append(generateBandsMultiToggleFilterCard(options["bands"]));
|
||||
$("#settings-container-2").append(generateMultiToggleFilterCard("DX Continent", "dx_continent", options["continents"]));
|
||||
$("#settings-container-2").append(generateMultiToggleFilterCard("DE Continent", "de_continent", options["continents"]));
|
||||
$("#settings-container-2").append(generateMultiToggleFilterCard("Modes", "mode_type", options["mode_types"]));
|
||||
$("#settings-container-2").append(generateMultiToggleFilterCard("Sources", "source", options["spot_sources"]));
|
||||
$("#filters-container-1").append(generateBandsMultiToggleFilterCard(options["bands"]));
|
||||
$("#filters-container-2").append(generateMultiToggleFilterCard("DX Continent", "dx_continent", options["continents"]));
|
||||
$("#filters-container-2").append(generateMultiToggleFilterCard("DE Continent", "de_continent", options["continents"]));
|
||||
$("#filters-container-2").append(generateMultiToggleFilterCard("Modes", "mode_type", options["mode_types"]));
|
||||
$("#filters-container-2").append(generateMultiToggleFilterCard("Sources", "source", options["spot_sources"]));
|
||||
|
||||
// Load settings from settings storage
|
||||
// Load filters from settings storage
|
||||
loadSettings();
|
||||
|
||||
// Load spots and set up the timer
|
||||
@@ -217,12 +223,12 @@ function filtersUpdated() {
|
||||
|
||||
// Set up UI element event listeners, after the document is ready
|
||||
function setUpEventListeners() {
|
||||
$("#settings-button").click(function() {
|
||||
$("#settings-area").toggle();
|
||||
$("#filters-button").click(function() {
|
||||
$("#filters-area").toggle();
|
||||
});
|
||||
$("#close-settings-button").click(function() {
|
||||
$("#settings-button").button("toggle");
|
||||
$("#settings-area").hide();
|
||||
$("#close-filters-button").click(function() {
|
||||
$("#filters-button").button("toggle");
|
||||
$("#filters-area").hide();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user