diff --git a/application/controllers/Webadif.php b/application/controllers/Webadif.php new file mode 100644 index 00000000..608b67d6 --- /dev/null +++ b/application/controllers/Webadif.php @@ -0,0 +1,156 @@ +setOptions(); + + $this->load->model('logbook_model'); + + $station_ids = $this->logbook_model->get_station_id_with_webadif_api(); + + if ($station_ids) { + foreach ($station_ids as $station) { + $webadif_api_key = $station->webadifapikey; + $webadif_api_url = $station->webadifapiurl; + if ($this->mass_upload_qsos($station->station_id, $webadif_api_key, $webadif_api_url)) { + echo "QSOs have been uploaded to QO-100 Dx Club."; + log_message('info', 'QSOs have been uploaded to QO-100 Dx Club.'); + } else { + echo "No QSOs found for upload."; + log_message('info', 'No QSOs found for upload.'); + } + } + } else { + echo "No station profiles with a QO-100 Dx Club API Key found."; + log_message('error', "No station profiles with a QO-100 Dx Club API Key found."); + } + } + + function setOptions() { + $this->config->load('config'); + ini_set('memory_limit', '-1'); + ini_set('display_errors', 1); + ini_set('display_startup_errors', 1); + error_reporting(E_ALL); + } + + /* + * Function gets all QSOs from given station_id, that are not previously uploaded to webADIF consumer. + * Adif is build for each qso, and then uploaded, one at a time + */ + function mass_upload_qsos($station_id, $webadif_api_key, $webadif_api_url) { + $i = 0; + $data['qsos'] = $this->logbook_model->get_webadif_qsos($station_id); + $errormessages=array(); + + $CI =& get_instance(); + $CI->load->library('AdifHelper'); + + if ($data['qsos']) { + foreach ($data['qsos']->result() as $qso) { + $adif = $CI->adifhelper->getAdifLine($qso); + $result = $this->logbook_model->push_qso_to_webadif($webadif_api_url, $webadif_api_key, $adif); + + if ($result) { + $this->logbook_model->mark_webadif_qsos_sent($qso->COL_PRIMARY_KEY); + $i++; + } else { + $errorMessage = 'QO-100 Dx Club upload failed for qso: Call: ' . $qso->COL_CALL . ' Band: ' . $qso->COL_BAND . ' Mode: ' . $qso->COL_MODE . ' Time: ' . $qso->COL_TIME_ON; + log_message('error', $errorMessage); + $errormessages[] = $errorMessage; + } + } + $result=[]; + $result['status'] = 'OK'; + $result['count'] = $i; + $result['errormessages'] = $errormessages; + return $result; + } else { + $result=[]; + $result['status'] = 'Error'; + $result['count'] = $i; + $result['errormessages'] = $errormessages; + return $result; + } + } + + /* + * Used for displaying the uid for manually selecting log for upload to webADIF consumer + */ + public function export() { + $this->load->model('stations'); + + $data['page_title'] = "QO-100 Dx Club Upload"; + + $data['station_profiles'] = $this->stations->all_of_user(); + $data['station_profile'] = $this->stations->stations_with_webadif_api_key(); + + $this->load->view('interface_assets/header', $data); + $this->load->view('webadif/export'); + $this->load->view('interface_assets/footer'); + } + + /* + * Used for ajax-function when selecting log for upload to webADIF consumer + */ + public function upload_station() { + $this->setOptions(); + $this->load->model('stations'); + + $postData = $this->input->post(); + + $this->load->model('logbook_model'); + $result = $this->logbook_model->exists_webadif_api_key($postData['station_id']); + $webadif_api_key = $result->webadifapikey; + $webadif_api_url = $result->webadifapiurl; + header('Content-type: application/json'); + $result = $this->mass_upload_qsos($postData['station_id'], $webadif_api_key, $webadif_api_url); + if ($result['status'] == 'OK') { + $stationinfo = $this->stations->stations_with_webadif_api_key(); + $info = $stationinfo->result(); + + $data['status'] = 'OK'; + $data['info'] = $info; + $data['infomessage'] = $result['count'] . " QSOs are now uploaded to QO-100 Dx Club"; + $data['errormessages'] = $result['errormessages']; + echo json_encode($data); + } else { + $data['status'] = 'Error'; + $data['info'] = 'Error: No QSOs found to upload.'; + $data['errormessages'] = $result['errormessages']; + echo json_encode($data); + } + } + + public function mark_webadif() { + // Set memory limit to unlimited to allow heavy usage + ini_set('memory_limit', '-1'); + $data['page_title'] = "QO-100 Dx Club Upload"; + + $station_id = $this->security->xss_clean($this->input->post('station_profile')); + + $this->load->model('adif_data'); + + $data['qsos'] = $this->adif_data->export_custom($this->input->post('from'), $this->input->post('to'), $station_id); + + $this->load->model('logbook_model'); + if ($data['qsos']!==null) { + foreach ($data['qsos']->result() as $qso) { + $this->logbook_model->mark_webadif_qsos_sent($qso->COL_PRIMARY_KEY); + } + } + + $this->load->view('interface_assets/header', $data); + $this->load->view('webadif/mark_webadif', $data); + $this->load->view('interface_assets/footer'); + } +} diff --git a/application/models/Logbook_model.php b/application/models/Logbook_model.php index 53299b8a..f4365922 100755 --- a/application/models/Logbook_model.php +++ b/application/models/Logbook_model.php @@ -1275,6 +1275,25 @@ class Logbook_model extends CI_Model { return $query; } + /* + * Function returns the QSOs from the logbook, which have not been either marked as uploaded to webADIF + */ + function get_webadif_qsos($station_id){ + $sql = " + SELECT qsos.*, station_profile.* FROM %s qsos + INNER JOIN station_profile ON qsos.station_id = station_profile.station_id + LEFT JOIN webadif ON qsos.COL_PRIMARY_KEY = webadif.qso_id + WHERE qsos.station_id = %d + AND webadif.upload_date IS NULL + "; + $sql = sprintf( + $sql, + $this->config->item('table_name'), + $station_id + ); + return $this->db->query($sql); + } + /* * Function returns all the station_id's with QRZ API Key's */ @@ -1294,6 +1313,26 @@ class Logbook_model extends CI_Model { } } + /* + * Function returns all the station_id's with QRZ API Key's + */ + function get_station_id_with_webadif_api() { + $sql = " + SELECT station_id, webadifapikey, webadifapiurl + FROM station_profile + WHERE COALESCE(webadifapikey, '') <> '' + AND COALESCE(webadifapiurl, '') <> '' + "; + + $query = $this->db->query($sql); + $result = $query->result(); + if ($result) { + return $result; + } else { + return null; + } + } + function get_last_qsos($num, $StationLocationsArray = null) { if($StationLocationsArray == null) { diff --git a/application/models/Stations.php b/application/models/Stations.php index 5abab0c7..03a689da 100644 --- a/application/models/Stations.php +++ b/application/models/Stations.php @@ -345,6 +345,35 @@ class Stations extends CI_Model { return $query; } + function stations_with_webadif_api_key() { + $sql=" + SELECT station_profile.station_id, station_profile.station_profile_name, station_profile.station_callsign, notc.c notcount, totc.c totcount + FROM station_profile + INNER JOIN ( + SELECT qsos.station_id, COUNT(qsos.COL_PRIMARY_KEY) c + FROM %s qsos + LEFT JOIN webadif ON qsos.COL_PRIMARY_KEY = webadif.qso_id + WHERE webadif.qso_id IS NULL + GROUP BY qsos.station_id + ) notc + INNER JOIN ( + SELECT qsos.station_id, COUNT(qsos.COL_PRIMARY_KEY) c + FROM %s qsos + GROUP BY qsos.station_id + ) totc + WHERE COALESCE(station_profile.webadifapikey, '') <> '' + AND COALESCE(station_profile.webadifapiurl, '') <> '' + AND station_profile.user_id = %d + "; + $sql=sprintf( + $sql, + $this->config->item('table_name'), + $this->config->item('table_name'), + $this->session->userdata('user_id') + ); + return $this->db->query($sql); + } + /* * Function: are_eqsl_nicks_defined * Description: Returns number of station profiles with eqslnicknames diff --git a/application/views/interface_assets/footer.php b/application/views/interface_assets/footer.php index c66bc8ad..cba5abaa 100644 --- a/application/views/interface_assets/footer.php +++ b/application/views/interface_assets/footer.php @@ -70,7 +70,7 @@ function load_was_map() { -uri->segment(1) == "adif" || $this->uri->segment(1) == "qrz") { ?> +uri->segment(1) == "adif" || $this->uri->segment(1) == "qrz" || $this->uri->segment(1) == "webadif") { ?> @@ -112,7 +112,7 @@ function load_was_map() { console.log("'clicked"); if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition); - } else { + } else { console.log('Geolocation is not supported by this browser.'); } } @@ -363,7 +363,7 @@ $(function () { $(".bootstrap-dialog-message").prepend('
×The stored query has been deleted!
'); $("#query_" + id).remove(); // removes query from table in dialog $("#querydropdown option[value='" + id + "']").remove(); // removes query from dropdown - if ($("#querydropdown option").length == 0) { + if ($("#querydropdown option").length == 0) { $("#btn-edit").remove(); $('.querydropdownform').remove(); }; @@ -549,7 +549,7 @@ function newpath(latlng1, latlng2, locator1, locator2) { var osmUrl='optionslib->get_option('option_map_tile_server');?>'; var osmAttrib='Map data © OpenStreetMap contributors'; - var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 9, attribution: osmAttrib}); + var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 9, attribution: osmAttrib}); var redIcon = L.icon({ iconUrl: icon_dot_url, @@ -602,7 +602,7 @@ function showActivatorsMap(call, count, grids) { var osmUrl='optionslib->get_option('option_map_tile_server');?>'; var osmAttrib='Map data © OpenStreetMap contributors'; - var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 9, attribution: osmAttrib}); + var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 9, attribution: osmAttrib}); map.addLayer(osm); } @@ -730,13 +730,13 @@ function showActivatorsMap(call, count, grids) { }); $(function () { - // hold onto the drop down menu + // hold onto the drop down menu var dropdownMenu; - // and when you show it, move it to the body + // and when you show it, move it to the body $(window).on('show.bs.dropdown', function (e) { - // grab the menu + // grab the menu dropdownMenu = $(e.target).find('.dropdown-menu'); // detach it and append it to the body @@ -753,7 +753,7 @@ function showActivatorsMap(call, count, grids) { }); }); - // and when you hide it, reattach the drop down, and hide it normally + // and when you hide it, reattach the drop down, and hide it normally $(window).on('hide.bs.dropdown', function (e) { $(e.target).append(dropdownMenu.detach()); dropdownMenu.hide(); @@ -882,7 +882,7 @@ $(document).on('keypress',function(e) { uri->segment(1) == "qso") { ?> -load->model('stations'); $active_station_id = $this->stations->find_active(); @@ -1581,6 +1581,9 @@ $(document).ready(function(){ uri->segment(1) == "qrz") { ?> + uri->segment(1) == "webadif") { ?> + + -uri->segment(1) == "qsl") { +uri->segment(1) == "qsl") { // Get Date format if($this->session->userdata('user_date_format')) { // If Logged in and session exists @@ -2050,7 +2053,7 @@ $(document).ready(function(){ case 'M d, Y': $usethisformat = 'MMM D, YYYY';break; case 'M d, y': $usethisformat = 'MMM D, YY';break; } - + ?> @@ -2066,8 +2069,8 @@ $(document).ready(function(){ "scrollX": true, "order": [ 2, 'desc' ], }); - - + + diff --git a/application/views/interface_assets/header.php b/application/views/interface_assets/header.php index 4cb69d2d..23c4fcf4 100644 --- a/application/views/interface_assets/header.php +++ b/application/views/interface_assets/header.php @@ -39,7 +39,7 @@ uri->segment(1) == "adif" || (isset($hasDatePicker) && $hasDatePicker)) { ?> - + '; } ?> @@ -214,7 +214,7 @@ session->userdata('user_id'); ?>" title="Account"> Account Station Logbooks - + Station Locations Bands @@ -256,6 +256,8 @@ $oqrs_requests = $CI->oqrs_model->oqrs_requests($location_list); QRZ Logbook + QO-100 Dx Club Upload + API Keys diff --git a/application/views/webadif/export.php b/application/views/webadif/export.php new file mode 100644 index 00000000..2c07640e --- /dev/null +++ b/application/views/webadif/export.php @@ -0,0 +1,93 @@ + +
+ +

+ +
+
+ + +
+ +
+
+
+

Here you can see and upload all QSOs which have not been previously uploaded to QO-100 Dx Club.

+

You need to set a QO-100 Dx Club API key in your station profile. Only station profiles with an API Key are displayed.

+

WarningThis might take a while as QSO uploads are processed sequentially.

+ +result()) { + echo ' + + + + + + + + + + + '; + foreach ($station_profile->result() as $station) { // Fills the table with the data + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + } + echo '
Profile nameStation callsignTotal QSOs not uploadedTotal QSOs uploadedActions
' . $station->station_profile_name . '' . $station->station_callsign . '' . $station->notcount . '' . $station->totcount . '
'; + + } + else { + echo ''; + } + ?> + +
+
+ +
+ +

Warning If a date range is not selected then all QSOs will be marked!

+

From date:

+
+
+ +
+
+
+
+
+

To date:

+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
diff --git a/application/views/webadif/mark_webadif.php b/application/views/webadif/mark_webadif.php new file mode 100644 index 00000000..8cdd6c0d --- /dev/null +++ b/application/views/webadif/mark_webadif.php @@ -0,0 +1,22 @@ +
+
+ session->flashdata('message')) { ?> + +
+

session->flashdata('message'); ?>

+
+ + +
+
+ QSOs marked +
+
+

Yay, it's done!

+

The QSOs are marked as exported to QO-100 Dx Club.

+
+
+ + +
+ diff --git a/assets/js/sections/webadif.js b/assets/js/sections/webadif.js new file mode 100644 index 00000000..2687d11d --- /dev/null +++ b/assets/js/sections/webadif.js @@ -0,0 +1,70 @@ +$(function () { + $('#datetimepicker5').datetimepicker({ + format: 'DD/MM/YYYY', + }); +}); + +$(function () { + $('#datetimepicker6').datetimepicker({ + format: 'DD/MM/YYYY', + }); +}); + +$(document).ready(function(){ + $('#markWebAdifAsExported').click(function(e){ + let form = $(this).closest('form'); + let station = form.find('select[name=station_profile]'); + if (station.val() == 0) { + station.addClass('is-invalid'); + }else{ + form.submit(); + } + }) +}); + +function ExportWebADIF(station_id) { + if ($(".alert").length > 0) { + $(".alert").remove(); + } + if ($(".errormessages").length > 0) { + $(".errormessages").remove(); + } + $(".ld-ext-right").addClass('running'); + $(".ld-ext-right").prop('disabled', true); + + $.ajax({ + url: base_url + 'index.php/webadif/upload_station', + type: 'post', + data: {'station_id': station_id}, + success: function (data) { + $(".ld-ext-right").removeClass('running'); + $(".ld-ext-right").prop('disabled', false); + if (data.status == 'OK') { + $.each(data.info, function(index, value){ + $('#notcount'+value.station_id).html(value.notcount); + $('#totcount'+value.station_id).html(value.totcount); + }); + $(".card-body").append(''); + } + else { + $(".card-body").append(''); + } + + if (data.errormessages.length > 0) { + $(".card-body").append('' + + '

\n' + + ' \n' + + '

\n' + + '
\n' + + '
\n' + + '
\n' + + '
'); + $.each(data.errormessages, function(index, value) { + $(".errors").append('
  • ' + value); + }); + } + } + }); +}