Skip to content

Commit

Permalink
implement manual date/time "handkey" interface
Browse files Browse the repository at this point in the history
Signed-off-by: Jason D. McCormick <[email protected]>
  • Loading branch information
jxmx committed Jun 11, 2022
1 parent f07e8b1 commit d752e8f
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------
** v3.1.0 - 2022-06-11
-------------------------
- Implement an interface for manual entry of logs with a
user-setable date and time

-------------------------
** v3.0.0 - 2022-04-27
-------------------------
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ The following URL endpoints are the support "entries" into the system:

`/index.html` - Main interface

`/handkey.html` - Interface for hand-keying in a paper log

`/board.html` - Display "board" for a running tally display screen

`/cabrillo.html` - Download a Cabrillo log of all contacts
Expand Down Expand Up @@ -217,6 +219,15 @@ found in `api/config_bands.json`. Users of `adif.php` and `cabrillo.php`
will also have to hand-edit those export functions to map added bands appropriately.
A future release will fix this.

## Handkey Interface

The `handkey.html` screen is for someone to hand-enter QSOs from people who
didn't want to log electronically. Obviously not using the live interface can
cause potential dupes, etc. However this provides a way for someone to either
bulk-enter someone's paper log or provide and interface to someone who likes
to write the QSO on paper then enter it and still the correct date/time. On
the main screen, the log time is not editable.

## Issues

For any discovered issues, please file an Issue within Github.
141 changes: 141 additions & 0 deletions handkey.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Firefly Field Day Logger</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/jquery.typeahead.min.css" rel="stylesheet">
<link href="css/local.css" rel="stylesheet">
<link rel="shortcut icon" href="img/firefly.svg" sizes="any" type="image/svg+xml">
<link rel="manifest" href="manifest.json">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="check-circle-fill" fill="currentColor" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
</symbol>
<symbol id="info-fill" fill="currentColor" viewBox="0 0 16 16">
<path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412-1 4.705c-.07.34.029.533.304.533.194 0 .487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703 0-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381 2.29-.287zM8 5.5a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/>
</symbol>
<symbol id="exclamation-triangle-fill" fill="currentColor" viewBox="0 0 16 16">
<path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/>
</symbol>
</svg>
<main>
<div class="titlebars" style="height: 75px;">
<table width="100%" height="100%">
<tr class="titlebars">
<td width="20%" style="vertical-align: middle; text-align: center;">
<img src="img/firefly.svg" height="45px"><span class="px-2">Firefly Logger</span>
</td>
<td width="60%" style="vertical-align: middle; text-align: center;">
<form id="stationset" name="stationset">
<table width="100%" height="100%" class="stationsett">
<tbody style="background-color: rgba(255,255,255,0.5);" class="shadow">
<td style="text-align: center;" class="p-2">
<b>Station Info</b>
</td>
<td>
<input type="text" id="callsign" name="callsign" size="10" class="form-control" placeholder="Callsign" autocomplete="off" readonly>
</td>
<td id="set-operator">
<input type="text" id="operator" name="operator" size="10" class="form-control" placeholder="Operator" autocomplete="off">
</td>
<td>
<select id="band" name="band" class="form-control">
<option value="X">Select Band...</option>
</select>
</td>
<td>
<select id="mode" name="mode" class="form-control">
<option value="X">Select Mode...</option>
</select>
</td>
<td style="text-align: center;" class="p-2">
<button type="button" class="btn btn-misc btn-sm" onclick="saveStationData()">Set</button>
</td>
</tbody>
</table>
</form>
</td>
<td width="20%" style="vertical-align: middle; text-align: center;">
<img src="img/firefly.svg" height="45px"><span class="px-2">Firefly Logger</span>
</td>
</tr>
</table>
</div>
<div class="container-md qso-entry-container shadow">
<div class="row">
<form id="log" name="log">
<table class="table table-borderless">
<thead>
<th scope="col" style="width: 15%">Date<br><i>YYYY-MM-DD</i></th>
<th scope="col" style="width: 10%">Time<br><i>HHMM</i></th>
<th scope="col" style="width: 15%">Callsign</th>
<th scope="col" style="width: 10%">Class</th>
<th scope="col" style="width: 10%">Section</th>
<th scope="col" style="width: 10%">&nbsp;</th>
<th scope="col" style="width: 10%">&nbsp;</th>
<th scope="col" style="width: 15%"></th>


</thead>
<tbody>
<td class="align-top">
<input type="text" size=12 name="logclockdate" id="logclockdate" class="form-control"
tabindex="-1" autocomplete="off">
</td>
<td class="align-top">
<input type="text" size=5 name="logclocktime" id="logclocktime" class="form-control"
autocomplete="off">
</td>
<td class="align-top">
<input id="call" name="call" type="text" size="10" class="form-control"
onkeyup="this.value = this.value.toUpperCase();" onblur="isDupeQSO()" autocomplete="off">
</td>
<td class="align-top">
<input id="opclass" name="opclass" type="text" size="10" class="form-control"
onkeyup="this.value = this.value.toUpperCase();" autocomplete="off">
</td>
<td class="align-top">
<div id="arrl-sections">
<input id="section" name="section" class="typeahead form-control" type="text"
size="10" autocomplete="off" onkeyup="this.value = this.value.toUpperCase();">
</div>
</td>
<td class="align-top" align="center">
<button id="logsubmit" name="logsubmit" type="button" class="btn btn-danger"
onclick="logSubmit()">Log</button>
</td>
<td class="align-top" align="left">
<button id="logclear" name="logclear" type="button" class="btn btn-misc"
onclick="logReset()" tabindex="-1">Clear</button>
</td>
<td><!-- future --> </td>
</tbody>
</table>
<input type="hidden" id="logclock" name="logclock" value="">
<input type="hidden" id="opcallsign" name="opcallsign" value="">
<input type="hidden" id="opoperator" name="opoperator" value="">
<input type="hidden" id="opband" name="opband" value="">
<input type="hidden" id="opmode" name="opmode" value="">
<input type="hidden" id="qkey" name="qkey" value="">
</form>
</div>
<div class="row">
<div id="d-flex">
<div id="statusarea" class="invisible alert d-flex align-items-center alert-dismissable fade show" role="alert"></div>
</div>
</div>
</div>
<script src="js/bootstrap.min.js"></script>
<script src="js/jquery-3.6.0.min.js"></script>
<script src="js/typeahead.jquery.js"></script>
<script src="js/statusmsg.js"></script>
<script src="js/index.js"></script>
</main>
<footer>
<div class="d-flex footerbar p-2"><i>Powered by Firefly Field Day Logger by Jason McCormick N8EI - <a href="https://github.com/jxmx/ffdl" tabindex="-1">GitHub</a></i></div>
</footer>
</body>
</html>
128 changes: 112 additions & 16 deletions js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ let config = {
var qsinceload = 0;
var sectionsloaded = false;
var stationcookieexists = false;
var thispage = location.href.split("/").slice(-1);

if(thispage == "handkey.html")
var isHandKey = true;

// load configuration from JSON files
function getConfig(configType){
Expand All @@ -34,25 +38,20 @@ function getConfig(configType){
var a = JSON.parse(this.responseText);
switch(configType){
case "general":
console.log("get config general");
config.general = a;
console.log("set config general");
setGeneralConfig();
break;
case "bands":
console.log("get config bands");
config.bands = a;
refreshBandList(config.bands.band);
setStationDataFromCookie();
break;
case "modes":
console.log("get config modes");
config.modes = a;
refreshModeList(config.modes.modes);
setStationDataFromCookie();
break;
case "sections":
console.log("get config sections");
config.sections = a;
sectionsloaded = true;
break;
Expand Down Expand Up @@ -91,10 +90,14 @@ window.addEventListener("load", function(){
getConfig("bands");
getConfig("modes");
getConfig("sections");
setGeneralConfig();
updateLogTime();
setInterval(updateLogTime,1000);
setInterval(testCookieExists,1000);

// Only things for the main form at index.html
if(thispage == "index.html" || thispage == ""){
setGeneralConfig();
updateLogTime();
setInterval(updateLogTime,1000);
setInterval(testCookieExists,1000);
}
});

//
Expand Down Expand Up @@ -135,6 +138,8 @@ var submitOkCall = false;
var submitOkClass = false;
var submitOkSection = false;
var submitOkDupe = false;
var submitOkLogClockDate = false;
var submitOkLogClockTime = false;

//
// QSO Call Validation - is callsign well-formed
Expand Down Expand Up @@ -301,12 +306,21 @@ function resetSubmitOkStatus() {
submitOkClass = false;
submitOkSection = false;
submitOkDupe = false;
submitOkLogClockDate = false;
submitOkLogClockTime = false;
toggleLogButton(false);
}

// check if it's ready to submit
function checkSubmitOkStatus() {
if( submitOkCall && submitOkClass && submitOkSection ){ // && submitOkDupe )
if( submitOkCall && submitOkClass && submitOkSection ){
if(isHandKey){
if(submitOkLogClockDate && submitOkLogClockTime){
return true;
} else {
return false;
}
}
return true;
} else {
return false;
Expand All @@ -331,7 +345,9 @@ function logSubmit() {
lform.method = "POST";
lform.action = "#";

// Generate and store the qkey hash
// If this is the handkey.html version the date/time needs to be parsed out
if(isHandKey)
handkeyDateTime();

// I have no idea whyu these can't be directly assigned by value.... Javascript is annoying
var opcallsign= document.getElementById("callsign").value;
Expand Down Expand Up @@ -367,7 +383,8 @@ function logSubmit() {
}

// update the display and clear the entry
updateDisplayLog();
if(!isHandKey)
updateDisplayLog();
logReset();
},
failure: function(msg) {
Expand All @@ -380,13 +397,92 @@ function logSubmit() {

// reset the log form
function logReset() {
clearStatusMsg();
// clearStatusMsg();
resetSubmitOkStatus();

// save the date for handkeying
if(isHandKey)
var lcd = document.getElementById("logclockdate").value;

document.getElementById("log").reset();

$('#log input').parent().find('input').removeClass("is-invalid").removeClass("is-valid");
document.getElementById("call").focus();

if(isHandKey){
document.getElementById("logclockdate").value = lcd;
document.getElementById("logclocktime").focus();
} else {
document.getElementById("call").focus();
}
};

// handkey.html variant support
function handkeyDateTime() {
var lcd = document.getElementById("logclockdate").value;
var lct = document.getElementById("logclocktime").value;
var logclock = lcd.concat(" ", lct.slice(0,2), ":", lct.slice(2,4), ":", "00");
document.getElementById("logclock").value = logclock;
};

$('#logclockdate').focusout(function() {
var input=$(this);
var re = /^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/;
var is_valid = true;
var dt = input.val();

if(re.test(input.val())){
var y = dt.slice(0,4);
var m = dt.slice(5,7);
var d = dt.slice(8,12);

// Y2K1 problem!
if(y < 2000 || y > 2100 ) is_valid = false;
if(m < 1 || m > 12 ) is_valid = false;
if(d < 1 || d > 31 ) is_valid = false;

} else {
is_valid = false;
}

if(is_valid){
input.removeClass("is-invalid").addClass("is-valid");
submitOkLogClockDate = true;
} else {
input.removeClass("is-valid").addClass("is-invalid");
submitOkLogClockDate = false;
}
});

$('#logclocktime').focusout(function() {
var input=$(this);
var re = /^[0-9]{3,4}$/;
var is_valid = true;
var t = input.val();

if(re.test(input.val())){
if(t.length == 3)
t = "0".concat(t);
document.getElementById("logclocktime").value = t;
var hh = t.slice(0,2);
var mm = t.slice(2,4);

if(hh < 0 || hh > 23) is_valid = false;
if(mm < 0 || mm > 59) is_valid = false;

} else {
is_valid = false;
}

if(is_valid){
input.removeClass("is-invalid").addClass("is-valid");
submitOkLogClockTime = true;
} else {
input.removeClass("is-valid").addClass("is-invalid");
submitOkLogClockTime = false;
}
});


//
// Manage QSOs
//
Expand All @@ -395,7 +491,7 @@ function editQSO(qkey){
}

function delQSO(qkey, qcall){
if( confirm("Are you sue your want to delete QSO with " + qcall + "?\n(QSO ID# " + qkey + ")") ){
if( confirm("Are you sure your want to delete QSO with " + qcall + "?\n(QSO ID# " + qkey + ")") ){
$.ajax({
type: "GET",
url: "api/delqso.php?qkey=" + qkey,
Expand Down Expand Up @@ -572,4 +668,4 @@ function testCookieExists(){
stationcookieexists = false;
}
}
}
}

0 comments on commit d752e8f

Please sign in to comment.