From 397a60d08384eafbaaedbc903dae6449114c4be2 Mon Sep 17 00:00:00 2001
From: Andreas <6977712+AndreasK79@users.noreply.github.com>
Date: Fri, 26 May 2023 10:38:31 +0200
Subject: [PATCH 1/7] [LoTW] Added table with users. Query to find unconfirmed
QSOs and L marking in advanced logbook
---
application/config/migration.php | 2 +-
application/controllers/Logbook.php | 36 +++++++++++++
application/controllers/Search.php | 12 +++++
application/controllers/Update.php | 44 ++++++++++++++--
application/migrations/123_add_lotw_users.php | 41 +++++++++++++++
application/models/Logbookadvanced_model.php | 1 +
application/views/interface_assets/footer.php | 23 +++++++++
application/views/search/cqzones.php | 4 +-
application/views/search/duplicates.php | 4 +-
application/views/search/filter.php | 4 +-
application/views/search/lotw_unconfirmed.php | 50 +++++++++++++++++++
.../views/search/lotw_unconfirmed_result.php | 43 ++++++++++++++++
application/views/search/main.php | 3 ++
assets/js/sections/logbookadvanced.js | 4 +-
src/QSLManager/QSO.php | 7 +++
15 files changed, 269 insertions(+), 9 deletions(-)
create mode 100644 application/migrations/123_add_lotw_users.php
create mode 100644 application/views/search/lotw_unconfirmed.php
create mode 100644 application/views/search/lotw_unconfirmed_result.php
diff --git a/application/config/migration.php b/application/config/migration.php
index 372fbaf2..c4ac8962 100644
--- a/application/config/migration.php
+++ b/application/config/migration.php
@@ -21,7 +21,7 @@ $config['migration_enabled'] = TRUE;
| be upgraded / downgraded to.
|
*/
-$config['migration_version'] = 122;
+$config['migration_version'] = 123;
/*
|--------------------------------------------------------------------------
diff --git a/application/controllers/Logbook.php b/application/controllers/Logbook.php
index 548ecafd..66ae7b81 100644
--- a/application/controllers/Logbook.php
+++ b/application/controllers/Logbook.php
@@ -814,6 +814,42 @@ class Logbook extends CI_Controller {
}
+ function search_lotw_unconfirmed($station_id) {
+ $station_id = $this->security->xss_clean($station_id);
+
+ $this->load->model('user_model');
+
+ if(!$this->user_model->authorize($this->config->item('auth_mode'))) { return; }
+
+ $CI =& get_instance();
+ $CI->load->model('logbooks_model');
+ $logbooks_locations_array = $CI->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook'));
+
+ if (!$logbooks_locations_array) {
+ return null;
+ }
+
+ $location_list = "'".implode("','",$logbooks_locations_array)."'";
+
+ $sql = 'select COL_CALL, COL_MODE, COL_SUBMODE, station_callsign, COL_SAT_NAME, COL_BAND, COL_TIME_ON, lotw_users.lastupload from ' . $this->config->item('table_name') .
+ ' join station_profile on ' . $this->config->item('table_name') . '.station_id = station_profile.station_id
+ join lotw_users on ' . $this->config->item('table_name') . '.col_call = lotw_users.callsign
+ where ' . $this->config->item('table_name') .'.station_id in ('. $location_list . ')';
+
+ if ($station_id != 'All') {
+ $sql .= ' and station_profile.station_id = ' . $station_id;
+ }
+
+ $sql .= " and COL_LOTW_QSL_RCVD <> 'Y' and " . $this->config->item('table_name') . ".COL_TIME_ON < lotw_users.lastupload";
+
+ $query = $this->db->query($sql);
+
+ $data['qsos'] = $query;
+
+ $this->load->view('search/lotw_unconfirmed_result.php', $data);
+
+ }
+
function search_incorrect_cq_zones($station_id) {
$station_id = $this->security->xss_clean($station_id);
diff --git a/application/controllers/Search.php b/application/controllers/Search.php
index af43c511..f503d059 100644
--- a/application/controllers/Search.php
+++ b/application/controllers/Search.php
@@ -80,6 +80,18 @@ class Search extends CI_Controller {
$this->load->view('interface_assets/footer');
}
+ // Searches for unconfirmed Lotw QSOs where QSO partner has uploaded to LoTW after the QSO date
+ public function lotw_unconfirmed() {
+ $this->load->model('stations');
+
+ $data['station_profile'] = $this->stations->all_of_user();
+ $data['page_title'] = "QSOs unconfirmed on LoTW, but the callsign has uploaded to LoTW after QSO date";
+
+ $this->load->view('interface_assets/header', $data);
+ $this->load->view('search/lotw_unconfirmed');
+ $this->load->view('interface_assets/footer');
+ }
+
function json_result() {
if(isset($_POST['search'])) {
$result = $this->fetchQueryResult($_POST['search'], false);
diff --git a/application/controllers/Update.php b/application/controllers/Update.php
index 81c3f509..d6cd88c3 100644
--- a/application/controllers/Update.php
+++ b/application/controllers/Update.php
@@ -287,9 +287,6 @@ class Update extends CI_Controller {
}
public function download_lotw_users() {
-
-
-
$contents = file_get_contents('https://lotw.arrl.org/lotw-user-activity.csv', true);
if($contents === FALSE) {
@@ -306,6 +303,47 @@ class Update extends CI_Controller {
}
+ public function lotw_users() {
+ $mtime = microtime();
+ $mtime = explode(" ",$mtime);
+ $mtime = $mtime[1] + $mtime[0];
+ $starttime = $mtime;
+
+ $file = 'https://lotw.arrl.org/lotw-user-activity.csv';
+
+ $handle = fopen($file, "r");
+ if ($handle === FALSE) {
+ echo "Something went wrong with fetching the LoTW uses file";
+ return;
+ }
+ $this->db->empty_table("lotw_users");
+ $i = 0;
+ $data = fgetcsv($handle,1000,",");
+ do {
+ if ($data[0]) {
+ $lotwdata[$i]['callsign'] = $data[0];
+ $lotwdata[$i]['lastupload'] = $data[1] . ' ' . $data[2];
+ if (($i % 2000) == 0) {
+ $this->db->insert_batch('lotw_users', $lotwdata);
+ unset($lotwdata);
+ // echo 'Record ' . $i . '
';
+ }
+ $i++;
+ }
+ } while ($data = fgetcsv($handle,1000,","));
+ fclose($handle);
+
+ $this->db->insert_batch('lotw_users', $lotwdata);
+
+ $mtime = microtime();
+ $mtime = explode(" ",$mtime);
+ $mtime = $mtime[1] + $mtime[0];
+ $endtime = $mtime;
+ $totaltime = ($endtime - $starttime);
+ echo "This page was created in ".$totaltime." seconds
";
+ echo "Records inserted: " . $i . "
";
+ }
+
public function lotw_check() {
$f = fopen('./updates/lotw_users.csv', "r");
$result = false;
diff --git a/application/migrations/123_add_lotw_users.php b/application/migrations/123_add_lotw_users.php
new file mode 100644
index 00000000..84709a76
--- /dev/null
+++ b/application/migrations/123_add_lotw_users.php
@@ -0,0 +1,41 @@
+db->table_exists('lotw_users')) {
+ $this->dbforge->add_field(array(
+ 'id' => array(
+ 'type' => 'INT',
+ 'constraint' => 20,
+ 'unsigned' => TRUE,
+ 'auto_increment' => TRUE,
+ 'unique' => TRUE
+ ),
+ 'callsign' => array(
+ 'type' => 'VARCHAR',
+ 'constraint' => 32,
+ 'unsigned' => TRUE,
+ ),
+ 'lastupload' => array(
+ 'type' => 'timestamp',
+ 'unsigned' => TRUE,
+ )
+ ));
+
+ $this->dbforge->add_key('id', TRUE);
+
+ $this->dbforge->create_table('lotw_users');
+
+ $this->db->query("ALTER TABLE lotw_users ADD INDEX `callsign` (`callsign`)");
+ }
+
+ }
+
+ public function down()
+ {
+ $this->dbforge->drop_table('lotw_users');
+ }
+}
diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php
index 437f4f7a..f0571352 100644
--- a/application/models/Logbookadvanced_model.php
+++ b/application/models/Logbookadvanced_model.php
@@ -100,6 +100,7 @@ class Logbookadvanced_model extends CI_Model {
FROM " . $this->config->item('table_name') . " qsos
INNER JOIN station_profile ON qsos.station_id=station_profile.station_id
LEFT OUTER JOIN dxcc_entities ON qsos.col_dxcc=dxcc_entities.adif
+ LEFT OUTER JOIN lotw_users ON qsos.col_call=lotw_users.callsign
WHERE station_profile.user_id = ?
$where
ORDER BY qsos.COL_TIME_ON desc, qsos.COL_PRIMARY_KEY desc
diff --git a/application/views/interface_assets/footer.php b/application/views/interface_assets/footer.php
index 4430a9c0..4e7741e2 100644
--- a/application/views/interface_assets/footer.php
+++ b/application/views/interface_assets/footer.php
@@ -816,6 +816,29 @@ function findduplicates(){
});
}
+function findlotwunconfirmed(){
+ event.preventDefault();
+ $('#partial_view').load(base_url+"index.php/logbook/search_lotw_unconfirmed/"+$("#station_id").val(), function() {
+ $('.qsolist').DataTable({
+ "pageLength": 25,
+ responsive: false,
+ ordering: false,
+ "scrollY": "500px",
+ "scrollCollapse": true,
+ "paging": false,
+ "scrollX": true,
+ dom: 'Bfrtip',
+ buttons: [
+ 'csv'
+ ]
+ });
+ // change color of csv-button if dark mode is chosen
+ if (isDarkModeTheme()) {
+ $(".buttons-csv").css("color", "white");
+ }
+ });
+}
+
function findincorrectcqzones() {
event.preventDefault();
$('#partial_view').load(base_url+"index.php/logbook/search_incorrect_cq_zones/"+$("#station_id").val(), function() {
diff --git a/application/views/search/cqzones.php b/application/views/search/cqzones.php
index 309d074a..ca90566a 100644
--- a/application/views/search/cqzones.php
+++ b/application/views/search/cqzones.php
@@ -17,9 +17,11 @@
| '.lang('gen_hamradio_callsign').' | +Date / time | +' . lang('gen_hamradio_mode') . ' | +' . lang('gen_hamradio_band') . ' | +Last LoTW upload | +' . lang('gen_hamradio_station') . ' | +
|---|---|---|---|---|---|
| '; + echo ' | ' . $qso->COL_TIME_ON . ' | '; + echo ''; echo $qso->COL_SUBMODE==null?$qso->COL_MODE:$qso->COL_SUBMODE; echo ' | '; + echo ''; if($qso->COL_SAT_NAME != null) { echo $qso->COL_SAT_NAME; } else { echo strtolower($qso->COL_BAND); }; echo ' | '; + echo '' . $qso->lastupload . ' | '; + echo '' . $qso->station_callsign . ' | '; + echo '
Export All Satellite QSOs Confirmed on LoTW
+Export All Satellite QSOs Confirmed on LoTW
diff --git a/application/views/search/cqzones.php b/application/views/search/cqzones.php index ca90566a..9a5867ab 100644 --- a/application/views/search/cqzones.php +++ b/application/views/search/cqzones.php @@ -21,7 +21,7 @@ Incorrect CQ Zoneslastupload); echo date($custom_date_format, $timestamp); $timestamp = strtotime($row->lastupload); echo " at ".date('H:i', $timestamp);?> UTC.
+ COL_LOTW_QSL_RCVD == "Y") { ?> From 56899375e5db1f3f5398a698e14e60330f3a41a7 Mon Sep 17 00:00:00 2001 From: Andreas <6977712+AndreasK79@users.noreply.github.com> Date: Sat, 27 May 2023 18:04:09 +0200 Subject: [PATCH 4/7] [Advanced Logbook] Added formatting of date/time and country name --- src/QSLManager/QSO.php | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/QSLManager/QSO.php b/src/QSLManager/QSO.php index 7edf070b..9558ff8b 100644 --- a/src/QSLManager/QSO.php +++ b/src/QSLManager/QSO.php @@ -10,7 +10,7 @@ use DomainException; class QSO { private string $qsoID; - private DateTime $qsoDateTime; + private string $qsoDateTime; private string $de; private string $dx; private string $mode; @@ -123,7 +123,16 @@ class QSO $this->qsoID = $data['COL_PRIMARY_KEY']; - $this->qsoDateTime = DateTime::createFromFormat("Y-m-d H:i:s", $data['COL_TIME_ON'], new DateTimeZone("UTC")); + $CI =& get_instance(); + // Get Date format + if($CI->session->userdata('user_date_format')) { + // If Logged in and session exists + $custom_date_format = $CI->session->userdata('user_date_format'); + } else { + // Get Default date format from /config/cloudlog.php + $custom_date_format = $CI->config->item('qso_date_format'); + } + $this->qsoDateTime = date($custom_date_format . " H:i", strtotime($data['COL_TIME_ON'])); $this->de = $data['COL_STATION_CALLSIGN']; $this->dx = $data['COL_CALL']; @@ -170,16 +179,6 @@ class QSO $this->QSLSent = ($data['COL_QSL_SENT'] === null) ? '' : $data['COL_QSL_SENT']; $this->QSLSentVia = ($data['COL_QSL_SENT_VIA'] === null) ? '' : $data['COL_QSL_SENT_VIA']; $this->QSLVia = ($data['COL_QSL_VIA'] === null) ? '' : $data['COL_QSL_VIA']; - - $CI =& get_instance(); - // Get Date format - if($CI->session->userdata('user_date_format')) { - // If Logged in and session exists - $custom_date_format = $CI->session->userdata('user_date_format'); - } else { - // Get Default date format from /config/cloudlog.php - $custom_date_format = $CI->config->item('qso_date_format'); - } $this->qsl = $this->getQslString($data, $custom_date_format); $this->lotw = $this->getLotwString($data, $custom_date_format); @@ -187,7 +186,7 @@ class QSO $this->cqzone = ($data['COL_CQZ'] === null) ? '' : $data['COL_CQZ']; $this->state = ($data['COL_STATE'] === null) ? '' :$data['COL_STATE']; - $this->dxcc = ($data['name'] === null) ? '- NONE -' :$data['name']; + $this->dxcc = ($data['name'] === null) ? '- NONE -' : ucwords(strtolower($data['name']), "- (/"); $this->iota = ($data['COL_IOTA'] === null) ? '' :$data['COL_IOTA']; if (array_key_exists('end', $data)) { $this->end = ($data['end'] === null) ? null : DateTime::createFromFormat("Y-m-d", $data['end'], new DateTimeZone('UTC')); @@ -413,7 +412,7 @@ class QSO /** * @return DateTime */ - public function getQsoDateTime(): DateTime + public function getQsoDateTime(): string { return $this->qsoDateTime; } @@ -754,7 +753,7 @@ class QSO { return [ 'qsoID' => $this->qsoID, - 'qsoDateTime' => $this->qsoDateTime->format("Y-m-d H:i"), + 'qsoDateTime' => $this->qsoDateTime, 'de' => $this->de, 'dx' => $this->dx, 'mode' => $this->getFormattedMode(), From 8616cea9edaedd268d6b893641b5b459de1d6fa9 Mon Sep 17 00:00:00 2001 From: Andreas <6977712+AndreasK79@users.noreply.github.com> Date: Sat, 27 May 2023 18:14:29 +0200 Subject: [PATCH 5/7] [LoTW mouse over] Formatted date --- src/QSLManager/QSO.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/QSLManager/QSO.php b/src/QSLManager/QSO.php index 9558ff8b..a64bd402 100644 --- a/src/QSLManager/QSO.php +++ b/src/QSLManager/QSO.php @@ -194,7 +194,8 @@ class QSO $this->end = null; } $this->callsign = ($data['callsign'] === null) ? '' :$data['callsign']; - $this->lastupload = ($data['lastupload'] === null) ? '' :$data['lastupload']; + $this->lastupload = ($data['lastupload'] === null) ? '' : date($custom_date_format . " H:i", strtotime($data['lastupload'])); + } /** From fc9358933ac937165d21ab7bbe94214dbbf3a308 Mon Sep 17 00:00:00 2001 From: Andreas <6977712+AndreasK79@users.noreply.github.com> Date: Sat, 27 May 2023 19:05:11 +0200 Subject: [PATCH 6/7] [Advanced Logbook] Fixed sorting for custom date format --- application/controllers/Logbookadvanced.php | 26 ++++++++++++++++++++- application/views/logbookadvanced/index.php | 9 +++++++ assets/js/sections/logbookadvanced.js | 2 +- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/application/controllers/Logbookadvanced.php b/application/controllers/Logbookadvanced.php index 6f054479..19daff37 100644 --- a/application/controllers/Logbookadvanced.php +++ b/application/controllers/Logbookadvanced.php @@ -49,11 +49,35 @@ class Logbookadvanced extends CI_Controller { $pageData['sats'] = $this->bands->get_worked_sats(); $pageData['bands'] = $this->bands->get_worked_bands(); - + + $CI =& get_instance(); + // Get Date format + if($CI->session->userdata('user_date_format')) { + // If Logged in and session exists + $pageData['custom_date_format'] = $CI->session->userdata('user_date_format'); + } else { + // Get Default date format from /config/cloudlog.php + $pageData['custom_date_format'] = $CI->config->item('qso_date_format'); + } + + switch ($pageData['custom_date_format']) { + case "d/m/y": $pageData['custom_date_format'] = 'DD/MM/YY'; break; + case "d/m/Y": $pageData['custom_date_format'] = 'DD/MM/YYYY'; break; + case "m/d/y": $pageData['custom_date_format'] = 'MM/DD/YY'; break; + case "m/d/Y": $pageData['custom_date_format'] = 'MM/DD/YYYY'; break; + case "d.m.Y": $pageData['custom_date_format'] = 'DD.MM.YYYY'; break; + case "y/m/d": $pageData['custom_date_format'] = 'YY/MM/DD'; break; + case "Y-m-d": $pageData['custom_date_format'] = 'YYYY-MM-DD'; break; + case "M d, Y": $pageData['custom_date_format'] = 'MMM DD, YYYY'; break; + case "M d, y": $pageData['custom_date_format'] = 'MMM DD, YY'; break; + default: $pageData['custom_date_format'] = 'DD/MM/YYYY'; + } + $footerData = []; $footerData['scripts'] = [ 'assets/js/moment.min.js', 'assets/js/tempusdominus-bootstrap-4.min.js', + 'assets/js/datetime-moment.js', 'assets/js/sections/logbookadvanced.js?' . filemtime(realpath(__DIR__ . "/../../assets/js/sections/logbookadvanced.js")) ]; diff --git a/application/views/logbookadvanced/index.php b/application/views/logbookadvanced/index.php index 42c0438c..ed417d8b 100644 --- a/application/views/logbookadvanced/index.php +++ b/application/views/logbookadvanced/index.php @@ -1,3 +1,12 @@ + +