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.
-
+
{% end %}
\ No newline at end of file
diff --git a/templates/add_spot.html b/templates/add_spot.html
index c95d720..d23de63 100644
--- a/templates/add_spot.html
+++ b/templates/add_spot.html
@@ -69,8 +69,8 @@
-
-
+
+
{% end %}
\ No newline at end of file
diff --git a/templates/alerts.html b/templates/alerts.html
index 6505fe5..6aac4f3 100644
--- a/templates/alerts.html
+++ b/templates/alerts.html
@@ -56,8 +56,8 @@
-
-
+
+
{% end %}
\ No newline at end of file
diff --git a/templates/bands.html b/templates/bands.html
index e275029..6d8dd1d 100644
--- a/templates/bands.html
+++ b/templates/bands.html
@@ -62,9 +62,9 @@
-
-
-
+
+
+
{% end %}
\ No newline at end of file
diff --git a/templates/base.html b/templates/base.html
index a575d2b..1f0fe94 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -46,10 +46,10 @@
crossorigin="anonymous">
-
-
-
-
+
+
+
+
diff --git a/templates/cards/table-columns-spots.html b/templates/cards/table-columns-spots.html
index 1b2f42d..f58f579 100644
--- a/templates/cards/table-columns-spots.html
+++ b/templates/cards/table-columns-spots.html
@@ -38,6 +38,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/templates/cards/worked-calls.html b/templates/cards/worked-calls.html
new file mode 100644
index 0000000..123e199
--- /dev/null
+++ b/templates/cards/worked-calls.html
@@ -0,0 +1,6 @@
+
+
+
Worked Calls
+
+
+
\ No newline at end of file
diff --git a/templates/map.html b/templates/map.html
index 11b7373..eebe69a 100644
--- a/templates/map.html
+++ b/templates/map.html
@@ -70,9 +70,9 @@
-
-
-
+
+
+
{% end %}
\ No newline at end of file
diff --git a/templates/spots.html b/templates/spots.html
index c4faac9..8d0ec65 100644
--- a/templates/spots.html
+++ b/templates/spots.html
@@ -65,6 +65,9 @@
@@ -84,9 +87,9 @@
-
-
-
+
+
+
{% end %}
\ No newline at end of file
diff --git a/templates/status.html b/templates/status.html
index 821eb64..ba99d59 100644
--- a/templates/status.html
+++ b/templates/status.html
@@ -3,8 +3,8 @@
-
-
+
+
{% end %}
\ No newline at end of file
diff --git a/webassets/js/bands.js b/webassets/js/bands.js
index 4a2570c..67707d7 100644
--- a/webassets/js/bands.js
+++ b/webassets/js/bands.js
@@ -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.
spotList.forEach(s => {
- bandSpotsDiv.append(`
`);
});
// Work out how tall the canvas should be. Normally this is matching the normal band column height, but if some
diff --git a/webassets/js/spots.js b/webassets/js/spots.js
index 6ae21eb..c98d166 100644
--- a/webassets/js/spots.js
+++ b/webassets/js/spots.js
@@ -105,6 +105,7 @@ function updateTable() {
var showType = $("#tableShowType")[0].checked;
var showRef = $("#tableShowRef")[0].checked;
var showDE = $("#tableShowDE")[0].checked;
+ var showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked;
// Populate table with headers
let table = $("#table");
@@ -136,12 +137,18 @@ function updateTable() {
if (showDE) {
table.find('thead tr').append(`
DE
`);
}
+ if (showWorkedCheckbox) {
+ table.find('thead tr').append(`
`);
+ }
table.find('tbody').empty();
if (spots.length == 0) {
table.find('tbody').append('
No spots match your filters.
');
}
+ // We are regenerating the entire table not just adding a new row, so reset the row counter
+ rowCount = 0;
+
let spotsNewestFirst = spots.toReversed();
spotsNewestFirst.forEach(s => addSpotToTopOfTable(s, false));
}
@@ -174,6 +181,7 @@ function createNewTableRowsForSpot(s, highlightNew) {
var showType = $("#tableShowType")[0].checked;
var showRef = $("#tableShowRef")[0].checked;
var showDE = $("#tableShowDE")[0].checked;
+ var showWorkedCheckbox = $("#tableShowWorkedCheckbox")[0].checked;
// Create row
let $tr = $('
');
@@ -185,8 +193,9 @@ function createNewTableRowsForSpot(s, highlightNew) {
$tr.addClass("table-active");
}
- // Show faded out if QRT
- if (s["qrt"] == true) {
+ // Show faded out if QRT or already worked
+ let alreadyWorkedThis = alreadyWorked(s["dx_call"], s["band"], s["mode"]);
+ if (s["qrt"] == true || alreadyWorkedThis) {
$tr.addClass("table-faded");
}
@@ -308,6 +317,9 @@ function createNewTableRowsForSpot(s, highlightNew) {
// Format band name
var bandFullName = s['band'] ? s['band'] + " band": "Unknown band";
+ // Format "worked" checkbox
+ var workedCheckbox = ``;
+
// Populate the row
if (showTime) {
$tr.append(`
${time_formatted}
`);
@@ -336,6 +348,9 @@ function createNewTableRowsForSpot(s, highlightNew) {
if (showDE) {
$tr.append(`
${de_flag}${de_call}
`);
}
+ if (showWorkedCheckbox) {
+ $tr.append(`
${workedCheckbox}
`);
+ }
// Second row for mobile view only, containing type, ref & comment
$tr2 = $("
");
@@ -344,7 +359,7 @@ function createNewTableRowsForSpot(s, highlightNew) {
if (rowCount % 2 == 1) {
$tr2.addClass("table-active");
}
- if (s["qrt"] == true) {
+ if (s["qrt"] == true || alreadyWorkedThis) {
$tr2.addClass("table-faded");
}
if (highlightNew) {
@@ -367,6 +382,9 @@ function createNewTableRowsForSpot(s, highlightNew) {
if (showDE) {
$td2floatright.append(` de ${de_call} `);
}
+ if (showWorkedCheckbox) {
+ $td2floatright.append(` ${workedCheckbox} `);
+ }
$td2.append($td2floatright);
$td2.append(``);
if (showComment) {
@@ -481,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
$(document).ready(function() {
// Call loadOptions(), this will then trigger loading spots and setting up timers.
diff --git a/webassets/js/spotsbandsandmap.js b/webassets/js/spotsbandsandmap.js
index 2d46a25..807aef0 100644
--- a/webassets/js/spotsbandsandmap.js
+++ b/webassets/js/spotsbandsandmap.js
@@ -1,5 +1,10 @@
// Storage for the spot data that the server gives us.
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.
// Some band names contain decimal points which are not allowed in CSS classes, so we text-replace them to "p".
@@ -118,10 +123,24 @@ function setBandColorSchemeFromUI() {
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
// after some time has passed with it in the background.
addEventListener("visibilitychange", (event) => {
if (!document.hidden) {
loadSpots();
}
+});
+
+// Startup
+$(document).ready(function() {
+ // Load worked list
+ var tmpWorked = JSON.parse(localStorage.getItem("worked"));
+ if (tmpWorked) {
+ worked = tmpWorked;
+ }
});
\ No newline at end of file