diff --git a/.htaccess.sample b/.htaccess.sample index 435eea60..f766ea9f 100644 --- a/.htaccess.sample +++ b/.htaccess.sample @@ -10,3 +10,5 @@ RewriteRule ^(.*)$ /index.php?/$1 "[L,QSA,B= ?,BNP]" RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ /index.php?/$1 "[L,QSA,B= ?,BNP]" + +RedirectMatch 404 ^/\.git diff --git a/application/config/migration.php b/application/config/migration.php index 55613c99..7c4aa6b1 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'] = 124; +$config['migration_version'] = 128; /* |-------------------------------------------------------------------------- diff --git a/application/controllers/Adif.php b/application/controllers/Adif.php index 5ebe2826..901d83b7 100644 --- a/application/controllers/Adif.php +++ b/application/controllers/Adif.php @@ -206,7 +206,7 @@ class adif extends CI_Controller { $custom_errors .= $this->logbook_model->import($record, $this->input->post('station_profile'), - $this->input->post('skipDuplicate'), $this->input->post('markLotw'), $this->input->post('dxccAdif'), $this->input->post('markQrz'), true, $this->input->post('operatorName')); + $this->input->post('skipDuplicate'), $this->input->post('markLotw'), $this->input->post('dxccAdif'), $this->input->post('markQrz'), $this->input->post('markHrd'), true, $this->input->post('operatorName')); }; diff --git a/application/controllers/Api.php b/application/controllers/Api.php index 2eaf99a7..fc2211f8 100644 --- a/application/controllers/Api.php +++ b/application/controllers/Api.php @@ -5,38 +5,7 @@ class API extends CI_Controller { // Do absolutely nothing function index() { - } - - /* - TODOs - - Search Callsign (Return Json) - - Add QSO return json - */ - - - function search_callsign($callsign) { - $this->db->select('COL_PRIMARY_KEY, COL_CALL, COL_MODE, COL_SUBMODE, COL_BAND, COL_COUNTRY, COL_FREQ, COL_GRIDSQUARE, COL_RST_RCVD, COL_RST_SENT, COL_SAT_MODE, COL_SAT_NAME'); - //$this->db->select("DATE_FORMAT(COL_TIME_ON, '%H:%i') AS time_on", FALSE ); - //$this->db->select("DATE_FORMAT(COL_TIME_ON, '%d/%c/%Y') AS date_on", FALSE ); - $this->db->like('COL_CALL', $callsign); - $this->db->or_like('COL_GRIDSQUARE', $callsign); - $query = $this->db->get($this->config->item('table_name')); - - - $results = array(); - - foreach ($query->result() as $result) - { - $results[] = $result; - } - - header('Content-type: application/json'); - - //$arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5); - echo $_GET['jsoncallback'].'('.json_encode($results).')'; //assign resulting code to $_GET['jsoncallback]. - - //echo json_encode($results); - + echo "nothing to see"; } function help() @@ -158,6 +127,30 @@ class API extends CI_Controller { } } + function station_info($key) { + $this->load->model('api_model'); + $this->load->model('stations'); + header("Content-type: application/json"); + if(substr($this->api_model->access($key),0,1) == 'r') { /* Checkpermission for _r_eading */ + $this->api_model->update_last_used($key); + $userid = $this->api_model->key_userid($key); + $station_ids = array(); + $stations=$this->stations->all_of_user($userid); + foreach ($stations->result() as $row) { + $result['station_id']=$row->station_id; + $result['station_profile_name']=$row->station_profile_name; + $result['station_gridsquare']=$row->station_gridsquare; + $result['station_callsign']=$row->station_callsign;; + $result['station_active']=$row->station_active; + array_push($station_ids, $result); + } + echo json_encode($station_ids); + } else { + http_response_code(401); + echo json_encode(['status' => 'failed', 'reason' => "missing or invalid api key"]); + } + } + // FUNCTION: search() // Handle search requests /* @@ -468,9 +461,9 @@ class API extends CI_Controller { if(isset($obj['station_profile_id'])) { - $this->logbook_model->import($record, $obj['station_profile_id'], NULL, NULL, NULL, NULL, false, false, true); + $this->logbook_model->import($record, $obj['station_profile_id'], NULL, NULL, NULL, NULL, NULL, false, false, true); } else { - $this->logbook_model->import($record, 0, NULL, NULL, NULL, NULL, false, false, true); + $this->logbook_model->import($record, 0, NULL, NULL, NULL, NULL, NULL, false, false, true); } }; diff --git a/application/controllers/Eqsl.php b/application/controllers/Eqsl.php index 642e6fa5..b18cf0b8 100644 --- a/application/controllers/Eqsl.php +++ b/application/controllers/Eqsl.php @@ -15,6 +15,7 @@ class eqsl extends CI_Controller { $folder_name = "images/eqsl_card_images"; $data['storage_used'] = $this->sizeFormat($this->folderSize($folder_name)); + // Render Page $data['page_title'] = "eQSL Cards"; @@ -29,6 +30,12 @@ class eqsl extends CI_Controller { $this->load->model('user_model'); if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); } + $this->load->model('stations'); + $data['station_profile'] = $this->stations->all_of_user(); + $active_station_id = $this->stations->find_active(); + $station_profile = $this->stations->profile($active_station_id); + $data['active_station_info'] = $station_profile->row(); + // Check if eQSL Nicknames have been defined $this->load->model('eqslmethods_model'); $eqsl_locations = $this->eqslmethods_model->all_of_user_with_eqsl_nick_defined(); @@ -71,29 +78,39 @@ class eqsl extends CI_Controller { $eqsl_results[] = $this->eqslimporter->fetch($eqsl_password); } - } - else - { - if ( ! $this->upload->do_upload()) - { - $data['page_title'] = "eQSL Import"; - $data['error'] = $this->upload->display_errors(); + } elseif ($this->input->post('eqslimport') == 'upload') { + $station_id4upload=$this->input->post('station_profile'); + if ($this->stations->check_station_is_accessible($station_id4upload)) { + $station_callsign=$this->stations->profile($station_id4upload)->row()->station_callsign; + if ( ! $this->upload->do_upload()) + { + $data['page_title'] = "eQSL Import"; + $data['error'] = $this->upload->display_errors(); - $this->load->view('interface_assets/header', $data); - $this->load->view('eqsl/import'); - $this->load->view('interface_assets/footer'); + $this->load->view('interface_assets/header', $data); + $this->load->view('eqsl/import'); + $this->load->view('interface_assets/footer'); - return; + return; + } else { + $data = array('upload_data' => $this->upload->data()); + + $this->load->library('EqslImporter'); + $this->eqslimporter->from_file('./uploads/'.$data['upload_data']['file_name'],$station_callsign); + + $eqsl_results[] = $this->eqslimporter->import(); + } + } else { + log_message('error',$station_id4upload." is not valid for user!"); } - else - { - $data = array('upload_data' => $this->upload->data()); + } else { + $data['page_title'] = "eQSL Import"; - $this->load->library('EqslImporter'); - $this->eqslimporter->from_file('./uploads/'.$data['upload_data']['file_name']); + $this->load->view('interface_assets/header', $data); + $this->load->view('eqsl/import'); + $this->load->view('interface_assets/footer'); - $eqsl_results[] = $this->eqslimporter->import(); - } + return; } $data['eqsl_results'] = $eqsl_results; diff --git a/application/controllers/Gridmap.php b/application/controllers/Gridmap.php index d4e32e6a..cc28c06e 100644 --- a/application/controllers/Gridmap.php +++ b/application/controllers/Gridmap.php @@ -11,11 +11,17 @@ class Gridmap extends CI_Controller { $this->load->model('bands'); $this->load->model('gridmap_model'); + $this->load->model('stations'); + + $data['homegrid'] = explode(',', $this->stations->find_gridsquare()); $data['modes'] = $this->gridmap_model->get_worked_modes(); $data['bands'] = $this->bands->get_worked_bands(); $data['sats_available'] = $this->bands->get_worked_sats(); + $data['user_gridmap_default_band'] = $this->session->userdata('user_gridmap_default_band'); + $data['user_gridmap_confirmation'] = $this->session->userdata('user_gridmap_confirmation'); + $data['layer'] = $this->optionslib->get_option('option_map_tile_server'); $data['attribution'] = $this->optionslib->get_option('option_map_tile_server_copyright'); @@ -27,6 +33,7 @@ class Gridmap extends CI_Controller { $footerData = []; $footerData['scripts'] = [ + 'assets/js/leaflet/geocoding.js', 'assets/js/leaflet/L.MaidenheadColouredGridMap.js', 'assets/js/sections/gridmap.js?' ]; @@ -175,4 +182,4 @@ class Gridmap extends CI_Controller { header('Content-Type: application/json'); echo json_encode($data); } -} \ No newline at end of file +} diff --git a/application/controllers/Hrdlog.php b/application/controllers/Hrdlog.php new file mode 100644 index 00000000..eca9ef47 --- /dev/null +++ b/application/controllers/Hrdlog.php @@ -0,0 +1,171 @@ +setOptions(); + + $this->load->model('logbook_model'); + + $station_ids = $this->logbook_model->get_station_id_with_hrdlog_code(); + + if ($station_ids) { + foreach ($station_ids as $station) { + $hrdlog_code = $station->hrdlog_code; + if($this->mass_upload_qsos($station->station_id, $hrdlog_code)) { + echo "QSOs have been uploaded to hrdlog.net."; + log_message('info', 'QSOs have been uploaded to hrdlog.net.'); + } else{ + echo "No QSOs found for upload."; + log_message('info', 'No QSOs found for upload.'); + } + } + } else { + echo "No station profiles with a hrdlog Code found."; + log_message('error', "No station profiles with a hrdlog Code 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 hrdlog. + * Adif is build for each qso, and then uploaded, one at a time + */ + function mass_upload_qsos($station_id, $hrdlog_code) { + $i = 0; + $data['qsos'] = $this->logbook_model->get_hrdlog_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); + + if ($qso->COL_HRDLOG_QSO_UPLOAD_STATUS == 'M') { + $result = $this->logbook_model->push_qso_to_hrdlog($hrdlog_code, $qso->COL_STATION_CALLSIGN,$adif, true); + } else { + $result = $this->logbook_model->push_qso_to_hrdlog($hrdlog_code, $qso->COL_STATION_CALLSIGN,$adif); + } + + if ( ($result['status'] == 'OK') || ( ($result['status'] == 'error') || ($result['status'] == 'duplicate')) ){ + $this->markqso($qso->COL_PRIMARY_KEY); + $i++; + } elseif ((substr($result['status'],0,11) == 'auth_error')) { + log_message('error', 'hrdlog upload failed for qso: Call: ' . $qso->COL_CALL . ' Band: ' . $qso->COL_BAND . ' Mode: ' . $qso->COL_MODE . ' Time: ' . $qso->COL_TIME_ON); + log_message('error', 'hrdlog upload failed with the following message: ' .$result['message']); + log_message('error', 'hrdlog upload stopped for Station_ID: ' .$station_id); + $errormessages[] = $result['message'] . 'Invalid HRDLog-Code, stopped at Call: ' . $qso->COL_CALL . ' Band: ' . $qso->COL_BAND . ' Mode: ' . $qso->COL_MODE . ' Time: ' . $qso->COL_TIME_ON; + break; /* If key is invalid, immediate stop syncing for more QSOs of this station */ + } else { + log_message('error', 'hrdlog upload failed for qso: Call: ' . $qso->COL_CALL . ' Band: ' . $qso->COL_BAND . ' Mode: ' . $qso->COL_MODE . ' Time: ' . $qso->COL_TIME_ON); + log_message('error', 'hrdlog upload failed with the following message: ' .$result['message']); + $errormessages[] = $result['message'] . ' Call: ' . $qso->COL_CALL . ' Band: ' . $qso->COL_BAND . ' Mode: ' . $qso->COL_MODE . ' Time: ' . $qso->COL_TIME_ON; + } + } + $result['status'] = 'OK'; + $result['count'] = $i; + $result['errormessages'] = $errormessages; + return $result; + } else { + $result['status'] = 'Error'; + $result['count'] = $i; + $result['errormessages'] = $errormessages; + return $result; + } + } + + /* + * Function marks QSO with given primarykey as uploaded to hrdlog + */ + function markqso($primarykey) { + $this->logbook_model->mark_hrdlog_qsos_sent($primarykey); + } + + /* + * Used for displaying the uid for manually selecting log for upload to hrdlog + */ + public function export() { + $this->load->model('stations'); + + $data['page_title'] = "HRDlog.net Logbook"; + + $data['station_profiles'] = $this->stations->all_of_user(); + $data['station_profile'] = $this->stations->stations_with_hrdlog_code(); + + $this->load->view('interface_assets/header', $data); + $this->load->view('hrdlog/export'); + $this->load->view('interface_assets/footer'); + } + + /* + * Used for ajax-function when selecting log for upload to hrdlog + */ + public function upload_station() { + $this->setOptions(); + $this->load->model('stations'); + + $postData = $this->input->post(); + + $this->load->model('logbook_model'); + $result = $this->logbook_model->exists_hrdlog_code($postData['station_id']); + $hrdlog_code = $result->hrdlog_code; + header('Content-type: application/json'); + $result = $this->mass_upload_qsos($postData['station_id'], $hrdlog_code); + if ($result['status'] == 'OK') { + $stationinfo = $this->stations->stations_with_hrdlog_code(); + $info = $stationinfo->result(); + + $data['status'] = 'OK'; + $data['info'] = $info; + $data['infomessage'] = $result['count'] . " QSOs are now uploaded to hrdlog"; + $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_hrdlog() { + // Set memory limit to unlimited to allow heavy usage + ini_set('memory_limit', '-1'); + + $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'); + + foreach ($data['qsos']->result() as $qso) + { + $this->logbook_model->mark_hrdlog_qsos_sent($qso->COL_PRIMARY_KEY); + } + + $this->load->view('interface_assets/header', $data); + $this->load->view('hrdlog/mark_hrdlog', $data); + $this->load->view('interface_assets/footer'); + } +} diff --git a/application/controllers/Labels.php b/application/controllers/Labels.php index 628b4dcd..9b813de0 100644 --- a/application/controllers/Labels.php +++ b/application/controllers/Labels.php @@ -87,22 +87,27 @@ class Labels extends CI_Controller { } + public function printids() { + $ids = xss_clean(json_decode($this->input->post('id'))); + $this->load->model('labels_model'); + $result = $this->labels_model->export_printrequestedids($ids); + + $this->prepareLabel($result, true); + } + public function print($station_id) { $clean_id = xss_clean($station_id); $this->load->model('labels_model'); $result = $this->labels_model->export_printrequested($clean_id); + $this->prepareLabel($result); + } + + function prepareLabel($qsos, $jscall = false) { + $this->load->model('labels_model'); $label = $this->labels_model->getDefaultLabel(); - - // require_once('fpdf.php'); - // require('PDF_Label.php'); - // require_once APPPATH."/src/Label/PDF_Label.php"; - // require_once APPPATH."/src/Label/fpdf.php"; - - // Example of custom format - // $pdf = new PDF_Label(array('paper-size'=>'A4', 'metric'=>'mm', 'marginLeft'=>1, 'marginTop'=>1, 'NX'=>2, 'NY'=>7, 'SpaceX'=>0, 'SpaceY'=>0, 'width'=>99, 'height'=>38, 'font-size'=>14)); - + try { if ($label) { $pdf = new PDF_Label(array( @@ -119,17 +124,29 @@ class Labels extends CI_Controller { 'font-size' => $label->font_size )); } else { - $this->session->set_flashdata('error', 'You need to create a label and set it to be used for print.'); - redirect('labels'); + if ($jscall) { + header('Content-Type: application/json'); + echo json_encode(array('message' => 'You need to create a label and set it to be used for print.')); + return; + } else { + $this->session->set_flashdata('error', 'You need to create a label and set it to be used for print.'); + redirect('labels'); + } } } catch (\Throwable $th) { - $this->session->set_flashdata('error', 'Something went wrong! The label could not be generated. Check label size and font size.'); - redirect('labels'); + if ($jscall) { + header('Content-Type: application/json'); + echo json_encode(array('message' => 'Something went wrong! The label could not be generated. Check label size and font size.')); + return; + } else { + $this->session->set_flashdata('error', 'Something went wrong! The label could not be generated. Check label size and font size.'); + redirect('labels'); + } } define('FPDF_FONTPATH', './src/Label/font/'); - + $pdf->AddPage(); - + if ($label->font == 'DejaVuSans') { $pdf->AddFont($label->font,'','DejaVuSansMono.ttf',true); $pdf->SetFont($label->font); @@ -137,13 +154,12 @@ class Labels extends CI_Controller { $pdf->AddFont($label->font); $pdf->SetFont($label->font); } - - - if ($result->num_rows() > 0) { + + if ($qsos->num_rows() > 0) { if ($label->qsos == 1) { - $this->makeOneQsoLabel($result->result(), $pdf); + $this->makeOneQsoLabel($qsos->result(), $pdf); } else { - $this->makeMultiQsoLabel($result->result(), $pdf, $label->qsos); + $this->makeMultiQsoLabel($qsos->result(), $pdf, $label->qsos); } } else { $this->session->set_flashdata('message', '0 QSOs found for print!'); diff --git a/application/controllers/Logbook.php b/application/controllers/Logbook.php index d1d797e2..6c5d7675 100644 --- a/application/controllers/Logbook.php +++ b/application/controllers/Logbook.php @@ -772,7 +772,7 @@ class Logbook extends CI_Controller { function querydb($id) { $this->db->from($this->config->item('table_name')); $this->db->join('station_profile', 'station_profile.station_id = '.$this->config->item('table_name').'.station_id'); - $this->db->join('dxcc_entities', 'dxcc_entities.adif = '.$this->config->item('table_name').'.COL_DXCC'); + $this->db->join('dxcc_entities', 'dxcc_entities.adif = '.$this->config->item('table_name').'.COL_DXCC', 'left outer'); $this->db->join('lotw_users', 'lotw_users.callsign = '.$this->config->item('table_name').'.col_call', 'left outer'); $this->db->group_start(); $this->db->like(''.$this->config->item('table_name').'.COL_CALL', $id); diff --git a/application/controllers/Logbookadvanced.php b/application/controllers/Logbookadvanced.php index 19daff37..384889f3 100644 --- a/application/controllers/Logbookadvanced.php +++ b/application/controllers/Logbookadvanced.php @@ -1,4 +1,4 @@ -logbook_model->fetchDxcc(); $pageData['iotaarray'] = $this->logbook_model->fetchIota(); $pageData['sats'] = $this->bands->get_worked_sats(); - + $pageData['bands'] = $this->bands->get_worked_bands(); - $CI =& get_instance(); + $CI =& get_instance(); // Get Date format if($CI->session->userdata('user_date_format')) { // If Logged in and session exists @@ -104,8 +104,17 @@ class Logbookadvanced extends CI_Controller { 'propmode' => xss_clean($this->input->post('propmode')), 'gridsquare' => xss_clean($this->input->post('gridsquare')), 'state' => xss_clean($this->input->post('state')), + 'cqzone' => xss_clean($this->input->post('cqzone')), 'qsoresults' => xss_clean($this->input->post('qsoresults')), 'sats' => xss_clean($this->input->post('sats')), + 'lotwSent' => xss_clean($this->input->post('lotwSent')), + 'lotwReceived' => xss_clean($this->input->post('lotwReceived')), + 'eqslSent' => xss_clean($this->input->post('eqslSent')), + 'eqslReceived' => xss_clean($this->input->post('eqslReceived')), + 'qslvia' => xss_clean($this->input->post('qslvia')), + 'sota' => xss_clean($this->input->post('sota')), + 'pota' => xss_clean($this->input->post('pota')), + 'wwff' => xss_clean($this->input->post('wwff')), ); $qsos = []; @@ -170,7 +179,7 @@ class Logbookadvanced extends CI_Controller { $data = $this->logbookadvanced_model->getQsosForAdif($ids, $user_id); $results = $data->result('array'); - + $qsos = []; foreach ($results as $data) { $qsos[] = new QSO($data); @@ -184,4 +193,32 @@ class Logbookadvanced extends CI_Controller { header("Content-Type: application/json"); print json_encode($q); } -} \ No newline at end of file + + function update_qsl_received() { + $this->load->model('logbookadvanced_model'); + + $ids = xss_clean($this->input->post('id')); + $user_id = (int)$this->session->userdata('user_id'); + $method = xss_clean($this->input->post('method')); + $sent = xss_clean($this->input->post('sent')); + + $status = $this->logbookadvanced_model->updateQslReceived($ids, $user_id, $method, $sent); + + $data = $this->logbookadvanced_model->getQsosForAdif($ids, $user_id); + + $results = $data->result('array'); + + $qsos = []; + foreach ($results as $data) { + $qsos[] = new QSO($data); + } + + $q = []; + foreach ($qsos as $qso) { + $q[] = $qso->toArray(); + } + + header("Content-Type: application/json"); + print json_encode($q); + } +} diff --git a/application/controllers/Lookup.php b/application/controllers/Lookup.php index 04c2ebcd..5e74dfed 100644 --- a/application/controllers/Lookup.php +++ b/application/controllers/Lookup.php @@ -53,10 +53,9 @@ class Lookup extends CI_Controller { $this->load->view('lookup/result', $data); } - public function scp($call) { - - if($call) { - $uppercase_callsign = strtoupper($call); + public function scp() { + if($_POST['callsign']) { + $uppercase_callsign = strtoupper($_POST['callsign']); } // SCP results from logbook diff --git a/application/controllers/Lotw.php b/application/controllers/Lotw.php index eb00dd44..efe12138 100644 --- a/application/controllers/Lotw.php +++ b/application/controllers/Lotw.php @@ -475,6 +475,7 @@ class Lotw extends CI_Controller { $tableheaders .= "IOTA"; $tableheaders .= "Log Status"; $tableheaders .= "LoTW Status"; + $tableheaders .= "Station ID"; $tableheaders .= ""; $table = ""; @@ -497,7 +498,7 @@ class Lotw extends CI_Controller { $record['qsl_rcvd'] = $config['lotw_rcvd_mark']; } - $status = $this->logbook_model->import_check($time_on, $record['call'], $record['band']); + $status = $this->logbook_model->import_check($time_on, $record['call'], $record['band'], $record['mode'], $record['station_callsign']); $skipNewQso = $this->input->post('importMissing'); // If import missing was checked if($status[0] == "No Match" && $skipNewQso != NULL) { @@ -505,7 +506,7 @@ class Lotw extends CI_Controller { $station_id = $this->logbook_model->find_correct_station_id($record['station_callsign'], $record['my_gridsquare']); if ($station_id != NULL) { - $result = $this->logbook_model->import($record, $station_id, NULL, TRUE, NULL, NULL, true, false); // Create the Entry + $result = $this->logbook_model->import($record, $station_id, NULL, TRUE, NULL, NULL, NULL, true, false); // Create the Entry if ($result == "") { $lotw_status = 'QSO imported'; } else { @@ -550,7 +551,12 @@ class Lotw extends CI_Controller { $ituz = ""; } - $lotw_status = $this->logbook_model->lotw_update($time_on, $record['call'], $record['band'], $qsl_date, $record['qsl_rcvd'], $state, $qsl_gridsquare, $iota, $cnty, $cqz, $ituz); + $station_id = $this->logbook_model->find_correct_station_id($record['station_callsign'], $record['my_gridsquare']); + if ($station_id != NULL) { + $lotw_status = $this->logbook_model->lotw_update($time_on, $record['call'], $record['band'], $qsl_date, $record['qsl_rcvd'], $state, $qsl_gridsquare, $iota, $cnty, $cqz, $ituz, $station_id); + } else { + $lotw_status = "No matching Grid/OP-Call (check Locations)"; + } } @@ -566,6 +572,7 @@ class Lotw extends CI_Controller { $table .= "".$iota.""; $table .= "QSO Record: ".$status[0].""; $table .= "LoTW Record: ".$lotw_status.""; + $table .= "".$station_id.""; $table .= ""; } diff --git a/application/controllers/Qrz.php b/application/controllers/Qrz.php index 13d35421..68eb29db 100644 --- a/application/controllers/Qrz.php +++ b/application/controllers/Qrz.php @@ -71,9 +71,15 @@ class Qrz extends CI_Controller { $result = $this->logbook_model->push_qso_to_qrz($qrz_api_key, $adif); } - if ($result['status'] == 'OK') { + if ( ($result['status'] == 'OK') || ( ($result['status'] == 'error') && ($result['message'] == 'STATUS=FAIL&REASON=Unable to add QSO to database: duplicate&EXTENDED=')) ){ $this->markqso($qso->COL_PRIMARY_KEY); $i++; + } elseif ( ($result['status']=='error') && (substr($result['message'],0,11) == 'STATUS=AUTH')) { + log_message('error', 'QRZ upload failed for qso: Call: ' . $qso->COL_CALL . ' Band: ' . $qso->COL_BAND . ' Mode: ' . $qso->COL_MODE . ' Time: ' . $qso->COL_TIME_ON); + log_message('error', 'QRZ upload failed with the following message: ' .$result['message']); + log_message('error', 'QRZ upload stopped for Station_ID: ' .$station_id); + $errormessages[] = $result['message'] . ' Call: ' . $qso->COL_CALL . ' Band: ' . $qso->COL_BAND . ' Mode: ' . $qso->COL_MODE . ' Time: ' . $qso->COL_TIME_ON; + break; /* If key is invalid, immediate stop syncing for more QSOs of this station */ } else { log_message('error', 'QRZ upload failed for qso: Call: ' . $qso->COL_CALL . ' Band: ' . $qso->COL_BAND . ' Mode: ' . $qso->COL_MODE . ' Time: ' . $qso->COL_TIME_ON); log_message('error', 'QRZ upload failed with the following message: ' .$result['message']); diff --git a/application/controllers/Qsl.php b/application/controllers/Qsl.php index 2602fa78..89df8947 100644 --- a/application/controllers/Qsl.php +++ b/application/controllers/Qsl.php @@ -66,11 +66,15 @@ class Qsl extends CI_Controller { if (isset($_FILES['qslcardfront']) && $_FILES['qslcardfront']['name'] != "" && $_FILES['qslcardfront']['error'] == 0) { $result['front'] = $this->uploadQslCardFront($qsoid); + } else { + $result['front']['status'] = ''; } if (isset($_FILES['qslcardback']) && $_FILES['qslcardback']['name'] != "" && $_FILES['qslcardback']['error'] == 0) { $result['back'] = $this->uploadQslCardBack($qsoid); + } else { + $result['back']['status'] = ''; } header("Content-type: application/json"); @@ -170,6 +174,13 @@ class Qsl extends CI_Controller { echo json_encode($result); } + function viewQsl() { + $cleanid = $this->security->xss_clean($this->input->post('id')); + $this->load->model('Qsl_model'); + $data['qslimages'] = $this->Qsl_model->getQslForQsoId($cleanid); + $this->load->view('qslcard/qslcarousel', $data); + } + } // Functions for storage, these need shifted to a libary to use across Cloudlog diff --git a/application/controllers/Radio.php b/application/controllers/Radio.php index 491d98c3..a276f0fb 100755 --- a/application/controllers/Radio.php +++ b/application/controllers/Radio.php @@ -78,82 +78,95 @@ } - function json($id) - { + function json($id) { - header('Content-Type: application/json'); + $this->load->model('user_model'); - $this->load->model('cat'); + // Check if users logged in - $query = $this->cat->radio_status($id); + if($this->user_model->validate_session() == 0) { + // user is not logged in + // Return Json data + header('Content-Type: application/json'); + echo json_encode(array( + "error" => "not_logged_in" + ), JSON_PRETTY_PRINT); + } else { - if ($query->num_rows() > 0) - { - foreach ($query->result() as $row) + header('Content-Type: application/json'); + + $this->load->model('cat'); + + $query = $this->cat->radio_status($id); + + if ($query->num_rows() > 0) { + foreach ($query->result() as $row) + { - $frequency = $row->frequency; + $frequency = $row->frequency; - $frequency_rx = $row->frequency_rx; + $frequency_rx = $row->frequency_rx; - $power = $row->power; + $power = $row->power; - $prop_mode = $row->prop_mode; + $prop_mode = $row->prop_mode; - // Check Mode - $mode = strtoupper($row->mode); - if ($mode == "FMN") { - $mode = "FM"; - } - - if ($row->prop_mode == "SAT") { - // Get Satellite Name - if ($row->sat_name == "AO-07") { - $sat_name = "AO-7"; - } elseif ($row->sat_name == "LILACSAT") { - $sat_name = "CAS-3H"; - } else { - $sat_name = strtoupper($row->sat_name); + // Check Mode + $mode = strtoupper($row->mode); + if ($mode == "FMN") { + $mode = "FM"; } - // Get Satellite Mode - $sat_mode_uplink = $this->get_mode_designator($row->frequency); - $sat_mode_downlink = $this->get_mode_designator($row->frequency_rx); + if ($row->prop_mode == "SAT") { + // Get Satellite Name + if ($row->sat_name == "AO-07") { + $sat_name = "AO-7"; + } elseif ($row->sat_name == "LILACSAT") { + $sat_name = "CAS-3H"; + } else { + $sat_name = strtoupper($row->sat_name); + } - if (empty($sat_mode_uplink)) { + // Get Satellite Mode + $sat_mode_uplink = $this->get_mode_designator($row->frequency); + $sat_mode_downlink = $this->get_mode_designator($row->frequency_rx); + + if (empty($sat_mode_uplink)) { + $sat_mode = ""; + } elseif ($sat_mode_uplink !== $sat_mode_downlink) { + $sat_mode = $sat_mode_uplink."/".$sat_mode_downlink; + } else { + $sat_mode = $sat_mode_uplink; + } + } else { + $sat_name = ""; $sat_mode = ""; - } elseif ($sat_mode_uplink !== $sat_mode_downlink) { - $sat_mode = $sat_mode_uplink."/".$sat_mode_downlink; - } else { - $sat_mode = $sat_mode_uplink; } - } else { - $sat_name = ""; - $sat_mode = ""; + + // Calculate how old the data is in minutes + $datetime1 = new DateTime("now", new DateTimeZone('UTC')); // Today's Date/Time + $datetime2 = new DateTime($row->timestamp, new DateTimeZone('UTC')); + $interval = $datetime1->diff($datetime2); + + $minutes = $interval->days * 24 * 60; + $minutes += $interval->h * 60; + $minutes += $interval->i; + + $updated_at = $minutes; + + // Return Json data + echo json_encode(array( + "frequency" => $frequency, + "frequency_rx" => $frequency_rx, + "mode" => $mode, + "satmode" => $sat_mode, + "satname" => $sat_name, + "power" => $power, + "prop_mode" => $prop_mode, + "updated_minutes_ago" => $updated_at, + ), JSON_PRETTY_PRINT); } - - // Calculate how old the data is in minutes - $datetime1 = new DateTime("now", new DateTimeZone('UTC')); // Today's Date/Time - $datetime2 = new DateTime($row->timestamp, new DateTimeZone('UTC')); - $interval = $datetime1->diff($datetime2); - - $minutes = $interval->days * 24 * 60; - $minutes += $interval->h * 60; - $minutes += $interval->i; - - $updated_at = $minutes; - - // Return Json data - echo json_encode(array( - "frequency" => $frequency, - "frequency_rx" => $frequency_rx, - "mode" => $mode, - "satmode" => $sat_mode, - "satname" => $sat_name, - "power" => $power, - "prop_mode" => $prop_mode, - "updated_minutes_ago" => $updated_at, - ), JSON_PRETTY_PRINT); } } } diff --git a/application/controllers/Update.php b/application/controllers/Update.php index 59c914de..cd56804c 100644 --- a/application/controllers/Update.php +++ b/application/controllers/Update.php @@ -189,7 +189,7 @@ class Update extends CI_Controller { gzclose($gz); if (file_put_contents($this->make_update_path("cty.xml"), $data) === FALSE) { - $this->update_status("FAILED: Could not write to LoTW users file"); + $this->update_status("FAILED: Could not write to cty.xml file"); return; } diff --git a/application/controllers/User.php b/application/controllers/User.php index 2d89e0ad..69f43a89 100644 --- a/application/controllers/User.php +++ b/application/controllers/User.php @@ -33,6 +33,7 @@ class User extends CI_Controller { $this->load->model('user_model'); if(!$this->user_model->authorize(99)) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); } + $this->load->model('bands'); $this->load->library('form_validation'); $this->form_validation->set_rules('user_name', 'Username', 'required'); @@ -46,6 +47,8 @@ class User extends CI_Controller { $this->form_validation->set_rules('user_locator', 'Locator', 'callback_check_locator'); $this->form_validation->set_rules('user_timezone', 'Timezone', 'required'); + $data['bands'] = $this->bands->get_user_bands(); + // Get themes list $data['themes'] = $this->user_model->getThemes(); @@ -69,8 +72,8 @@ class User extends CI_Controller { $data['user_callsign'] = $this->input->post('user_callsign'); $data['user_locator'] = $this->input->post('user_locator'); $data['user_timezone'] = $this->input->post('user_timezone'); - $data['user_measurement_base'] = $this->input->post('user_measurement_base'); - $data['user_stylesheet'] = $this->input->post('user_stylesheet'); + $data['user_measurement_base'] = $this->input->post('user_measurement_base'); + $data['user_stylesheet'] = $this->input->post('user_stylesheet'); $data['user_qth_lookup'] = $this->input->post('user_qth_lookup'); $data['user_sota_lookup'] = $this->input->post('user_sota_lookup'); $data['user_wwff_lookup'] = $this->input->post('user_wwff_lookup'); @@ -84,6 +87,9 @@ class User extends CI_Controller { $data['user_show_profile_image'] = $this->input->post('user_show_profile_image'); $data['user_previous_qsl_type'] = $this->input->post('user_previous_qsl_type'); $data['user_amsat_status_upload'] = $this->input->post('user_amsat_status_upload'); + $data['user_mastodon_url'] = $this->input->post('user_mastodon_url'); + $data['user_gridmap_default_band'] = $this->input->post('user_gridmap_default_band'); + $data['user_gridmap_confirmation'] = ($this->input->post('user_gridmap_confirmation_qsl') !== null ? 'Q' : '').($this->input->post('user_gridmap_confirmation_lotw') !== null ? 'L' : '').($this->input->post('user_gridmap_confirmation_eqsl') !== null ? 'E' : ''); $this->load->view('user/add', $data); } else { $this->load->view('user/add', $data); @@ -116,7 +122,10 @@ class User extends CI_Controller { $this->input->post('user_column5'), $this->input->post('user_show_profile_image'), $this->input->post('user_previous_qsl_type'), - $this->input->post('user_amsat_status_upload'))) { + $this->input->post('user_amsat_status_upload'), + $this->input->post('user_mastodon_url'), + $this->input->post('user_gridmap_default_band'), + ($this->input->post('user_gridmap_confirmation_qsl') !== null ? 'Q' : '').($this->input->post('user_gridmap_confirmation_lotw') !== null ? 'L' : '').($this->input->post('user_gridmap_confirmation_eqsl') !== null ? 'E' : ''))) { // Check for errors case EUSERNAMEEXISTS: $data['username_error'] = 'Username '.$this->input->post('user_name').' already in use!'; @@ -144,8 +153,8 @@ class User extends CI_Controller { $data['user_lastname'] = $this->input->post('user_lastname'); $data['user_callsign'] = $this->input->post('user_callsign'); $data['user_locator'] = $this->input->post('user_locator'); - $data['user_measurement_base'] = $this->input->post('user_measurement_base'); - $data['user_stylesheet'] = $this->input->post('user_stylesheet'); + $data['user_measurement_base'] = $this->input->post('user_measurement_base'); + $data['user_stylesheet'] = $this->input->post('user_stylesheet'); $data['user_qth_lookup'] = $this->input->post('user_qth_lookup'); $data['user_sota_lookup'] = $this->input->post('user_sota_lookup'); $data['user_wwff_lookup'] = $this->input->post('user_wwff_lookup'); @@ -159,6 +168,9 @@ class User extends CI_Controller { $data['user_show_profile_image'] = $this->input->post('user_show_profile_image'); $data['user_previous_qsl_type'] = $this->input->post('user_previous_qsl_type'); $data['user_amsat_status_upload'] = $this->input->post('user_amsat_status_upload'); + $data['user_mastodon_url'] = $this->input->post('user_mastodon_url'); + $data['user_gridmap_default_band'] = $this->input->post('user_gridmap_default_band'); + $data['user_gridmap_confirmation'] = ($this->input->post('user_gridmap_confirmation_qsl') !== null ? 'Q' : '').($this->input->post('user_gridmap_confirmation_lotw') !== null ? 'L' : '').($this->input->post('user_gridmap_confirmation_eqsl') !== null ? 'E' : ''); $this->load->view('user/add', $data); $this->load->view('interface_assets/footer'); } @@ -169,6 +181,7 @@ class User extends CI_Controller { if((!$this->user_model->authorize(99)) && ($this->session->userdata('user_id') != $this->uri->segment(3))) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); } $query = $this->user_model->get_by_id($this->uri->segment(3)); + $this->load->model('bands'); $this->load->library('form_validation'); $this->form_validation->set_rules('user_name', 'Username', 'required|xss_clean'); @@ -183,6 +196,8 @@ class User extends CI_Controller { $this->form_validation->set_rules('user_locator', 'Locator', 'callback_check_locator'); $this->form_validation->set_rules('user_timezone', 'Timezone', 'required'); + $data['bands'] = $this->bands->get_user_bands(); + // Get themes list $data['themes'] = $this->user_model->getThemes(); @@ -300,23 +315,23 @@ class User extends CI_Controller { $data['user_eqsl_password'] = $q->user_eqsl_password; } - if($this->input->post('user_measurement_base')) { - $data['user_measurement_base'] = $this->input->post('user_measurement_base', true); - } else { - $data['user_measurement_base'] = $q->user_measurement_base; - } + if($this->input->post('user_measurement_base')) { + $data['user_measurement_base'] = $this->input->post('user_measurement_base', true); + } else { + $data['user_measurement_base'] = $q->user_measurement_base; + } if($this->input->post('user_date_format')) { - $data['user_date_format'] = $this->input->post('user_date_format', true); - } else { - $data['user_date_format'] = $q->user_date_format; - } + $data['user_date_format'] = $this->input->post('user_date_format', true); + } else { + $data['user_date_format'] = $q->user_date_format; + } - if($this->input->post('user_stylesheet')) { - $data['user_stylesheet'] = $this->input->post('user_stylesheet', true); - } else { - $data['user_stylesheet'] = $q->user_stylesheet; - } + if($this->input->post('user_stylesheet')) { + $data['user_stylesheet'] = $this->input->post('user_stylesheet', true); + } else { + $data['user_stylesheet'] = $q->user_stylesheet; + } if($this->input->post('user_qth_lookup')) { $data['user_qth_lookup'] = $this->input->post('user_qth_lookup', true); @@ -366,6 +381,24 @@ class User extends CI_Controller { $data['user_amsat_status_upload'] = $q->user_amsat_status_upload; } + if($this->input->post('user_mastodon_url')) { + $data['user_mastodon_url'] = $this->input->post('user_mastodon_url', false); + } else { + $data['user_mastodon_url'] = $q->user_mastodon_url; + } + + if($this->input->post('user_gridmap_default_band')) { + $data['user_gridmap_default_band'] = $this->input->post('user_gridmap_default_band', false); + } else { + $data['user_gridmap_default_band'] = $q->user_gridmap_default_band; + } + + if($this->input->post('user_gridmap_confirmation')) { + $data['user_gridmap_confirmation'] = ($this->input->post('user_gridmap_confirmation_qsl') !== null ? 'Q' : '').($this->input->post('user_gridmap_confirmation_lotw') !== null ? 'L' : '').($this->input->post('user_gridmap_confirmation_eqsl') !== null ? 'E' : ''); + } else { + $data['user_gridmap_confirmation'] = $q->user_gridmap_confirmation; + } + if($this->input->post('user_column1')) { $data['user_column1'] = $this->input->post('user_column1', true); } else { @@ -436,7 +469,7 @@ class User extends CI_Controller { $data['user_callsign'] = $this->input->post('user_callsign', true); $data['user_locator'] = $this->input->post('user_locator', true); $data['user_timezone'] = $this->input->post('user_timezone', true); - $data['user_stylesheet'] = $this->input->post('user_stylesheet'); + $data['user_stylesheet'] = $this->input->post('user_stylesheet'); $data['user_qth_lookup'] = $this->input->post('user_qth_lookup'); $data['user_sota_lookup'] = $this->input->post('user_sota_lookup'); $data['user_wwff_lookup'] = $this->input->post('user_wwff_lookup'); @@ -451,6 +484,9 @@ class User extends CI_Controller { $data['user_show_profile_image'] = $this->input->post('user_show_profile_image'); $data['user_previous_qsl_type'] = $this->input->post('user_previous_qsl_type'); $data['user_amsat_status_upload'] = $this->input->post('user_amsat_status_upload'); + $data['user_mastodon_url'] = $this->input->post('user_mastodon_url'); + $data['user_gridmap_default_band'] = $this->input->post('user_gridmap_default_band'); + $data['user_gridmap_confirmation'] = ($this->input->post('user_gridmap_confirmation_qsl') !== null ? 'Q' : '').($this->input->post('user_gridmap_confirmation_lotw') !== null ? 'L' : '').($this->input->post('user_gridmap_confirmation_eqsl') !== null ? 'E' : ''); $this->load->view('user/edit'); $this->load->view('interface_assets/footer'); } diff --git a/application/language/english/account_lang.php b/application/language/english/account_lang.php index a5172c94..54025f59 100644 --- a/application/language/english/account_lang.php +++ b/application/language/english/account_lang.php @@ -32,7 +32,7 @@ $lang['account_gridsquare'] = 'Gridsquare'; $lang['account_cloudlog_preferences'] = 'Cloudlog Preferences'; $lang['account_timezone'] = 'Timezone'; $lang['account_date_format'] = 'Date Format'; -$lang['account_measurement_preference'] = 'Measurement preference'; +$lang['account_measurement_preferences'] = 'Measurement preference'; $lang['account_select_how_you_would_like_dates_shown_when_logged_into_your_account'] = 'Select how you would like dates shown when logged into your account.'; $lang['account_choose_which_unit_distances_will_be_shown_in'] = 'Choose which unit distances will be shown in'; @@ -68,8 +68,8 @@ $lang['account_clublog_password'] = 'Club Log Password'; $lang['account_the_email_or_callsign_you_use_to_login_to_club_log'] = 'The Email or Callsign you use to login to Club Log'; $lang['account_eqsl'] = 'eQSL'; -$lang['account_eqsl_username'] = 'eQSL.cc Username'; -$lang['account_eqsl_password'] = 'eQSL.cc Password'; +$lang['account_eqslcc_username'] = 'eQSL.cc Username'; +$lang['account_eqslcc_password'] = 'eQSL.cc Password'; $lang['account_save_account_changes'] = 'Save Account Changes'; $lang['account_create_account'] = 'Create Account'; @@ -89,3 +89,9 @@ $lang['account_forgot_your_password'] = 'Forgot your password?'; $lang['account_login_to_cloudlog'] = 'Login to Cloudlog'; $lang['account_login'] = 'Login'; + +$lang['account_mastodon'] = 'Mastodonserver'; +$lang['account_user_mastodon'] = 'URL of Mastodonserver'; + +$lang['account_gridmap_settings'] = 'Settings for Gridsquare Map'; +$lang['account_gridmap_default_band'] = 'Default Band'; diff --git a/application/language/english/general_words_lang.php b/application/language/english/general_words_lang.php index 6dc3b456..2b15e688 100644 --- a/application/language/english/general_words_lang.php +++ b/application/language/english/general_words_lang.php @@ -55,6 +55,7 @@ $lang['general_word_lotw'] = 'Logbook of the World'; $lang['general_edit_qso'] = 'Edit QSO'; $lang['general_mark_qsl_rx_bureau'] = 'Mark QSL Received (Bureau)'; $lang['general_mark_qsl_rx_direct'] = 'Mark QSL Received (Direct)'; +$lang['general_mark_qsl_rx_electronic'] = 'Mark QSL Received (Electronic)'; $lang['general_mark_qsl_tx_bureau'] = 'Mark QSL Sent (Bureau)'; $lang['general_mark_qsl_tx_direct'] = 'Mark QSL Sent (Direct)'; @@ -138,4 +139,4 @@ $lang['northamerica'] = 'North America'; $lang['oceania'] = 'Oceania'; $lang['southamerica'] = 'South America'; -$lang['gen_band_selection'] = 'Band selection'; \ No newline at end of file +$lang['gen_band_selection'] = 'Band selection'; diff --git a/application/language/english/menu_lang.php b/application/language/english/menu_lang.php index 30972966..b4951a41 100644 --- a/application/language/english/menu_lang.php +++ b/application/language/english/menu_lang.php @@ -75,6 +75,7 @@ $lang['menu_labels'] = 'Labels'; $lang['menu_logbook_of_the_world'] = 'Logbook of the World'; $lang['menu_eqsl_import_export'] = 'eQSL Import / Export'; $lang['menu_qrz_logbook'] = 'QRZ Logbook'; +$lang['menu_hrd_logbook'] = 'HRDLog Logbook'; $lang['menu_qo_100_dx_club_upload'] = 'QO-100 Dx Club Upload'; $lang['menu_api_keys'] = 'API Keys'; $lang['menu_hardware_interfaces'] = 'Hardware Interfaces'; diff --git a/application/language/finnish/account_lang.php b/application/language/finnish/account_lang.php index 5adf7910..5de67d87 100644 --- a/application/language/finnish/account_lang.php +++ b/application/language/finnish/account_lang.php @@ -32,7 +32,7 @@ $lang['account_gridsquare'] = 'Gridsquare'; $lang['account_cloudlog_preferences'] = 'Cloudlog Asetukset'; $lang['account_timezone'] = 'Aikavyöhyke'; $lang['account_date_format'] = 'Päivämäärämuoto'; -$lang['account_measurement_preference'] = 'Mittayksikkömuoto'; +$lang['account_measurement_preferences'] = 'Mittayksikkömuoto'; $lang['account_select_how_you_would_like_dates_shown_when_logged_into_your_account'] = 'Valitse, miten haluat päivämäärät näkyvän, kun olet kirjautunut tilillesi.'; $lang['account_choose_which_unit_distances_will_be_shown_in'] = 'Valitse, mitä mittayksikkömuotoa käytetään'; @@ -68,8 +68,8 @@ $lang['account_clublog_password'] = 'Club Log Salasana'; $lang['account_the_email_or_callsign_you_use_to_login_to_club_log'] = 'Sähköposti tai kutsu, jota käytät kirjautuessasi Club Log:iin'; $lang['account_eqsl'] = 'eQSL'; -$lang['account_eqsl_username'] = 'eQSL.cc Käyttäjänimi'; -$lang['account_eqsl_password'] = 'eQSL.cc Salasana'; +$lang['account_eqslcc_username'] = 'eQSL.cc Käyttäjänimi'; +$lang['account_eqslcc_password'] = 'eQSL.cc Salasana'; $lang['account_save_account_changes'] = 'Tallenna käyttäjätilin muutokset'; $lang['account_create_account'] = 'Luo käyttäjätili'; @@ -89,3 +89,6 @@ $lang['account_forgot_your_password'] = 'Salasana unohtunut?'; $lang['account_login_to_cloudlog'] = 'Kirjaudu Cloudlogiin'; $lang['account_login'] = 'Kirjaudu'; + +$lang['account_mastodon'] = 'Mastodonserver'; +$lang['account_user_mastodon'] = 'URL of Mastodonserver'; diff --git a/application/language/finnish/menu_lang.php b/application/language/finnish/menu_lang.php index 8ca7b2ba..83d7321c 100644 --- a/application/language/finnish/menu_lang.php +++ b/application/language/finnish/menu_lang.php @@ -73,6 +73,7 @@ $lang['menu_print_requested_qsls'] = 'Tulosta pyydetyt QSL:t'; $lang['menu_logbook_of_the_world'] = 'Logbook of the World'; $lang['menu_eqsl_import_export'] = 'eQSL Tuonti / Vienti'; $lang['menu_qrz_logbook'] = 'QRZ Logi'; +$lang['menu_hrd_logbook'] = 'HRDLog Logi'; $lang['menu_qo_100_dx_club_upload'] = 'QO-100 Dx Club Lähetys'; $lang['menu_api_keys'] = 'API Keys'; $lang['menu_hardware_interfaces'] = 'Hardware Interfaces'; diff --git a/application/language/german/account_lang.php b/application/language/german/account_lang.php index d0400d8e..dda2d956 100644 --- a/application/language/german/account_lang.php +++ b/application/language/german/account_lang.php @@ -32,7 +32,7 @@ $lang['account_gridsquare'] = 'Planquadrat'; $lang['account_cloudlog_preferences'] = 'Cloudlog Einstellungen'; $lang['account_timezone'] = 'Zeitzone'; $lang['account_date_format'] = 'Datumsformat'; -$lang['account_measurement_preference'] = 'Entfernungsformat'; +$lang['account_measurement_preferences'] = 'Entfernungsformat'; $lang['account_select_how_you_would_like_dates_shown_when_logged_into_your_account'] = 'Wähle, wie Datumsfelder angezeigt werden sollen, wenn du eingeloggt bist.'; $lang['account_choose_which_unit_distances_will_be_shown_in'] = 'Wähle, in welcher Einheit Entfernungen angezeigt werden sollen.'; @@ -68,8 +68,8 @@ $lang['account_clublog_password'] = 'Club Log Passwort'; $lang['account_the_email_or_callsign_you_use_to_login_to_club_log'] = 'Die Emailadresse oder Rufzeichen, das für den Club Log Login verwendet wird'; $lang['account_eqsl'] = 'eQSL'; -$lang['account_eqsl_username'] = 'eQSL.cc Benutzername'; -$lang['account_eqsl_password'] = 'eQSL.cc Passwort'; +$lang['account_eqslcc_username'] = 'eQSL.cc Benutzername'; +$lang['account_eqslcc_password'] = 'eQSL.cc Passwort'; $lang['account_save_account_changes'] = 'Speichere Kontoänderungen'; $lang['account_create_account'] = 'Konto anlegen'; @@ -89,3 +89,9 @@ $lang['account_forgot_your_password'] = 'Passwort vergessen?'; $lang['account_login_to_cloudlog'] = 'Anmeldung bei Cloudlog'; $lang['account_login'] = 'Anmeldung'; + +$lang['account_mastodon'] = 'Mastodonserver'; +$lang['account_user_mastodon'] = 'URL des Mastodonservers'; + +$lang['account_gridmap_settings'] = 'Einstellung der Planquadratkarte'; +$lang['account_gridmap_default_band'] = 'Standardband'; diff --git a/application/language/german/general_words_lang.php b/application/language/german/general_words_lang.php index 61865b04..8930dddf 100644 --- a/application/language/german/general_words_lang.php +++ b/application/language/german/general_words_lang.php @@ -55,6 +55,7 @@ $lang['general_word_lotw'] = 'Logbook of the World'; $lang['general_edit_qso'] = 'QSO bearbeiten'; $lang['general_mark_qsl_rx_bureau'] = 'Markiere QSL erhalten (Büro)'; $lang['general_mark_qsl_rx_direct'] = 'Markiere QSL erhalten (Direkt)'; +$lang['general_mark_qsl_rx_electronic'] = 'Markiere QSL erhalten (Elektronisch)'; $lang['general_mark_qsl_tx_bureau'] = 'Markiere QSL gesendet (Büro)'; $lang['general_mark_qsl_tx_direct'] = 'Markiere QSL gesendet (Direkt)'; diff --git a/application/language/german/menu_lang.php b/application/language/german/menu_lang.php index ba75892b..05fbb07d 100644 --- a/application/language/german/menu_lang.php +++ b/application/language/german/menu_lang.php @@ -75,6 +75,7 @@ $lang['menu_labels'] = 'Etiketten'; $lang['menu_logbook_of_the_world'] = 'Logbook of the World'; $lang['menu_eqsl_import_export'] = 'eQSL Import / Export'; $lang['menu_qrz_logbook'] = 'QRZ Logbuch'; +$lang['menu_hrd_logbook'] = 'HRDLog Logbuch'; $lang['menu_qo_100_dx_club_upload'] = 'QO-100 Dx Club Upload'; $lang['menu_api_keys'] = 'API-Schlüssel'; $lang['menu_hardware_interfaces'] = 'Hardware-Schnittstellen'; diff --git a/application/language/russian/account_lang.php b/application/language/russian/account_lang.php index c4e676a4..a4d0e313 100644 --- a/application/language/russian/account_lang.php +++ b/application/language/russian/account_lang.php @@ -32,7 +32,7 @@ $lang['account_gridsquare'] = 'QTH локатор'; $lang['account_cloudlog_preferences'] = 'Настройки Cloudlog'; $lang['account_timezone'] = 'Часовой пояс'; $lang['account_date_format'] = 'Формат даты'; -$lang['account_measurement_preference'] = 'Единицы измерения'; +$lang['account_measurement_preferences'] = 'Единицы измерения'; $lang['account_select_how_you_would_like_dates_shown_when_logged_into_your_account'] = 'Выберите представление даты для отображения в вашем аккаунте.'; $lang['account_choose_which_unit_distances_will_be_shown_in'] = 'Выберите единицы измерения расстояния'; @@ -68,8 +68,8 @@ $lang['account_clublog_password'] = 'Пароль'; $lang['account_the_email_or_callsign_you_use_to_login_to_club_log'] = 'Емэйл или позывной, которые вы используете для логина в Club Log'; $lang['account_eqsl'] = 'eQSL'; -$lang['account_eqsl_username'] = 'Логин'; -$lang['account_eqsl_password'] = 'Пароль'; +$lang['account_eqslcc_username'] = 'Логин'; +$lang['account_eqslcc_password'] = 'Пароль'; $lang['account_save_account_changes'] = 'Сохранить изменения'; $lang['account_create_account'] = 'Создать аккаунт'; @@ -89,3 +89,6 @@ $lang['account_forgot_your_password'] = 'Забыли пароль?'; $lang['account_login_to_cloudlog'] = 'Вход в Cloudlog'; $lang['account_login'] = 'Вход'; + +$lang['account_mastodon'] = 'Mastodonserver'; +$lang['account_user_mastodon'] = 'URL of Mastodonserver'; diff --git a/application/language/russian/general_words_lang.php b/application/language/russian/general_words_lang.php index de976c69..3f636bd9 100644 --- a/application/language/russian/general_words_lang.php +++ b/application/language/russian/general_words_lang.php @@ -59,6 +59,7 @@ $lang['general_mark_qsl_rx_bureau'] = 'Отметить QSL полученной $lang['general_mark_qsl_rx_direct'] = 'Отметить QSL полученной (напрямую)'; $lang['general_mark_qsl_tx_bureau'] = 'Отметить QSL отправленной (через бюро)'; $lang['general_mark_qsl_tx_direct'] = 'Отметить QSL отправленой (напрямую)'; +$lang['general_mark_qsl_rx_electronic'] = 'Отметить QSL полученной (электронно)'; $lang['general_delete_qso'] = 'Удалить QSO'; @@ -111,6 +112,7 @@ $lang['gen_hamradio_iota'] = 'IOTA'; $lang['gen_hamradio_sota'] = 'SOTA'; $lang['gen_hamradio_pota'] = 'POTA'; $lang['gen_hamradio_gridsquare'] = 'Квадрат'; +$lang['gen_hamradio_distance'] = 'Дистанция'; $lang['gen_hamradio_operator'] = 'Оператор'; $lang['gen_hamradio_sig'] = 'Sig'; diff --git a/application/language/russian/gridsquares_lang.php b/application/language/russian/gridsquares_lang.php index e28ddaeb..aac2d4b0 100644 --- a/application/language/russian/gridsquares_lang.php +++ b/application/language/russian/gridsquares_lang.php @@ -2,14 +2,25 @@ defined('BASEPATH') OR exit('No direct script access allowed'); - - -$lang['gridsquares_gridsquare_map'] = 'Выбор диапазона'; +$lang['gridsquares_gridsquare_map'] = 'Карта квадратов'; $lang['gridsquares_confirmed_is_green'] = 'Подтверждённые окрашены зелёным'; -$lang['gridsquares_worked_but_not_confirmed_is_red'] = 'Сработанные, но не подтверждённые — красным'; +$lang['gridsquares_worked_but_not_confirmed_is_red'] = 'Сработанные, но не подтверждённые окрвшены красным'; +$lang['gridsquares_activated_but_not_confirmed_is_red'] = 'Активированные, но не подтверждённые окрашены красным'; $lang['gridsquares_this_map_does_not_include_satellite_internet_or_repeater_qsos'] = 'На этой карте не отображены QSO, проведённые через спутники, интернет или репитеры'; $lang['gridsquares_grid_squares'] = 'квадрат(/-а/-ов)'; $lang['gridsquares_total_count'] = 'Всего'; + +$lang['gridsquares_band'] = 'Диапазон'; +$lang['gridsquares_mode'] = 'Вид излучения'; +$lang['gridsquares_sat'] = 'Спутник'; +$lang['gridsquares_confirmation'] = 'Подтверждение'; + +$lang['gridsquares_button_plot'] = 'Отобразить'; + +$lang['gridsquares_gridsquares'] = 'Квадраты'; +$lang['gridsquares_gridsquares_confirmed'] = 'Подтверждёно квадратов'; +$lang['gridsquares_gridsquares_not_confirmed'] = 'Неподтверждёно квадратов'; +$lang['gridsquares_gridsquares_total_worked'] = 'Всего сработано квадратов'; \ No newline at end of file diff --git a/application/language/russian/menu_lang.php b/application/language/russian/menu_lang.php index efdfce23..f4c04cb1 100644 --- a/application/language/russian/menu_lang.php +++ b/application/language/russian/menu_lang.php @@ -21,6 +21,7 @@ $lang['menu_notes'] = 'Заметки'; $lang['menu_analytics'] = 'Аналитика'; $lang['menu_statistics'] = 'Статистика'; $lang['menu_gridsquares'] = 'Квадраты'; +$lang['menu_gridmap'] = 'Карта квадратов'; $lang['menu_activated_gridsquares'] = 'Активированные квадраты'; $lang['menu_gridsquare_activators'] = 'Активаторы квадратов'; $lang['menu_distances_worked'] = 'Сработанные дистанции'; @@ -70,12 +71,14 @@ $lang['menu_sota_csv_export'] = 'Экспорт SOTA CSV'; $lang['menu_cabrillo_export'] = 'Экспорт Cabrillo'; $lang['menu_oqrs_requests'] = 'Запросы OQRS'; $lang['menu_print_requested_qsls'] = 'Распечатать запрошенные QSL'; +$lang['menu_labels'] = 'Наклейки'; $lang['menu_logbook_of_the_world'] = 'Logbook of the World'; $lang['menu_eqsl_import_export'] = 'Импорт / экспорт eQSL'; $lang['menu_qrz_logbook'] = 'QRZ Logbook'; +$lang['menu_hrd_logbook'] = 'HRDLog Logbook'; $lang['menu_qo_100_dx_club_upload'] = 'Загрузка в QO-100 Dx Club'; $lang['menu_api_keys'] = 'ключи API'; $lang['menu_hardware_interfaces'] = 'Аппаратные интерфейсы'; $lang['menu_help'] = 'Помощь'; $lang['menu_forum'] = 'Форум'; -$lang['menu_logout'] = 'Выход'; \ No newline at end of file +$lang['menu_logout'] = 'Выход'; diff --git a/application/language/russian/options_lang.php b/application/language/russian/options_lang.php index dec1cb48..52753e90 100644 --- a/application/language/russian/options_lang.php +++ b/application/language/russian/options_lang.php @@ -32,6 +32,8 @@ $lang['options_radio_timeout_warning_changed_to'] = 'Значение тайма $lang['options_email'] = 'Емэйл'; $lang['options_outgoing_protocol'] = 'Протокол отправки емэйл'; $lang['options_smtp_encryption'] = 'Шифрование SMTP'; +$lang['options_email_address'] = 'Адрес электронной почты'; +$lang['options_email_sender_name'] = 'Имя отправителя'; $lang['options_smtp_host'] = 'SMTP хост'; $lang['options_smtp_port'] = 'SMTP порт'; $lang['options_smtp_username'] = 'SMTP логин'; @@ -40,6 +42,8 @@ $lang['options_crlf'] = 'CRLF'; $lang['options_newline'] = 'Newline'; $lang['options_outgoing_email_protocol_changed_to'] = 'Протокол отправки емэйл изменён на '; $lang['options_smtp_encryption_changed_to'] = 'Шифрование SMTP изменено на '; +$lang['options_email_address_changed_to'] = 'Адрес электронной почты изменён на '; +$lang['options_email_sender_name_changed_to'] = 'Имя отправителя изменено на '; $lang['options_smtp_host_changed_to'] = 'SMTP хост изменён на '; $lang['options_smtp_port_changed_to'] = 'SMTP порт изменён на '; $lang['options_smtp_username_changed_to'] = 'SMTP логин изменён на '; diff --git a/application/libraries/AdifHelper.php b/application/libraries/AdifHelper.php index cc936f08..a639896c 100644 --- a/application/libraries/AdifHelper.php +++ b/application/libraries/AdifHelper.php @@ -42,7 +42,6 @@ class AdifHelper { 'FORCE_INIT', 'GRIDSQUARE', 'HEADING', - 'HRDLOG_QSO_UPLOAD_STATUS', 'IOTA', 'ITUZ', 'K_INDEX', @@ -64,6 +63,7 @@ class AdifHelper { 'PRECEDENCE', 'PROP_MODE', 'PUBLIC_KEY', + 'HRDLOG_QSO_UPLOAD_STATUS', 'QRZCOM_QSO_UPLOAD_STATUS', 'QSLMSG', 'QSL_RCVD', diff --git a/application/libraries/EqslImporter.php b/application/libraries/EqslImporter.php index 77cc8701..087ca036 100644 --- a/application/libraries/EqslImporter.php +++ b/application/libraries/EqslImporter.php @@ -36,8 +36,9 @@ class EqslImporter $this->qth_nickname = $qth; } - public function from_file($adif_file) { + public function from_file($adif_file,$station_callsign) { $this->init('ADIF upload', $adif_file); + $this->callsign=$station_callsign; } // generate a sanitized file name from a callsign and a QTH nickname @@ -136,6 +137,7 @@ class EqslImporter $query = $this->CI->db->query('SELECT eqsl_rcvd_mark FROM config'); $q = $query->row(); $config['eqsl_rcvd_mark'] = $q->eqsl_rcvd_mark; + $station_callsign=$this->callsign; $this->CI->adif_parser->load_from_file($this->adif_file); $this->CI->adif_parser->initialize(); @@ -154,14 +156,14 @@ class EqslImporter $record['qsl_sent'] = $config['eqsl_rcvd_mark']; } - $status = $this->CI->logbook_model->import_check($time_on, $record['call'], $record['band']); + $status = $this->CI->logbook_model->import_check($time_on, $record['call'], $record['band'], $record['mode'],$station_callsign); $qsoid = 0; if ($status[0] == "Found") { $qsoid = $status[1]; - $dupe = $this->CI->eqslmethods_model->eqsl_dupe_check($time_on, $record['call'], $record['band'], $config['eqsl_rcvd_mark']); + $dupe = $this->CI->eqslmethods_model->eqsl_dupe_check($time_on, $record['call'], $record['band'], $record['mode'],$config['eqsl_rcvd_mark'],$station_callsign); if ($dupe == false) { $updated += 1; - $eqsl_status = $this->CI->eqslmethods_model->eqsl_update($time_on, $record['call'], $record['band'], $config['eqsl_rcvd_mark']); + $eqsl_status = $this->CI->eqslmethods_model->eqsl_update($time_on, $record['call'], $record['band'], $record['mode'], $config['eqsl_rcvd_mark'],$station_callsign); } else { $dupes += 1; $eqsl_status = "Already received an eQSL for this QSO."; diff --git a/application/migrations/125_lotw_enddates.php b/application/migrations/125_lotw_enddates.php new file mode 100644 index 00000000..e09e26d3 --- /dev/null +++ b/application/migrations/125_lotw_enddates.php @@ -0,0 +1,21 @@ +db->table_exists('lotw_certs')) { + $sql = 'UPDATE lotw_certs SET qso_end_date = DATE_ADD(qso_end_date, INTERVAL 24*60*60 -1 SECOND) WHERE TIME(qso_end_date) = "00:00:00";'; + $this->db->query($sql); + } + } + + public function down() + { + if ($this->db->table_exists('lotw_certs')) { + $sql = 'UPDATE lotw_certs SET qso_end_date = DATE_SUB(qso_end_date, INTERVAL 24*60*60 -1 SECOND) WHERE TIME(qso_end_date) = "23:59:59";'; + $this->db->query($sql); + } + } +} diff --git a/application/migrations/126_mastodon_url.php b/application/migrations/126_mastodon_url.php new file mode 100644 index 00000000..ec2a5992 --- /dev/null +++ b/application/migrations/126_mastodon_url.php @@ -0,0 +1,30 @@ +db->field_exists('user_mastodon_url', 'users')) { + $fields = array( + 'user_mastodon_url varchar(32) default NULL', + ); + $this->dbforge->add_column('users', $fields, 'user_column5'); + } + } + + public function down() + { + $this->dbforge->drop_column('users', 'user_mastodon_url'); + } +} + + + diff --git a/application/migrations/127_add_hrdlog_fields.php b/application/migrations/127_add_hrdlog_fields.php new file mode 100644 index 00000000..8d1cdf1c --- /dev/null +++ b/application/migrations/127_add_hrdlog_fields.php @@ -0,0 +1,42 @@ +db->field_exists('hrdlogrealtime', 'station_profile')) { + $fields = array( + 'hrdlogrealtime tinyint(1)' + ); + $this->dbforge->add_column('station_profile', $fields); + } + + if (!$this->db->field_exists('hrdlog_code', 'station_profile')) { + $fields = array( + 'hrdlog_code varchar(20) DEFAULT NULL', + ); + $this->dbforge->add_column('station_profile', $fields); + } + + if ( (!$this->db->field_exists('COL_HRDLOG_QSO_UPLOAD_DATE', $this->config->item('table_name'))) && + (!$this->db->field_exists('COL_HRDLOG_QSO_UPLOAD_STATUS', $this->config->item('table_name')))) { + $fields = array( + 'COL_HRDLOG_QSO_UPLOAD_DATE datetime default NULL', + 'COL_HRDLOG_QSO_UPLOAD_STATUS varchar(10) default NULL' + ); + $this->dbforge->add_column($this->config->item('table_name'), $fields); + } + } + + public function down() + { + if ($this->db->field_exists('hrdlogrealtime', 'station_profile')) { + $this->dbforge->drop_column('station_profile', 'hrdlogrealtime'); + } + if ($this->db->field_exists('hrdlog_code', 'station_profile')) { + $this->dbforge->drop_column('station_profile', 'hrdlog_code'); + } + } +} diff --git a/application/migrations/128_user_default_map_settings.php b/application/migrations/128_user_default_map_settings.php new file mode 100644 index 00000000..79bee0af --- /dev/null +++ b/application/migrations/128_user_default_map_settings.php @@ -0,0 +1,43 @@ +db->field_exists('user_gridmap_default_band', 'users')) { + $fields = array( + 'user_gridmap_default_band varchar(10) default NULL', + ); + $this->dbforge->add_column('users', $fields); + } + if (!$this->db->field_exists('user_gridmap_confirmation', 'users')) { + $fields = array( + 'user_gridmap_confirmation varchar(3) default NULL', + ); + $this->dbforge->add_column('users', $fields); + } + $data = array( + 'user_gridmap_default_band' => 'All', + 'user_gridmap_confirmation' => 'QL', + ); + $this->db->update('users', $data); + } + + public function down() + { + $this->dbforge->drop_column('users', 'user_gridmap_default_band'); + $this->dbforge->drop_column('users', 'user_gridmap_confirmation'); + } +} + + + diff --git a/application/models/Eqslmethods_model.php b/application/models/Eqslmethods_model.php index 369a4117..5ad652dd 100644 --- a/application/models/Eqslmethods_model.php +++ b/application/models/Eqslmethods_model.php @@ -156,7 +156,7 @@ class Eqslmethods_model extends CI_Model { // Update a QSO with eQSL QSL info // We could also probably use this use this: http://eqsl.cc/qslcard/VerifyQSO.txt // http://www.eqsl.cc/qslcard/ImportADIF.txt - function eqsl_update($datetime, $callsign, $band, $qsl_status) { + function eqsl_update($datetime, $callsign, $band, $mode, $qsl_status,$station_callsign) { $data = array( 'COL_EQSL_QSLRDATE' => date('Y-m-d H:i:s'), // eQSL doesn't give us a date, so let's use current 'COL_EQSL_QSL_RCVD' => $qsl_status @@ -165,7 +165,9 @@ class Eqslmethods_model extends CI_Model { $this->db->where('COL_TIME_ON >= DATE_ADD(DATE_FORMAT("'.$datetime.'", \'%Y-%m-%d %H:%i\' ), INTERVAL -15 MINUTE )'); $this->db->where('COL_TIME_ON <= DATE_ADD(DATE_FORMAT("'.$datetime.'", \'%Y-%m-%d %H:%i\' ), INTERVAL 15 MINUTE )'); $this->db->where('COL_CALL', $callsign); + $this->db->where('COL_STATION_CALLSIGN', $station_callsign); $this->db->where('COL_BAND', $band); + $this->db->where('COL_MODE', $mode); $this->db->update($this->config->item('table_name'), $data); @@ -173,12 +175,14 @@ class Eqslmethods_model extends CI_Model { } // Determine if we've already received an eQSL for this QSO - function eqsl_dupe_check($datetime, $callsign, $band, $qsl_status) { + function eqsl_dupe_check($datetime, $callsign, $band, $mode, $qsl_status,$station_callsign) { $this->db->select('COL_EQSL_QSLRDATE'); $this->db->where('COL_TIME_ON >= DATE_ADD(DATE_FORMAT("'.$datetime.'", \'%Y-%m-%d %H:%i\' ), INTERVAL -15 MINUTE )'); $this->db->where('COL_TIME_ON <= DATE_ADD(DATE_FORMAT("'.$datetime.'", \'%Y-%m-%d %H:%i\' ), INTERVAL 15 MINUTE )'); $this->db->where('COL_CALL', $callsign); $this->db->where('COL_BAND', $band); + $this->db->where('COL_MODE', $mode); + $this->db->where('COL_STATION_CALLSIGN', $station_callsign); $this->db->where('COL_EQSL_QSL_RCVD', $qsl_status); $this->db->limit(1); diff --git a/application/models/Labels_model.php b/application/models/Labels_model.php index 91c62027..c0c50494 100644 --- a/application/models/Labels_model.php +++ b/application/models/Labels_model.php @@ -127,4 +127,16 @@ class Labels_model extends CI_Model { return $query; } + + function export_printrequestedids($ids) { + $this->db->select($this->config->item('table_name').'.*, station_profile.*, dxcc_entities.name as station_country'); + $this->db->join('station_profile', 'station_profile.station_id = '.$this->config->item('table_name').'.station_id'); + $this->db->join('dxcc_entities', 'station_profile.station_dxcc = dxcc_entities.adif'); + $this->db->where('station_profile.user_id', $this->session->userdata('user_id')); + $this->db->where_in('COL_PRIMARY_KEY', $ids); + $this->db->order_by("COL_DXCC", "ASC"); + $query = $this->db->get($this->config->item('table_name')); + + return $query; + } } \ No newline at end of file diff --git a/application/models/Logbook_model.php b/application/models/Logbook_model.php index 71e7ac28..06d6d1b1 100755 --- a/application/models/Logbook_model.php +++ b/application/models/Logbook_model.php @@ -252,6 +252,10 @@ class Logbook_model extends CI_Model { $data['COL_MY_GRIDSQUARE'] = strtoupper(trim($station['station_gridsquare'])); } + if ($this->exists_hrdlog_code($station_id)) { + $data['COL_HRDLOG_QSO_UPLOAD_STATUS'] = 'N'; + } + if ($this->exists_qrz_api_key($station_id)) { $data['COL_QRZCOM_QSO_UPLOAD_STATUS'] = 'N'; } @@ -506,12 +510,26 @@ class Logbook_model extends CI_Model { $this->upload_amsat_status($data); } - // No point in fetching qrz api key and qrzrealtime setting if we're skipping the export + // No point in fetching hrdlog code or qrz api key and qrzrealtime setting if we're skipping the export if (!$skipexport) { - $result = $this->exists_qrz_api_key($data['station_id']); - // Push qso to qrz if apikey is set, and realtime upload is enabled, and we're not importing an adif-file + $result = $this->exists_hrdlog_code($data['station_id']); + // Push qso to hrdlog if code is set, and realtime upload is enabled, and we're not importing an adif-file + if (isset($result->hrdlog_code) && $result->hrdlogrealtime == 1) { + $CI =& get_instance(); + $CI->load->library('AdifHelper'); + $qso = $this->get_qso($last_id)->result(); + + $adif = $CI->adifhelper->getAdifLine($qso[0]); + $result = $this->push_qso_to_hrdlog($result->hrdlog_code, $data['COL_STATION_CALLSIGN'], $adif); + if ( ($result['status'] == 'OK') || ( ($result['status'] == 'error') || ($result['status'] == 'duplicate') || ($result['status'] == 'auth_error') )){ + $this->mark_hrdlog_qsos_sent($last_id); + } + } + $result = ''; // Empty result from previous hrdlog-attempt for safety + $result = $this->exists_qrz_api_key($data['station_id']); +// Push qso to qrz if apikey is set, and realtime upload is enabled, and we're not importing an adif-file if (isset($result->qrzapikey) && $result->qrzrealtime == 1) { $CI =& get_instance(); $CI->load->library('AdifHelper'); @@ -519,7 +537,7 @@ class Logbook_model extends CI_Model { $adif = $CI->adifhelper->getAdifLine($qso[0]); $result = $this->push_qso_to_qrz($result->qrzapikey, $adif); - if ($result['status'] == 'OK') { + if ( ($result['status'] == 'OK') || ( ($result['status'] == 'error') && ($result['message'] == 'STATUS=FAIL&REASON=Unable to add QSO to database: duplicate&EXTENDED=')) ){ $this->mark_qrz_qsos_sent($last_id); } } @@ -545,6 +563,24 @@ class Logbook_model extends CI_Model { } } + /* + * Function checks if a HRDLog Code exists in the table with the given station id + */ + function exists_hrdlog_code($station_id) { + $sql = 'select hrdlog_code, hrdlogrealtime from station_profile + where station_id = ' . $station_id; + + $query = $this->db->query($sql); + + $result = $query->row(); + + if ($result) { + return $result; + } else { + return false; + } + } + /* * Function checks if a QRZ API Key exists in the table with the given station id */ @@ -583,6 +619,59 @@ class Logbook_model extends CI_Model { } } + /* + * Function uploads a QSO to HRDLog with the API given. + * $adif contains a line with the QSO in the ADIF format. QSO ends with an + */ + function push_qso_to_hrdlog($apikey, $station_callsign, $adif, $replaceoption = false) { + $url = 'https://robot.hrdlog.net/newentry.aspx'; + + $post_data['Code'] = $apikey; + if ($replaceoption) { + $post_data['Cmd'] = 'UPDATE'; + $post_data['ADIFKey'] = $adif; + } + $post_data['ADIFData'] = $adif; + + $post_data['Callsign'] = $station_callsign; + + + $post_encoded=http_build_query($post_data); + + $ch = curl_init( $url ); + curl_setopt( $ch, CURLOPT_POST, true); + curl_setopt( $ch, CURLOPT_POSTFIELDS, $post_encoded); + curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt( $ch, CURLOPT_HEADER, 0); + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded')); + $content = curl_exec($ch); + if ($content){ + if (stristr($content,'1')) { + $result['status'] = 'OK'; + return $result; + } elseif (stristr($content,'0')) { + $result['status'] = 'duplicate'; + $result['message'] = $content; + return $result; + } elseif (stristr($content,'Unknown user')) { + $result['status'] = 'auth_error'; + $result['message'] = $content; + return $result; + } else { + $result['status'] = 'error'; + $result['message'] = $content; + return $result; + } + } + if(curl_errno($ch)){ + $result['status'] = 'error'; + $result['message'] = 'Curl error: '. curl_errno($ch); + return $result; + } + curl_close($ch); + } + /* * Function uploads a QSO to QRZ with the API given. * $adif contains a line with the QSO in the ADIF format. QSO ends with an @@ -655,6 +744,23 @@ class Logbook_model extends CI_Model { return $response === 200; } + /* + * Function marks QSOs as uploaded to HRDLog. + * $primarykey is the unique id for that QSO in the logbook + */ + function mark_hrdlog_qsos_sent($primarykey) { + $data = array( + 'COL_HRDLOG_QSO_UPLOAD_DATE' => date("Y-m-d H:i:s", strtotime("now")), + 'COL_HRDLOG_QSO_UPLOAD_STATUS' => 'Y', + ); + + $this->db->where('COL_PRIMARY_KEY', $primarykey); + + $this->db->update($this->config->item('table_name'), $data); + + return true; + } + /* * Function marks QSOs as uploaded to QRZ. * $primarykey is the unique id for that QSO in the logbook @@ -694,10 +800,10 @@ class Logbook_model extends CI_Model { $sat_name = ''; if ($data['COL_SAT_NAME'] == 'AO-7') { if ($data['COL_BAND'] == '2m' && $data['COL_BAND_RX'] == '10m') { - $sat_name = '[A]_AO-7'; + $sat_name = 'AO-7[A]'; } if ($data['COL_BAND'] == '70cm' && $data['COL_BAND_RX'] == '2m') { - $sat_name = '[B]_AO-7'; + $sat_name = 'AO-7[B]'; } } else if ($data['COL_SAT_NAME'] == 'QO-100') { $sat_name = 'QO-100_NB'; @@ -940,6 +1046,10 @@ class Logbook_model extends CI_Model { 'COL_CNTY' => $uscounty ); + if ($this->exists_hrdlog_code($data['station_id'])) { + $data['COL_HRDLOG_QSO_UPLOAD_STATUS'] = 'M'; + } + if ($this->exists_qrz_api_key($data['station_id'])) { $data['COL_QRZCOM_QSO_UPLOAD_STATUS'] = 'M'; } @@ -1311,6 +1421,23 @@ class Logbook_model extends CI_Model { return $this->db->get(); } + /* + * Function returns the QSOs from the logbook, which have not been either marked as uploaded to hrdlog, or has been modified with an edit + */ + function get_hrdlog_qsos($station_id){ + $sql = 'select *, dxcc_entities.name as station_country from ' . $this->config->item('table_name') . ' thcv ' . + ' left join station_profile on thcv.station_id = station_profile.station_id' . + ' left outer join dxcc_entities on thcv.col_my_dxcc = dxcc_entities.adif' . + ' where thcv.station_id = ' . $station_id . + ' and (COL_HRDLOG_QSO_UPLOAD_STATUS is NULL + or COL_HRDLOG_QSO_UPLOAD_STATUS = "" + or COL_HRDLOG_QSO_UPLOAD_STATUS = "M" + or COL_HRDLOG_QSO_UPLOAD_STATUS = "N")'; + + $query = $this->db->query($sql); + return $query; + } + /* * Function returns the QSOs from the logbook, which have not been either marked as uploaded to qrz, or has been modified with an edit */ @@ -1371,6 +1498,25 @@ class Logbook_model extends CI_Model { return $this->db->query($sql); } + /* + * Function returns all the station_id's with HRDLOG Code + */ + function get_station_id_with_hrdlog_code() { + $sql = 'select station_id, hrdlog_code from station_profile + where coalesce(hrdlog_code, "") <> ""'; + + $query = $this->db->query($sql); + + $result = $query->result(); + + if ($result) { + return $result; + } + else { + return null; + } + } + /* * Function returns all the station_id's with QRZ API Key's */ @@ -2469,13 +2615,15 @@ class Logbook_model extends CI_Model { } /* Used to check if the qso is already in the database */ - function import_check($datetime, $callsign, $band) { + function import_check($datetime, $callsign, $band, $mode, $station_callsign) { $this->db->select('COL_PRIMARY_KEY, COL_TIME_ON, COL_CALL, COL_BAND'); $this->db->where('COL_TIME_ON >= DATE_ADD(DATE_FORMAT("'.$datetime.'", \'%Y-%m-%d %H:%i\' ), INTERVAL -15 MINUTE )'); $this->db->where('COL_TIME_ON <= DATE_ADD(DATE_FORMAT("'.$datetime.'", \'%Y-%m-%d %H:%i\' ), INTERVAL 15 MINUTE )'); $this->db->where('COL_CALL', $callsign); + $this->db->where('COL_STATION_CALLSIGN', $station_callsign); $this->db->where('COL_BAND', $band); + $this->db->where('COL_MODE', $mode); $query = $this->db->get($this->config->item('table_name')); @@ -2488,7 +2636,7 @@ class Logbook_model extends CI_Model { } } - function lotw_update($datetime, $callsign, $band, $qsl_date, $qsl_status, $state, $qsl_gridsquare, $iota, $cnty, $cqz, $ituz) { + function lotw_update($datetime, $callsign, $band, $qsl_date, $qsl_status, $state, $qsl_gridsquare, $iota, $cnty, $cqz, $ituz, $station_id) { $data = array( 'COL_LOTW_QSLRDATE' => $qsl_date, @@ -2517,6 +2665,7 @@ class Logbook_model extends CI_Model { $this->db->where('date_format(COL_TIME_ON, \'%Y-%m-%d %H:%i\') = "'.$datetime.'"'); $this->db->where('COL_CALL', $callsign); $this->db->where('COL_BAND', $band); + $this->db->where('station_id', $station_id); $this->db->update($this->config->item('table_name'), $data); unset($data); @@ -2587,9 +2736,10 @@ class Logbook_model extends CI_Model { * $markLoTW - used in ADIF import to mark QSOs as exported to LoTW when importing QSOs * $dxccAdif - used in ADIF import to determine if DXCC From ADIF is used, or if Cloudlog should try to guess * $markQrz - used in ADIF import to mark QSOs as exported to QRZ Logbook when importing QSOs + * $markHrd - used in ADIF import to mark QSOs as exported to HRDLog.net Logbook when importing QSOs * $skipexport - used in ADIF import to skip the realtime upload to QRZ Logbook when importing QSOs from ADIF */ - function import($record, $station_id = "0", $skipDuplicate = false, $markLotw = false, $dxccAdif = false, $markQrz = false, $skipexport = false, $operatorName = false, $apicall = false) { + function import($record, $station_id = "0", $skipDuplicate = false, $markLotw = false, $dxccAdif = false, $markQrz = false, $markHrd = false,$skipexport = false, $operatorName = false, $apicall = false) { // be sure that station belongs to user $CI =& get_instance(); $CI->load->model('Stations'); @@ -2928,12 +3078,19 @@ class Logbook_model extends CI_Model { $operatorName = (!empty($record['operator'])) ? $record['operator'] : ''; } - // If user checked to mark QSOs as uploaded to QRZ Logbook, or else we try to find info in ADIF import. + // If user checked to mark QSOs as uploaded to QRZ or HRDLog Logbook, or else we try to find info in ADIF import. + if ($markHrd != null) { + $input_hrdlog_qso_upload_status = 'Y'; + $input_hrdlog_qso_upload_date = $date = date("Y-m-d H:i:s", strtotime("now")); + } + if ($markQrz != null) { $input_qrzcom_qso_upload_status = 'Y'; $input_qrzcom_qso_upload_date = $date = date("Y-m-d H:i:s", strtotime("now")); } else { + $input_hrdlog_qso_upload_date = (!empty($record['hrdlog_qso_upload_date'])) ? $record['hrdlog_qso_upload_date'] : null; + $input_hrdlog_qso_upload_status = (!empty($record['hrdlog_qso_upload_status'])) ? $record['hrdlog_qso_upload_status'] : ''; $input_qrzcom_qso_upload_date = (!empty($record['qrzcom_qso_upload_date'])) ? $record['qrzcom_qso_upload_date'] : null; $input_qrzcom_qso_upload_status = (!empty($record['qrzcom_qso_upload_status'])) ? $record['qrzcom_qso_upload_status'] : ''; } @@ -3049,6 +3206,8 @@ class Logbook_model extends CI_Model { 'COL_PRECEDENCE' => (!empty($record['precedence'])) ? $record['precedence'] : '', 'COL_PROP_MODE' => (!empty($record['prop_mode'])) ? $record['prop_mode'] : '', 'COL_PUBLIC_KEY' => (!empty($record['public_key'])) ? $record['public_key'] : '', + 'COL_HRDLOG_QSO_UPLOAD_DATE' => $input_hrdlog_qso_upload_date, + 'COL_HRDLOG_QSO_UPLOAD_STATUS' => $input_hrdlog_qso_upload_status, 'COL_QRZCOM_QSO_UPLOAD_DATE' => $input_qrzcom_qso_upload_date, 'COL_QRZCOM_QSO_UPLOAD_STATUS' => $input_qrzcom_qso_upload_status, 'COL_QSL_RCVD' => $input_qsl_rcvd, @@ -3771,7 +3930,7 @@ class Logbook_model extends CI_Model { */ function find_correct_station_id($station_callsign, $my_gridsquare) { $sql = 'select station_id from station_profile - where station_callsign = "' . $station_callsign . '" and station_gridsquare like "%' . substr($my_gridsquare,0, 4) . '%"'; + where station_callsign = "' . $station_callsign . '" and station_gridsquare = "' .$my_gridsquare. '"'; $query = $this->db->query($sql); diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php index d94e1565..c6cfe6d4 100644 --- a/application/models/Logbookadvanced_model.php +++ b/application/models/Logbookadvanced_model.php @@ -56,6 +56,24 @@ class Logbookadvanced_model extends CI_Model { $binding[] = $searchCriteria['qslReceived']; } + if ($searchCriteria['lotwSent'] !== '') { + $conditions[] = "COL_LOTW_QSL_SENT = ?"; + $binding[] = $searchCriteria['lotwSent']; + } + if ($searchCriteria['lotwReceived'] !== '') { + $conditions[] = "COL_LOTW_QSL_RCVD = ?"; + $binding[] = $searchCriteria['lotwReceived']; + } + + if ($searchCriteria['eqslSent'] !== '') { + $conditions[] = "COL_EQSL_QSL_SENT = ?"; + $binding[] = $searchCriteria['eqslSent']; + } + if ($searchCriteria['eqslReceived'] !== '') { + $conditions[] = "COL_EQSL_QSL_RCVD = ?"; + $binding[] = $searchCriteria['eqslReceived']; + } + if ($searchCriteria['iota'] !== '') { $conditions[] = "COL_IOTA = ?"; $binding[] = $searchCriteria['iota']; @@ -71,6 +89,31 @@ class Logbookadvanced_model extends CI_Model { $binding[] = $searchCriteria['state']; } + if ($searchCriteria['cqzone'] !== '') { + $conditions[] = "COL_CQZ = ?"; + $binding[] = $searchCriteria['cqzone']; + } + + if ($searchCriteria['qslvia'] !== '') { + $conditions[] = "COL_QSL_VIA like ?"; + $binding[] = $searchCriteria['qslvia'].'%'; + } + + if ($searchCriteria['sota'] !== '') { + $conditions[] = "COL_SOTA_REF like ?"; + $binding[] = $searchCriteria['sota'].'%'; + } + + if ($searchCriteria['pota'] !== '') { + $conditions[] = "COL_POTA_REF like ?"; + $binding[] = $searchCriteria['pota'].'%'; + } + + if ($searchCriteria['wwff'] !== '') { + $conditions[] = "COL_WWFF_REF like ?"; + $binding[] = $searchCriteria['wwff'].'%'; + } + if ($searchCriteria['gridsquare'] !== '') { $conditions[] = "(COL_GRIDSQUARE like ? or COL_VUCC_GRIDS like ?)"; $binding[] = '%' . $searchCriteria['gridsquare'] . '%'; @@ -101,6 +144,11 @@ class Logbookadvanced_model extends CI_Model { 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 + LEFT OUTER JOIN ( + select count(*) as qslcount, qsoid + from qsl_images + group by qsoid + ) x on qsos.COL_PRIMARY_KEY = x.qsoid WHERE station_profile.user_id = ? $where ORDER BY qsos.COL_TIME_ON desc, qsos.COL_PRIMARY_KEY desc @@ -110,12 +158,12 @@ class Logbookadvanced_model extends CI_Model { $data = $this->db->query($sql, $binding); $results = $data->result('array'); - + $qsos = []; foreach ($results as $data) { $qsos[] = new QSO($data); } - + return $qsos; } @@ -132,11 +180,17 @@ class Logbookadvanced_model extends CI_Model { $order = $this->getSortorder($sortorder); $sql = " - SELECT *, dxcc_entities.name AS station_country + SELECT qsos.*, d2.*, lotw_users.*, station_profile.*, x.qslcount, dxcc_entities.name AS station_country 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_MY_DXCC = dxcc_entities.adif + LEFT OUTER JOIN dxcc_entities d2 ON qsos.COL_DXCC = d2.adif LEFT OUTER JOIN lotw_users ON qsos.col_call=lotw_users.callsign + LEFT OUTER JOIN ( + select count(*) as qslcount, qsoid + from qsl_images + group by qsoid + ) x on qsos.COL_PRIMARY_KEY = x.qsoid WHERE station_profile.user_id = ? $where $order @@ -211,7 +265,25 @@ class Logbookadvanced_model extends CI_Model { ); $this->db->where_in('COL_PRIMARY_KEY', json_decode($ids, true)); $this->db->update($this->config->item('table_name'), $data); - + + return array('message' => 'OK'); + } + } + + public function updateQslReceived($ids, $user_id, $method, $sent) { + $this->load->model('user_model'); + + if(!$this->user_model->authorize(2)) { + return array('message' => 'Error'); + } else { + $data = array( + 'COL_QSLRDATE' => date('Y-m-d H:i:s'), + 'COL_QSL_RCVD' => $sent, + 'COL_QSL_RCVD_VIA' => $method + ); + $this->db->where_in('COL_PRIMARY_KEY', json_decode($ids, true)); + $this->db->update($this->config->item('table_name'), $data); + return array('message' => 'OK'); } } @@ -263,19 +335,19 @@ class Logbookadvanced_model extends CI_Model { $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; } $modes = array(); - + $this->db->select('distinct col_mode, coalesce(col_submode, "") col_submode', FALSE); $this->db->where_in('station_id', $logbooks_locations_array); $this->db->order_by('col_mode, col_submode', 'ASC'); $query = $this->db->get($this->config->item('table_name')); - + foreach($query->result() as $mode){ if ($mode->col_submode == null || $mode->col_submode == "") { array_push($modes, $mode->col_mode); diff --git a/application/models/LotwCert.php b/application/models/LotwCert.php index 1d1fd03d..1dab4515 100644 --- a/application/models/LotwCert.php +++ b/application/models/LotwCert.php @@ -6,7 +6,7 @@ class LotwCert extends CI_Model { |-------------------------------------------------------------------------- | Function: lotw_certs |-------------------------------------------------------------------------- - | + | | Returns all lotw_certs for a selected user via the $user_id parameter | */ @@ -17,7 +17,7 @@ class LotwCert extends CI_Model { $this->db->join('dxcc_entities','lotw_certs.cert_dxcc_id = dxcc_entities.adif','left'); $this->db->order_by('cert_dxcc', 'ASC'); $query = $this->db->get('lotw_certs'); - + return $query; } @@ -46,7 +46,7 @@ class LotwCert extends CI_Model { 'date_created' => $date_created, 'date_expires' => $date_expires, 'qso_start_date' => $qso_start_date, - 'qso_end_date' => $qso_end_date, + 'qso_end_date' => $qso_end_date . ' 23:59:59', 'cert_key' => $cert_key, 'cert' => $general_cert, ); @@ -60,7 +60,7 @@ class LotwCert extends CI_Model { 'date_created' => $date_created, 'date_expires' => $date_expires, 'qso_start_date' => $qso_start_date, - 'qso_end_date' => $qso_end_date, + 'qso_end_date' => $qso_end_date . ' 23:59:59', 'cert_key' => $cert_key, 'cert' => $general_cert ); @@ -90,9 +90,9 @@ class LotwCert extends CI_Model { return "Updated"; } - + function empty_table($table) { - $this->db->empty_table($table); + $this->db->empty_table($table); } function lotw_cert_expired($user_id, $date) { diff --git a/application/models/Pota.php b/application/models/Pota.php index 117a8c42..1c5c8a40 100644 --- a/application/models/Pota.php +++ b/application/models/Pota.php @@ -15,6 +15,8 @@ class Pota extends CI_Model { $bandslots = $this->bands->get_worked_bands('pota'); + if(!$bandslots) return null; + $this->db->where_in("station_id", $logbooks_locations_array); $this->db->where_in("col_band", $bandslots); $this->db->order_by("COL_POTA_REF", "ASC"); diff --git a/application/models/Sota.php b/application/models/Sota.php index 6d47334e..46d7e5f5 100644 --- a/application/models/Sota.php +++ b/application/models/Sota.php @@ -15,6 +15,8 @@ class Sota extends CI_Model { $bandslots = $this->bands->get_worked_bands('sota'); + if(!$bandslots) return null; + $this->db->where_in("station_id", $logbooks_locations_array); $this->db->where_in("col_band", $bandslots); $this->db->order_by("COL_SOTA_REF", "ASC"); diff --git a/application/models/Stations.php b/application/models/Stations.php index 7d9e8823..b780b0a9 100644 --- a/application/models/Stations.php +++ b/application/models/Stations.php @@ -23,9 +23,12 @@ class Stations extends CI_Model { return $this->db->get(); } - function all_of_user() { + function all_of_user($userid = null) { + if ($userid == null) { + $userid=$this->session->userdata('user_id'); // Fallback to session-uid, if userid is omitted + } $this->db->select('station_profile.*, dxcc_entities.name as station_country, dxcc_entities.end as dxcc_end'); - $this->db->where('user_id', $this->session->userdata('user_id')); + $this->db->where('user_id', $userid); $this->db->join('dxcc_entities','station_profile.station_dxcc = dxcc_entities.adif','left outer'); return $this->db->get('station_profile'); } @@ -88,9 +91,11 @@ class Stations extends CI_Model { 'station_cq' => xss_clean($this->input->post('station_cq', true)), 'station_itu' => xss_clean($this->input->post('station_itu', true)), 'state' => $state, - 'eqslqthnickname' => xss_clean($this->input->post('eqslnickname', true)), - 'qrzapikey' => xss_clean($this->input->post('qrzapikey', true)), - 'qrzrealtime' => xss_clean($this->input->post('qrzrealtime', true)), + 'eqslqthnickname' => xss_clean($this->input->post('eqslnickname', true)), + 'hrdlog_code' => xss_clean($this->input->post('hrdlog_code', true)), + 'hrdlogrealtime' => xss_clean($this->input->post('hrdlogrealtime', true)), + 'qrzapikey' => xss_clean($this->input->post('qrzapikey', true)), + 'qrzrealtime' => xss_clean($this->input->post('qrzrealtime', true)), 'oqrs' => xss_clean($this->input->post('oqrs', true)), 'oqrs_email' => xss_clean($this->input->post('oqrsemail', true)), 'oqrs_text' => xss_clean($this->input->post('oqrstext', true)), @@ -130,8 +135,10 @@ class Stations extends CI_Model { 'station_itu' => xss_clean($this->input->post('station_itu', true)), 'state' => $state, 'eqslqthnickname' => xss_clean($this->input->post('eqslnickname', true)), - 'qrzapikey' => xss_clean($this->input->post('qrzapikey', true)), - 'qrzrealtime' => xss_clean($this->input->post('qrzrealtime', true)), + 'hrdlog_code' => xss_clean($this->input->post('hrdlog_code', true)), + 'hrdlogrealtime' => xss_clean($this->input->post('hrdlogrealtime', true)), + 'qrzapikey' => xss_clean($this->input->post('qrzapikey', true)), + 'qrzrealtime' => xss_clean($this->input->post('qrzrealtime', true)), 'oqrs' => xss_clean($this->input->post('oqrs', true)), 'oqrs_email' => xss_clean($this->input->post('oqrsemail', true)), 'oqrs_text' => xss_clean($this->input->post('oqrstext', true)), @@ -339,6 +346,35 @@ class Stations extends CI_Model { } } + function stations_with_hrdlog_code() { + $sql = "select station_profile.station_id, station_profile.station_profile_name, station_profile.station_callsign, modc.modcount, notc.notcount, totc.totcount + from station_profile + left outer join ( + select count(*) modcount, station_id + from ". $this->config->item('table_name') . + " where COL_HRDLOG_QSO_UPLOAD_STATUS = 'M' + group by station_id + ) as modc on station_profile.station_id = modc.station_id + left outer join ( + select count(*) notcount, station_id + from " . $this->config->item('table_name') . + " where (coalesce(COL_HRDLOG_QSO_UPLOAD_STATUS, '') = '' + or COL_HRDLOG_QSO_UPLOAD_STATUS = 'N') + group by station_id + ) as notc on station_profile.station_id = notc.station_id + left outer join ( + select count(*) totcount, station_id + from " . $this->config->item('table_name') . + " where COL_HRDLOG_QSO_UPLOAD_STATUS = 'Y' + group by station_id + ) as totc on station_profile.station_id = totc.station_id + where coalesce(station_profile.hrdlog_code, '') <> '' + and station_profile.user_id = " . $this->session->userdata('user_id'); + $query = $this->db->query($sql); + + return $query; + } + function stations_with_qrz_api_key() { $sql = "select station_profile.station_id, station_profile.station_profile_name, station_profile.station_callsign, modc.modcount, notc.notcount, totc.totcount from station_profile @@ -372,14 +408,14 @@ class Stations extends CI_Model { $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 ( + LEFT OUTER 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 AND qsos.COL_SAT_NAME = 'QO-100' GROUP BY qsos.station_id ) notc ON station_profile.station_id = notc.station_id - INNER JOIN ( + LEFT JOIN ( SELECT qsos.station_id, COUNT(qsos.COL_PRIMARY_KEY) c FROM %s qsos WHERE qsos.COL_SAT_NAME = 'QO-100' diff --git a/application/models/User_model.php b/application/models/User_model.php index d58cf883..dc9eff52 100644 --- a/application/models/User_model.php +++ b/application/models/User_model.php @@ -123,7 +123,8 @@ class User_Model extends CI_Model { function add($username, $password, $email, $type, $firstname, $lastname, $callsign, $locator, $timezone, $measurement, $user_date_format, $user_stylesheet, $user_qth_lookup, $user_sota_lookup, $user_wwff_lookup, $user_pota_lookup, $user_show_notes, $user_column1, $user_column2, $user_column3, $user_column4, $user_column5, - $user_show_profile_image, $user_previous_qsl_type, $user_amsat_status_upload) { + $user_show_profile_image, $user_previous_qsl_type, $user_amsat_status_upload, $user_mastodon_url, + $user_gridmap_default_band, $user_gridmap_confirmation) { // Check that the user isn't already used if(!$this->exists($username)) { $data = array( @@ -152,6 +153,9 @@ class User_Model extends CI_Model { 'user_show_profile_image' => xss_clean($user_show_profile_image), 'user_previous_qsl_type' => xss_clean($user_previous_qsl_type), 'user_amsat_status_upload' => xss_clean($user_amsat_status_upload), + 'user_mastodon_url' => xss_clean($user_mastodon_url), + 'user_gridmap_default_band' => xss_clean($user_gridmap_default_band), + 'user_gridmap_confirmation' => xss_clean($user_gridmap_confirmation), ); // Check the password is valid @@ -208,6 +212,9 @@ class User_Model extends CI_Model { 'user_show_profile_image' => xss_clean($fields['user_show_profile_image']), 'user_previous_qsl_type' => xss_clean($fields['user_previous_qsl_type']), 'user_amsat_status_upload' => xss_clean($fields['user_amsat_status_upload']), + 'user_mastodon_url' => xss_clean($fields['user_mastodon_url']), + 'user_gridmap_default_band' => xss_clean($fields['user_gridmap_default_band']), + 'user_gridmap_confirmation' => (isset($fields['user_gridmap_confirmation_qsl']) ? 'Q' : '').(isset($fields['user_gridmap_confirmation_lotw']) ? 'L' : '').(isset($fields['user_gridmap_confirmation_eqsl']) ? 'E' : ''), ); // Check to see if the user is allowed to change user levels @@ -328,6 +335,9 @@ class User_Model extends CI_Model { 'user_column5' => isset($u->row()->user_column5) ? $u->row()->user_column5: 'Country', 'user_previous_qsl_type' => isset($u->row()->user_previous_qsl_type) ? $u->row()->user_previous_qsl_type: 0, 'user_amsat_status_upload' => isset($u->row()->user_amsat_status_upload) ? $u->row()->user_amsat_status_upload: 0, + 'user_mastodon_url' => $u->row()->user_mastodon_url, + 'user_gridmap_default_band' => $u->row()->user_gridmap_default_band, + 'user_gridmap_confirmation' => $u->row()->user_gridmap_confirmation, 'active_station_logbook' => $u->row()->active_station_logbook, ); diff --git a/application/models/Wwff.php b/application/models/Wwff.php index 93908d7e..e15584c3 100644 --- a/application/models/Wwff.php +++ b/application/models/Wwff.php @@ -15,6 +15,8 @@ class Wwff extends CI_Model { $bandslots = $this->bands->get_worked_bands('wwff'); + if(!$bandslots) return null; + $this->db->where_in("station_id", $logbooks_locations_array); $this->db->where_in("col_band", $bandslots); $this->db->order_by("COL_WWFF_REF", "ASC"); diff --git a/application/views/adif/import.php b/application/views/adif/import.php index c2c36fac..3b310065 100644 --- a/application/views/adif/import.php +++ b/application/views/adif/import.php @@ -59,6 +59,16 @@ +
+
+
+ + +
+
Select if ADIF being imported does not contain this information.
+
+
+
diff --git a/application/views/eqsl/import.php b/application/views/eqsl/import.php index 1808f11e..2c9edf72 100644 --- a/application/views/eqsl/import.php +++ b/application/views/eqsl/import.php @@ -29,10 +29,18 @@ -

+

Upload the Exported ADIF file from eQSL from the Download Inbox page, to mark QSOs as confirmed on eQSL.

Important Log files must have the file type .adi

+

+

Choose Station(location) eQSL File belongs to:

+


diff --git a/application/views/gridmap/index.php b/application/views/gridmap/index.php index 93a2cdeb..62d473d4 100644 --- a/application/views/gridmap/index.php +++ b/application/views/gridmap/index.php @@ -6,9 +6,9 @@ padding: 6px 8px; font: 14px Arial, Helvetica, sans-serif; background: white; - background: rgba(255, 255, 255, 0.8); line-height: 24px; color: #555; + border-radius: 10px; } .legend h4 { text-align: center; @@ -25,7 +25,19 @@ height: 18px; float: left; margin: 0 8px 0 0; - opacity: 0.7; +} +.coordinates { + justify-content: center; + align-items: stretch; +} +.cohidden { + display:none; +} +#latDeg, #lngDeg { + width: 170px; +} +#locator, #distance, #bearing { + width: 120px; }
@@ -38,8 +50,12 @@ @@ -67,15 +83,27 @@
- + '; ?>
- + '; ?>
- + '; ?>
@@ -94,14 +122,27 @@
+
+
Latitude:
+
+
Longitude:
+
+
Gridsquare:
+
+
Distance:
+
+
Bearing:
+
+
\ No newline at end of file + diff --git a/application/views/hrdlog/export.php b/application/views/hrdlog/export.php new file mode 100644 index 00000000..85767b58 --- /dev/null +++ b/application/views/hrdlog/export.php @@ -0,0 +1,96 @@ + +
+ +

+ +
+
+ + +
+ +
+
+
+

Here you can see and upload all QSOs which have not been previously uploaded to a HRDLog logbook.

+

You need to set a HRDLog Logbook API Code in your station profile. Only station profiles with an API Key set are displayed.

+

The Code can be demanded at http://www.hrdlog.net/EditUser.aspx

+

Warning This 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 ''; + } + echo '
Profile nameStation callsignEdited QSOs not uploadedTotal QSOs not uploadedTotal QSOs uploadedActions
' . $station->station_profile_name . '' . $station->station_callsign . '' . $station->modcount . '' . $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/hrdlog/mark_hrdlog.php b/application/views/hrdlog/mark_hrdlog.php new file mode 100644 index 00000000..629e1efe --- /dev/null +++ b/application/views/hrdlog/mark_hrdlog.php @@ -0,0 +1,22 @@ +
+
+ session->flashdata('message')) { ?> + +
+

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

+
+ + +
+
+ QSOs marked +
+
+

Yay, it's done!

+

The QSOs are marked as exported to HRDLog Logbook.

+
+
+ + +
+ diff --git a/application/views/interface_assets/footer.php b/application/views/interface_assets/footer.php index cb3e3c63..574f57fb 100644 --- a/application/views/interface_assets/footer.php +++ b/application/views/interface_assets/footer.php @@ -71,7 +71,7 @@ function load_was_map() { -uri->segment(1) == "adif" || $this->uri->segment(1) == "qrz" || $this->uri->segment(1) == "webadif") { ?> +uri->segment(1) == "adif" || $this->uri->segment(1) == "qrz" || $this->uri->segment(1) == "hrdlog" ||$this->uri->segment(1) == "webadif") { ?> @@ -1235,97 +1235,110 @@ $(document).on('keypress',function(e) { @@ -1702,6 +1715,9 @@ $(document).ready(function(){ + uri->segment(1) == "hrdlog") { ?> + + uri->segment(1) == "qrz") { ?> @@ -2007,7 +2023,7 @@ $(document).ready(function(){ success: function (dataofconfirm) { $(".edit-dialog").modal('hide'); $(".qso-dialog").modal('hide'); - uri->segment(1) != "search" && $this->uri->segment(2) != "filter" && $this->uri->segment(1) != "qso") { ?>location.reload(); + uri->segment(1) != "search" && $this->uri->segment(2) != "filter" && $this->uri->segment(1) != "qso" && $this->uri->segment(1) != "logbookadvanced") { ?>location.reload(); }, error: function(xhr, status, error) { console.log(xhr.responseText); @@ -2398,7 +2414,7 @@ function viewEqsl(picture, callsign) { $("#qslcardfront").val(null); } - } else { + } else if (data.status.front.status != '') { $("#qslupload").append('
×Front QSL Card:' + data.status.front.error + '
'); @@ -2436,7 +2452,7 @@ function viewEqsl(picture, callsign) { $(".carouselExampleIndicators").carousel(); $("#qslcardback").val(null); } - } else { + } else if (data.status.back.status != '') { $("#qslupload").append('
×\nBack QSL Card: ' + data.status.back.error + '
'); diff --git a/application/views/interface_assets/header.php b/application/views/interface_assets/header.php index 2cd82483..df346f2b 100644 --- a/application/views/interface_assets/header.php +++ b/application/views/interface_assets/header.php @@ -260,6 +260,7 @@ $oqrs_requests = $CI->oqrs_model->oqrs_requests($location_list); + diff --git a/application/views/logbookadvanced/index.php b/application/views/logbookadvanced/index.php index ed417d8b..13528f30 100644 --- a/application/views/logbookadvanced/index.php +++ b/application/views/logbookadvanced/index.php @@ -15,7 +15,9 @@
+
" method="post"> +
@@ -53,7 +55,7 @@
+ + '. $i .''; + } + ?> + ?> + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
- - + + + + + +
-
-
- - +
+ + +
+
+ + +
+
+ + +
+
+ + + + + + + + +
- +
+ +
+
+ With selected : + + + + + + + + + + + + + + +
+
+
- With selected : - - - - - - - - - - - - + Quick search with selected : + + + + + + + + + + +
+
+
+
+ + + + + + + +
+
+ @@ -228,6 +335,4 @@
- -
diff --git a/application/views/qrz/export.php b/application/views/qrz/export.php index 0bb24e4f..1f51b4c8 100644 --- a/application/views/qrz/export.php +++ b/application/views/qrz/export.php @@ -21,7 +21,7 @@

Here you can see and upload all QSOs which have not been previously uploaded to a QRZ logbook.

You need to set a QRZ Logbook API key in your station profile. Only station profiles with an API Key set are displayed.

-

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

+

Warning This might take a while as QSO uploads are processed sequentially.

result()) { @@ -61,9 +61,9 @@

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

diff --git a/application/views/qslcard/qslcarousel.php b/application/views/qslcard/qslcarousel.php new file mode 100644 index 00000000..78aad712 --- /dev/null +++ b/application/views/qslcard/qslcarousel.php @@ -0,0 +1,38 @@ + + + + Previous + + + + Next + +
\ No newline at end of file diff --git a/application/views/station_profile/create.php b/application/views/station_profile/create.php index 3350451e..5f6efd3e 100644 --- a/application/views/station_profile/create.php +++ b/application/views/station_profile/create.php @@ -249,6 +249,20 @@ eQSL QTH Nickname.
+ +
+
+ + Find your API key on HRDLog Userprofile +
+
+ +
+
+ diff --git a/application/views/station_profile/edit.php b/application/views/station_profile/edit.php index f2809222..d263e17d 100644 --- a/application/views/station_profile/edit.php +++ b/application/views/station_profile/edit.php @@ -371,6 +371,27 @@
+
+
+
+
HRDLog.net
+
+
+ + hrdlog_code; } ?>"> + Create your API Code on HRDLog.net Userprofile page +
+
+ + +
+
+
+
+
diff --git a/application/views/user/add.php b/application/views/user/add.php index d3a0492e..a7bd8897 100644 --- a/application/views/user/add.php +++ b/application/views/user/add.php @@ -514,6 +514,73 @@
+
+
+
+ +
+
+
+ + +
Main URL of your Mastodon server, e.g. https://radiosocial.de
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+ + + +
+
+ +
+ '; ?> + +
+
+ '; ?> + +
+
+ '; ?> + +
+
+
+
+
diff --git a/application/views/user/edit.php b/application/views/user/edit.php index ff3586c2..23c1d781 100644 --- a/application/views/user/edit.php +++ b/application/views/user/edit.php @@ -476,7 +476,7 @@
- +
@@ -512,7 +512,73 @@
+
+
+
+ +
+
+
+ + +
Main URL of your Mastodon server, e.g. https://radiosocial.de
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ + +
+
+ +
+ '; ?> + +
+
+ '; ?> + +
+
+ '; ?> + +
+
+
+
+
diff --git a/application/views/view_log/qso.php b/application/views/view_log/qso.php index 0071fc06..e036b4e5 100644 --- a/application/views/view_log/qso.php +++ b/application/views/view_log/qso.php @@ -407,6 +407,7 @@ ?>
+ session->userdata('user_mastodon_url') != null) { echo '
'; } ?> @@ -508,70 +509,61 @@

-
+
+
+
-
- - +
+ + +
+ + + + +
+
+
+ + +
+ +
- -
- - -
- - - - - -
+ +

+

+
+ + + + + +
+
+

+

+
+ + + + + + +
+
- + load->view('qslcard/qslcarousel', $qslimages); ?>
eqsl_image_file .'" alt="QSL picture #'. $i++.'">'; + if ($row->eqsl_image_file != null) { + echo 'QSL picture #'. $i++.''; + } ?>
result()) { + $queuedqsos = 0; + foreach ($station_profile->result() as $count) { // Fills the table with the data + $queuedqsos += $count->notcount; + } + if ($queuedqsos > 0) { ?>

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

Warning This might take a while as QSO uploads are processed sequentially.

@@ -41,15 +46,25 @@ '; foreach ($station_profile->result() as $station) { // Fills the table with the data - echo ''; - echo '' . $station->station_profile_name . ''; - echo '' . $station->station_callsign . ''; - echo '' . $station->notcount . ''; - echo '' . $station->totcount . ''; - echo ''; - echo ''; + if ($station->notcount != null) { + echo ''; + echo '' . $station->station_profile_name . ''; + echo '' . $station->station_callsign . ''; + echo '' . $station->notcount . ''; + echo '' . $station->totcount . ''; + echo ''; + echo ''; + } } echo ''; + } else { + ?> +
+ There are currently no outstanding QSOs that need to be uploaded to the QO-100 Dx Club's API.
+ Go ahead and turn on your QO-100 station! +
+ 0 */1 * * * curl --silent /lotw/lotw_upload &>/dev/null

+ # Upload QSOs to HRDLog.net Logbook (ignore cron job if this integration is not required)
+ 0 */6 * * * curl --silent /hrdlog/upload &>/dev/null
+
# Upload QSOs to QRZ Logbook (ignore cron job if this integration is not required)
0 */6 * * * curl --silent /qrz/upload &>/dev/null

@@ -153,4 +156,4 @@

- \ No newline at end of file + diff --git a/assets/js/leaflet/geocoding.js b/assets/js/leaflet/geocoding.js new file mode 100644 index 00000000..0749c1b2 --- /dev/null +++ b/assets/js/leaflet/geocoding.js @@ -0,0 +1,127 @@ +const isValidLocatorString = locatorString => locatorString.match(/^[A-Ra-r][A-Ra-r]\d\d[A-Xa-x][A-Xa-x]/) !== null; +const charToNumber = char => char.toUpperCase().charCodeAt(0) - CHAR_CODE_OFFSET; +const numberToChar = number => String.fromCharCode(number + CHAR_CODE_OFFSET); +const CHAR_CODE_OFFSET = 65; +const degToRad = deg => (deg % 360) * Math.PI / 180; +const radToDeg = rad => (rad / Math.PI *180) % 360; +const isValidPoint = (lat, lng) => (lat >= -90 && lat <= 90) && (lng >= -180 && lng <= 180); + +function ConvertDDToDMS(lat, lng) { + var LatLng = []; + + if (lng < -180) { + lng = lng + 360; + } + if (lng > 180) { + lng = lng - 360; + } + + LatLng['latDeg'] = (lat < 0 ? "S" : "N") + " " + pad((0 |(lat < 0 ? (lat = -lat) : lat)), 2) + "° " + pad(0 | (((lat += 1e-9) % 1) * 60),2) + "' " + ((0 | (((lat * 60) % 1) * 6000)) / 100) + "\""; + + LatLng['lngDeg'] = (lng < 0 ? "W" : "E") + " " + pad((0 | (lng < 0 ? (lng = -lng) : lng)), 3) + "° " + pad(0 | (((lng += 1e-9) % 1) * 60),2) + "' " + ((0 | (((lng * 60) % 1) * 6000)) / 100) + "\""; + + return LatLng; +} + +function pad(n, width, z) { + z = z || '0'; + n = n + ''; + return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; +} + +const latLngToLocator = (lat, lng) => { + if (lng < -180) { + lng = lng + 360; + } + if (lng > 180) { + lng = lng - 360; + } + if (!isValidPoint(lat, lng)) { + throw new Error('Input is not a valid coordinate'); + } + + const longitude = lng + 180; + const latitude = lat + 90; + + const fieldLng = numberToChar(Math.floor(longitude / 20)); + const fieldLat = numberToChar(Math.floor(latitude / 10)); + + const squareLng = Math.floor(longitude % 20 / 2); + const squareLat = Math.floor(latitude % 10); + + const subsquareLng = numberToChar(Math.floor((longitude % 20 % 2) * 12)).toLowerCase(); + const subsquareLat = numberToChar((latitude % 10 - squareLat) * 24).toLowerCase(); + + return fieldLng + fieldLat + squareLng + squareLat + subsquareLng + subsquareLat; +}; + +function onMapMove(event) { + var LatLng = event.latlng; + var lat = LatLng.lat; + var lng = LatLng.lng; + var LatLng2 = ConvertDDToDMS(lat, lng); + $('#latDeg').html(LatLng2.latDeg); + $('#lngDeg').html(LatLng2.lngDeg); + var locator = latLngToLocator(lat,lng); + $('#locator').html(locator); + var distance = bearingDistance(homegrid, locator); + + $('#bearing').html(distance.deg + ' deg'); + $('#distance').html(Math.round(distance.km * 10) / 10 + ' km'); +}; + +const bearingDistance = (from, to) => { + const fromCoords = locatorToLatLng(from); + const toCoords = locatorToLatLng(to); + const dLat = degToRad(toCoords[0] - fromCoords[0]); + const dLon = degToRad(toCoords[1] - fromCoords[1]); + const fromLat = degToRad(fromCoords[0]); + const toLat = degToRad(toCoords[0]); + const a = Math.pow(Math.sin(dLat / 2), 2) + Math.pow(Math.sin(dLon / 2), 2) * Math.cos(fromLat) * Math.cos(toLat); + const b = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + + const y = (dLon) * Math.cos(fromLat) * Math.cos(toLat); + const x = Math.sin(toLat) - Math.sin(fromLat) * Math.cos(b); + + let az = Math.atan2(y, x); + + if (az < 0) { + az += 2 * Math.PI; + } + + return { + km: b * 6371, + deg: calcAngle(fromCoords, toCoords) + }; +}; + +var calcAngle = function (p1, p2) { + var lat1 = p1[0] / 180 * Math.PI; + var lat2 = p2[0] / 180 * Math.PI; + var lng1 = p1[1] / 180 * Math.PI; + var lng2 = p2[1] / 180 * Math.PI; + var y = Math.sin(lng2-lng1) * Math.cos(lat2); + var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(lng2-lng1); + var brng = (Math.atan2(y, x) * 180 / Math.PI + 360).toFixed(0); + + return (brng % 360); +} + +const locatorToLatLng = (locatorString) => { + locatorString += 'll'; // append subsquare in case is 4 chars long... If not, is ignored. + if (!isValidLocatorString(locatorString)) { + throw new Error('Input is not valid locator string'); + } + + const fieldLng = charToNumber(locatorString[0]) * 20; + const fieldLat = charToNumber(locatorString[1]) * 10; + const squareLng = Number.parseInt(locatorString[2]) * 2; + const squareLat = Number.parseInt(locatorString[3]); + const subsquareLng = (charToNumber(locatorString[4]) + 0.5) / 12; + const subsquareLat = (charToNumber(locatorString[5]) + 0.5) / 24; + + return [ + fieldLat + squareLat + subsquareLat - 90, + fieldLng + squareLng + subsquareLng - 180 + ]; +}; \ No newline at end of file diff --git a/assets/js/sections/common.js b/assets/js/sections/common.js index ceb493e5..030a298f 100644 --- a/assets/js/sections/common.js +++ b/assets/js/sections/common.js @@ -1,4 +1,6 @@ function qsl_rcvd(id, method) { + $(".ld-ext-right-r-"+method).addClass('running'); + $(".ld-ext-right-r-"+method).prop('disabled', true); $.ajax({ url: base_url + 'index.php/qso/qsl_rcvd_ajax', type: 'post', @@ -6,6 +8,8 @@ function qsl_rcvd(id, method) { 'method': method }, success: function(data) { + $(".ld-ext-right-r-"+method).removeClass('running'); + $(".ld-ext-right-r-"+method).prop('disabled', false); if (data.message == 'OK') { $("#qsl_" + id).find("span:eq(1)").attr('class', 'qsl-green'); // Paints arrow green $(".qsl_rcvd_" + id).remove(); // removes choice from menu @@ -39,6 +43,8 @@ function qsl_sent(id, method) { // Function: qsl_requested // Marks QSL card requested against the QSO. function qsl_requested(id, method) { + $(".ld-ext-right-t-"+method).addClass('running'); + $(".ld-ext-right-t-"+method).prop('disabled', true); $.ajax({ url: base_url + 'index.php/qso/qsl_requested_ajax', type: 'post', @@ -46,6 +52,8 @@ function qsl_requested(id, method) { 'method': method }, success: function(data) { + $(".ld-ext-right-t-"+method).removeClass('running'); + $(".ld-ext-right-t-"+method).prop('disabled', false); if (data.message == 'OK') { $("#qsl_" + id).find("span:eq(0)").attr('class', 'qsl-yellow'); // Paints arrow yellow } @@ -59,6 +67,8 @@ function qsl_requested(id, method) { // Function: qsl_ignore // Marks QSL card ignore against the QSO. function qsl_ignore(id, method) { + $(".ld-ext-right-ignore").addClass('running'); + $(".ld-ext-right-ignore").prop('disabled', true); $.ajax({ url: base_url + 'index.php/qso/qsl_ignore_ajax', type: 'post', @@ -66,6 +76,8 @@ function qsl_ignore(id, method) { 'method': method }, success: function(data) { + $(".ld-ext-right-ignore").removeClass('running'); + $(".ld-ext-right-ignore").prop('disabled', false); if (data.message == 'OK') { $("#qsl_" + id).find("span:eq(0)").attr('class', 'qsl-grey'); // Paints arrow grey } @@ -358,7 +370,7 @@ function validateLocator(locator) { } // This displays the dialog with the form and it's where the resulttable is displayed -function spawnLookupModal() { +function spawnLookupModal(searchphrase, searchtype) { $.ajax({ url: base_url + 'index.php/lookup', type: 'post', @@ -372,38 +384,22 @@ function spawnLookupModal() { onshown: function(dialog) { $('#quicklookuptype').change(function(){ var type = $('#quicklookuptype').val(); - if (type == "dxcc") { - $('#quicklookupdxcc').show(); - $('#quicklookupiota').hide(); - $('#quicklookupcqz').hide(); - $('#quicklookupwas').hide(); - $('#quicklookuptext').hide(); - } else if (type == "iota") { - $('#quicklookupiota').show(); - $('#quicklookupdxcc').hide(); - $('#quicklookupcqz').hide(); - $('#quicklookupwas').hide(); - $('#quicklookuptext').hide(); - } else if (type == "vucc" || type == "sota" || type == "wwff") { - $('#quicklookuptext').show(); - $('#quicklookupiota').hide(); - $('#quicklookupdxcc').hide(); - $('#quicklookupcqz').hide(); - $('#quicklookupwas').hide(); - } else if (type == "cq") { - $('#quicklookupcqz').show(); - $('#quicklookupiota').hide(); - $('#quicklookupdxcc').hide(); - $('#quicklookupwas').hide(); - $('#quicklookuptext').hide(); - } else if (type == "was") { - $('#quicklookupwas').show(); - $('#quicklookupcqz').hide(); - $('#quicklookupiota').hide(); - $('#quicklookupdxcc').hide(); - $('#quicklookuptext').hide(); - } + changeLookupType(type); }); + if (searchtype !== undefined) { + $('#quicklookuptype').val(searchtype); + if (searchtype == 'dxcc') { + $("#quicklookupdxcc").val(searchphrase); + } else if (searchtype == 'iota') { + $("#quicklookupiota").val(searchphrase); + } else if (searchtype == 'cq') { + $("#quicklookupcqz").val(searchphrase); + } else { + $("#quicklookuptext").val(searchphrase); + } + changeLookupType(searchtype); + getLookupResult(this.form); + } }, buttons: [{ label: 'Close', @@ -416,6 +412,40 @@ function spawnLookupModal() { }); } +function changeLookupType(type) { + if (type == "dxcc") { + $('#quicklookupdxcc').show(); + $('#quicklookupiota').hide(); + $('#quicklookupcqz').hide(); + $('#quicklookupwas').hide(); + $('#quicklookuptext').hide(); + } else if (type == "iota") { + $('#quicklookupiota').show(); + $('#quicklookupdxcc').hide(); + $('#quicklookupcqz').hide(); + $('#quicklookupwas').hide(); + $('#quicklookuptext').hide(); + } else if (type == "vucc" || type == "sota" || type == "wwff") { + $('#quicklookuptext').show(); + $('#quicklookupiota').hide(); + $('#quicklookupdxcc').hide(); + $('#quicklookupcqz').hide(); + $('#quicklookupwas').hide(); + } else if (type == "cq") { + $('#quicklookupcqz').show(); + $('#quicklookupiota').hide(); + $('#quicklookupdxcc').hide(); + $('#quicklookupwas').hide(); + $('#quicklookuptext').hide(); + } else if (type == "was") { + $('#quicklookupwas').show(); + $('#quicklookupcqz').hide(); + $('#quicklookupiota').hide(); + $('#quicklookupdxcc').hide(); + $('#quicklookuptext').hide(); + } +} + // This function executes the call to the backend for fetching queryresult and displays the table in the dialog function getLookupResult() { $(".ld-ext-right").addClass('running'); @@ -457,3 +487,31 @@ function getDxccResult(dxcc, name) { } }); } + +function displayQsl(id) { + $.ajax({ + url: base_url + 'index.php/qsl/viewQsl', + type: 'post', + data: { + id: id, + }, + success: function (html) { + BootstrapDialog.show({ + title: 'QSL Card', + size: BootstrapDialog.SIZE_WIDE, + cssClass: 'lookup-dialog', + nl2br: false, + message: html, + onshown: function(dialog) { + + }, + buttons: [{ + label: 'Close', + action: function (dialogItself) { + dialogItself.close(); + } + }] + }); + } + }); +} diff --git a/assets/js/sections/contesting.js b/assets/js/sections/contesting.js index c2b0b2d9..9675cbcb 100644 --- a/assets/js/sections/contesting.js +++ b/assets/js/sections/contesting.js @@ -211,10 +211,19 @@ $('#start_date').change(function() { $("#callsign").keyup(function () { var call = $(this).val(); if (call.length >= 3) { - $.get('lookup/scp/' + call.toUpperCase(), function (result) { - $('.callsign-suggestions').text(result); - highlight(call.toUpperCase()); - }); + + $.ajax({ + url: 'lookup/scp', + method: 'POST', + data: { + callsign: $(this).val().toUpperCase() + }, + success: function(result) { + $('.callsign-suggestions').text(result); + highlight(call.toUpperCase()); + } + }); + checkIfWorkedBefore(); var qTable = $('.qsotable').DataTable(); qTable.search(call).draw(); diff --git a/assets/js/sections/gridmap.js b/assets/js/sections/gridmap.js index cec89f61..0402e506 100644 --- a/assets/js/sections/gridmap.js +++ b/assets/js/sections/gridmap.js @@ -40,6 +40,7 @@ function gridPlot(form) { sat: $("#sats").val(), }, success: function (data) { + $('.cohidden').show(); $(".ld-ext-right").removeClass('running'); $(".ld-ext-right").prop('disabled', false); $('#plot').prop("disabled", false); @@ -89,6 +90,7 @@ function gridPlot(form) { legend.addTo(map); var maidenhead = L.maidenhead().addTo(map); + map.on('mousemove', onMapMove); }, error: function (data) { }, @@ -142,4 +144,8 @@ function spawnGridsquareModal(loc_4char) { }); } }); -} \ No newline at end of file +} + +$(document).ready(function(){ + gridPlot(this.form); +}) diff --git a/assets/js/sections/hrdlog.js b/assets/js/sections/hrdlog.js new file mode 100644 index 00000000..9679c50a --- /dev/null +++ b/assets/js/sections/hrdlog.js @@ -0,0 +1,59 @@ +$(function () { + $('#datetimepicker5').datetimepicker({ + format: 'DD/MM/YYYY', + }); +}); + +$(function () { + $('#datetimepicker6').datetimepicker({ + format: 'DD/MM/YYYY', + }); +}); + +function ExportHrd(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/hrdlog/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){ + $('#modcount'+value.station_id).html(value.modcount); + $('#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); + }); + } + } + }); +} diff --git a/assets/js/sections/logbookadvanced.js b/assets/js/sections/logbookadvanced.js index 2cf65790..5a639c5b 100644 --- a/assets/js/sections/logbookadvanced.js +++ b/assets/js/sections/logbookadvanced.js @@ -43,9 +43,9 @@ function updateRow(qso) { cells.eq(c++).html(qso.lotw); } cells.eq(c++).text(qso.qslMessage); - cells.eq(c++).text(qso.dxcc); + cells.eq(c++).html(qso.dxcc); cells.eq(c++).text(qso.state); - cells.eq(c++).text(qso.cqzone); + cells.eq(c++).html(qso.cqzone); cells.eq(c++).html(qso.iota); $('[data-toggle="tooltip"]').tooltip(); @@ -73,7 +73,7 @@ function loadQSOTable(rows) { var table = $('#qsoList').DataTable(); table.clear(); - + for (i = 0; i < rows.length; i++) { let qso = rows[i]; @@ -102,7 +102,7 @@ function loadQSOTable(rows) { data.push(qso.state); data.push(qso.cqzone); data.push(qso.iota); - + let createdRow = table.row.add(data).index(); table.rows(createdRow).nodes().to$().data('qsoID', qso.qsoID); table.row(createdRow).node().id = 'qsoID-' + qso.qsoID; @@ -187,7 +187,16 @@ $(document).ready(function () { gridsquare: this.gridsquare.value, state: this.state.value, qsoresults: this.qsoResults.value, - sats: this.sats.value + sats: this.sats.value, + cqzone: this.cqzone.value, + lotwSent: this.lotwSent.value, + lotwReceived: this.lotwReceived.value, + eqslSent: this.eqslSent.value, + eqslReceived: this.eqslReceived.value, + qslvia: $('[name="qslviainput"]').val(), + sota: this.sota.value, + pota: this.pota.value, + wwff: this.wwff.value, }, dataType: 'json', success: function (data) { @@ -348,6 +357,157 @@ $(document).ready(function () { $('#notRequired').click(function (event) { handleQsl('I','', 'notRequired'); }); + $('#receivedBureau').click(function (event) { + handleQslReceived('Y','B', 'receivedBureau'); + }); + $('#receivedDirect').click(function (event) { + handleQslReceived('Y','D', 'receivedDirect'); + }); + + $('#searchGridsquare').click(function (event) { + quickSearch('gridsquare'); + }); + + $('#searchState').click(function (event) { + quickSearch('state'); + }); + + $('#searchIota').click(function (event) { + quickSearch('iota'); + }); + + $('#searchDxcc').click(function (event) { + quickSearch('dxcc'); + }); + + $('#searchCallsign').click(function (event) { + quickSearch('dx'); + }); + + $('#searchCqZone').click(function (event) { + quickSearch('cqzone'); + }); + + $('#searchMode').click(function (event) { + quickSearch('mode'); + }); + + $('#searchBand').click(function (event) { + quickSearch('band'); + }); + + $('#searchSota').click(function (event) { + quickSearch('sota'); + }); + + $('#searchWwff').click(function (event) { + quickSearch('wwff'); + }); + + $('#searchPota').click(function (event) { + quickSearch('pota'); + }); + + function quickSearch(type) { + var elements = $('#qsoList tbody input:checked'); + var nElements = elements.length; + if (nElements == 0) { + return; + } + if (nElements > 1) { + BootstrapDialog.alert({ + title: 'WARNING', + message: 'Only 1 row can be selected for Quickfilter!', + type: BootstrapDialog.TYPE_WARNING, + closable: false, + draggable: false, + callback: function (result) { + } + }); + } + var offset = 0; + + if (!$(".eqslconfirmation")[0]){ + offset--; + } + if (!$(".lotwconfirmation")[0]){ + offset--; + } + elements.each(function() { + var currentRow = $(this).first().closest('tr'); + var col1 = ''; + switch (type) { + case 'dxcc': var tdoffset = (offset + 16); col1 = currentRow.find("td:eq("+tdoffset+")").html(); col1 = col1.match(/\d/g); col1 = col1.join(""); break; + case 'cqzone': var tdoffset = (offset + 18); col1 = currentRow.find("td:eq("+tdoffset+")").text(); break; + case 'iota': var tdoffset = (offset + 19); col1 = currentRow.find("td:eq("+tdoffset+")").text(); col1 = col1.trim(); break; + case 'state': var tdoffset = (offset + 17); col1 = currentRow.find("td:eq("+tdoffset+")").text(); break; + case 'dx': col1 = currentRow.find("td:eq(3)").text(); col1 = col1.match(/^([^\s]+)/gm); break; + case 'gridsquare': col1 = $(currentRow).find('#dxgrid').text(); col1 = col1.substring(0, 4); break; + case 'sota': col1 = $(currentRow).find('#dxsota').text(); break; + case 'wwff': col1 = $(currentRow).find('#dxwwff').text(); break; + case 'pota': col1 = $(currentRow).find('#dxpota').text(); break; + case 'mode': col1 = currentRow.find("td:eq(4)").text(); break; + case 'band': col1 = currentRow.find("td:eq(7)").text(); col1 = col1.match(/\S\w*/); break; + } + if (col1.length == 0) return; + $('#searchForm').trigger("reset"); + $("#"+type).val(col1); + $('#searchForm').submit(); + }); + } + + $('#printLabel').click(function (event) { + var elements = $('#qsoList tbody input:checked'); + var nElements = elements.length; + if (nElements == 0) { + return; + } + $('#printLabel').prop("disabled", true); + + var id_list=[]; + + elements.each(function() { + let id = $(this).first().closest('tr').data('qsoID') + id_list.push(id); + }); + + $.ajax({ + url: base_url + 'index.php/labels/printids', + type: 'post', + data: {'id': JSON.stringify(id_list, null, 2) }, + xhr:function(){ + var xhr = new XMLHttpRequest(); + xhr.responseType= 'blob' + return xhr; + }, + success: function(data) { + if(data){ + var file = new Blob([data], {type: 'application/pdf'}); + var fileURL = URL.createObjectURL(file); + window.open(fileURL); + } + $.each(id_list, function(k, v) { + unselectQsoID(this); + }); + $('#printLabel').prop("disabled", false); + }, + error: function (data) { + BootstrapDialog.alert({ + title: 'ERROR', + message: 'Something went wrong with label print. Go to labels and check if you have defined a label, and that it is set for print!', + type: BootstrapDialog.TYPE_DANGER, + closable: false, + draggable: false, + callback: function (result) { + } + }); + $.each(id_list, function(k, v) { + unselectQsoID(this); + }); + $('#printLabel').prop("disabled", false); + }, + }); + }); $('#searchForm').on('reset', function(e) { setTimeout(function() { @@ -386,6 +546,37 @@ $(document).ready(function () { }); } + function handleQslReceived(sent, method, tag) { + var elements = $('#qsoList tbody input:checked'); + var nElements = elements.length; + if (nElements == 0) { + return; + } + $('#'+tag).prop("disabled", true); + var id_list=[]; + elements.each(function() { + let id = $(this).first().closest('tr').data('qsoID') + id_list.push(id); + }); + $.ajax({ + url: base_url + 'index.php/logbookadvanced/update_qsl_received', + type: 'post', + data: {'id': JSON.stringify(id_list, null, 2), + 'sent' : sent, + 'method' : method + }, + success: function(data) { + if (data !== []) { + $.each(data, function(k, v) { + updateRow(this); + unselectQsoID(this.qsoID); + }); + } + $('#'+tag).prop("disabled", false); + } + }); + } + $('#checkBoxAll').change(function (event) { if (this.checked) { $('#qsoList tbody tr').each(function (i) { diff --git a/assets/js/sections/qso.js b/assets/js/sections/qso.js index b72576ce..86114217 100644 --- a/assets/js/sections/qso.js +++ b/assets/js/sections/qso.js @@ -774,12 +774,19 @@ $("#callsign").on("keypress", function(e) { // On Key up check and suggest callsigns $("#callsign").keyup(function() { if ($(this).val().length >= 3) { - $('.callsign-suggest').show(); - $.get('lookup/scp/' + $(this).val().toUpperCase(), function(result) { - $('.callsign-suggestions').text(result); - }); + $('.callsign-suggest').show(); + $.ajax({ + url: 'lookup/scp', + method: 'POST', + data: { + callsign: $(this).val().toUpperCase() + }, + success: function(result) { + $('.callsign-suggestions').text(result); + } + }); } -}); + }); //Reset QSO form Fields function function resetDefaultQSOFields() { diff --git a/docker/Dockerfile b/docker/Dockerfile index f77d1400..bee0e909 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -7,14 +7,16 @@ RUN touch /usr/local/etc/php/conf.d/uploads.ini \ && echo "max_execution_time = 60" >> /usr/local/etc/php/conf.d/uploads.ini RUN apt-get update \ && apt-get install -y git curl libxml2-dev libonig-dev -RUN docker-php-ext-install mysqli +RUN docker-php-ext-install mysqli mbstring xml #RUN docker-php-ext-install curl -RUN docker-php-ext-install mbstring -RUN docker-php-ext-install xml #RUN docker-php-ext-install openssl -WORKDIR /var/www/html +RUN rm -rf /var/www/html/docker/ COPY ./ /var/www/html/ -RUN ls && rm -rf /var/www/html/docker/ \ +WORKDIR /var/www/html +RUN cd /var/www/html \ +&& echo "Setting root as owner of the folder..." \ +&& chown -R root:root /var/www/html \ +&& echo "Setting permissions to the install folder" \ && chown -R root:www-data ./application/config/ \ && chown -R root:www-data ./application/logs/ \ && chown -R root:www-data ./assets/qslcard/ \ @@ -30,4 +32,7 @@ RUN ls && rm -rf /var/www/html/docker/ \ && chmod -R g+rw ./updates/ \ && chmod -R g+rw ./uploads/ \ && chmod -R g+rw ./images/eqsl_card_images/ \ -&& chmod -R g+rw ./assets/json/ +&& chmod -R g+rw ./assets/json/ \ +&& chmod 777 /var/www/html/install \ +&& echo "Make sure everything is fine" \ +&& dir -ls diff --git a/install/config/config.php b/install/config/config.php index 70f1741f..c1f01bdb 100644 --- a/install/config/config.php +++ b/install/config/config.php @@ -14,7 +14,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); */ $config['app_name'] = "Cloudlog"; -$config['app_version'] = "2.4.3"; +$config['app_version'] = "2.4.4"; $config['directory'] = "%directory%"; $config['callbook'] = "hamqth"; // Options are hamqth or qrz diff --git a/install/index.php b/install/index.php index 55d2ecdf..cc0e5d8b 100644 --- a/install/index.php +++ b/install/index.php @@ -131,8 +131,8 @@ if($_POST) {
    Configuration Settings - " class="input_text" name="directory" /> - " class="input_text" name="websiteurl" /> + " class="input_text" name="directory" /> + " class="input_text" name="websiteurl" />
    diff --git a/src/QSLManager/QSO.php b/src/QSLManager/QSO.php index 98a4a614..3b00aa06 100644 --- a/src/QSLManager/QSO.php +++ b/src/QSLManager/QSO.php @@ -15,7 +15,7 @@ class QSO private string $dx; private string $mode; private string $submode; - private string $band; + private ?string $band; private string $bandRX; private string $rstR; private string $rstS; @@ -45,6 +45,8 @@ class QSO private string $dxSigInfo; private string $dxDARCDOK; private string $dxSOTAReference; + private string $dxPOTAReference; + private string $dxWWFFReference; /** @var string[] */ private string $dxVUCCGridsquares; private string $QSLMsg; @@ -107,6 +109,8 @@ class QSO 'COL_MY_SOTA_REF', 'COL_MY_VUCC_GRIDS', 'COL_SOTA_REF', + 'COL_POTA_REF', + 'COL_WWFF_REF', 'COL_SUBMODE', 'COL_VUCC_GRIDS', 'COL_CQZ', @@ -125,7 +129,7 @@ class QSO $this->qsoID = $data['COL_PRIMARY_KEY']; - $CI =& get_instance(); + $CI =& get_instance(); // Get Date format if($CI->session->userdata('user_date_format')) { // If Logged in and session exists @@ -134,7 +138,7 @@ class QSO // 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->qsoDateTime = date($custom_date_format . " H:i", strtotime($data['COL_TIME_ON'])); $this->de = $data['COL_STATION_CALLSIGN']; $this->dx = $data['COL_CALL']; @@ -171,6 +175,8 @@ class QSO $this->dxDARCDOK = $data['COL_DARC_DOK'] ?? ''; $this->dxSOTAReference = $data['COL_SOTA_REF'] ?? ''; + $this->dxPOTAReference = $data['COL_POTA_REF'] ?? ''; + $this->dxWWFFReference = $data['COL_WWFF_REF'] ?? ''; $this->dxVUCCGridsquares = $data['COL_VUCC_GRIDS'] ?? ''; @@ -183,14 +189,14 @@ 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']; - + $this->qsl = $this->getQslString($data, $custom_date_format); $this->lotw = $this->getLotwString($data, $custom_date_format); $this->eqsl = $this->getEqslString($data, $custom_date_format); - - $this->cqzone = ($data['COL_CQZ'] === null) ? '' : $data['COL_CQZ']; + + $this->cqzone = ($data['COL_CQZ'] === null) ? '' : ''.$data['COL_CQZ'].''; $this->state = ($data['COL_STATE'] === null) ? '' :$data['COL_STATE']; - $this->dxcc = ($data['name'] === null) ? '- NONE -' : ucwords(strtolower($data['name']), "- (/"); + $this->dxcc = ($data['name'] === null) ? '- NONE -' : ''.ucwords(strtolower($data['name']), "- (/").''; $this->iota = ($data['COL_IOTA'] === null) ? '' : $this->getIotaLink($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')); @@ -227,7 +233,7 @@ class QSO */ function getQSLString($data, $custom_date_format): string { - $CI =& get_instance(); + $CI =& get_instance(); $qslstring = 'lang->line('general_word_qslcard_electronic').")"; break; } - } + } $qslstring .= '">▲lang->line('general_word_qslcard_electronic').")"; break; } - } + } $qslstring .= '">▼'; + if ($data['qslcount'] != null) { + $qslstring .= ' '; + } return $qslstring; } - + /** * @return string */ function getLotwString($data, $custom_date_format): string { - $CI =& get_instance(); + $CI =& get_instance(); $lotwstring = 'lang->line('lotw_short')." ".$CI->lang->line('general_word_sent'); - if ($data['COL_LOTW_QSLSDATE'] != null) { - $timestamp = strtotime($data['COL_LOTW_QSLSDATE']); - $lotwstring .= " ". ($timestamp != '' ? date($custom_date_format, $timestamp) : ''); - } - $lotwstring .= "\" data-toggle=\"tooltip\""; - } + if ($data['COL_LOTW_QSL_SENT'] == "Y") { + $lotwstring .= "data-original-title=\"" . $CI->lang->line('lotw_short')." ".$CI->lang->line('general_word_sent'); + if ($data['COL_LOTW_QSLSDATE'] != null) { + $timestamp = strtotime($data['COL_LOTW_QSLSDATE']); + $lotwstring .= " ". ($timestamp != '' ? date($custom_date_format, $timestamp) : ''); + } + $lotwstring .= "\" data-toggle=\"tooltip\""; + } $lotwstring .= ' class="lotw-' . (($data['COL_LOTW_QSL_SENT']=='Y') ? 'green' : 'red') . '">▲'; $lotwstring .= 'lang->line('lotw_short') ." ". $CI->lang->line('general_word_received'); - - if ($data['COL_LOTW_QSLRDATE'] != null) { - $timestamp = strtotime($data['COL_LOTW_QSLRDATE']); - $lotwstring .= " ". ($timestamp != '' ? date($custom_date_format, $timestamp) : ''); - } - - $lotwstring .= "\" data-toggle=\"tooltip\""; - } + if ($data['COL_LOTW_QSL_RCVD'] == "Y") { + $lotwstring .= "data-original-title=\"". $CI->lang->line('lotw_short') ." ". $CI->lang->line('general_word_received'); + + if ($data['COL_LOTW_QSLRDATE'] != null) { + $timestamp = strtotime($data['COL_LOTW_QSLRDATE']); + $lotwstring .= " ". ($timestamp != '' ? date($custom_date_format, $timestamp) : ''); + } + + $lotwstring .= "\" data-toggle=\"tooltip\""; + } $lotwstring .= ' class="lotw-' . (($data['COL_LOTW_QSL_RCVD']=='Y') ? 'green':'red') . '">▼'; @@ -362,32 +371,32 @@ class QSO */ function getEqslString($data, $custom_date_format): string { - $CI =& get_instance(); + $CI =& get_instance(); $eqslstring = 'lang->line('eqsl_short')." ".$CI->lang->line('general_word_sent'); - - if ($data['COL_EQSL_QSLSDATE'] != null) { - $timestamp = strtotime($data['COL_EQSL_QSLSDATE']); - $eqslstring .= " ".($timestamp!=''?date($custom_date_format, $timestamp):''); - } - - $eqslstring .= "\" data-toggle=\"tooltip\""; - } - + if ($data['COL_EQSL_QSL_SENT'] == "Y") { + $eqslstring .= "data-original-title=\"".$CI->lang->line('eqsl_short')." ".$CI->lang->line('general_word_sent'); + + if ($data['COL_EQSL_QSLSDATE'] != null) { + $timestamp = strtotime($data['COL_EQSL_QSLSDATE']); + $eqslstring .= " ".($timestamp!=''?date($custom_date_format, $timestamp):''); + } + + $eqslstring .= "\" data-toggle=\"tooltip\""; + } + $eqslstring .= ' class="eqsl-' . (($data['COL_EQSL_QSL_SENT'] =='Y') ? 'green':'red') . '">▲lang->line('eqsl_short')." ".$CI->lang->line('general_word_received'); - - if ($data['COL_EQSL_QSLRDATE'] != null) { - $timestamp = strtotime($data['COL_EQSL_QSLRDATE']); - $eqslstring .= " ".($timestamp!=''?date($custom_date_format, $timestamp):''); - } - $eqslstring .= "\" data-toggle=\"tooltip\""; - } + if ($data['COL_EQSL_QSL_RCVD'] == "Y") { + $eqslstring .= "data-original-title=\"".$CI->lang->line('eqsl_short')." ".$CI->lang->line('general_word_received'); + + if ($data['COL_EQSL_QSLRDATE'] != null) { + $timestamp = strtotime($data['COL_EQSL_QSLRDATE']); + $eqslstring .= " ".($timestamp!=''?date($custom_date_format, $timestamp):''); + } + $eqslstring .= "\" data-toggle=\"tooltip\""; + } $eqslstring .= ' class="eqsl-' . (($data['COL_EQSL_QSL_RCVD'] =='Y')?'green':'red') . '">'; @@ -634,6 +643,22 @@ class QSO return $this->dxSOTAReference; } + /** + * @return string + */ + public function getDxPOTAReference(): string + { + return $this->dxPOTAReference; + } + + /** + * @return string + */ + public function getWWFFReference(): string + { + return $this->dxWWFFReference; + } + /** * @return string[] */ @@ -838,12 +863,18 @@ class QSO { $refs = []; if ($this->dxVUCCGridsquares !== '') { - $refs[] = $this->dxVUCCGridsquares . ' ' .$this->getQrbLink($this->stationGridsquare, $this->dxVUCCGridsquares, $this->dxGridsquare); + $refs[] = '' . $this->dxVUCCGridsquares . ' ' .$this->getQrbLink($this->stationGridsquare, $this->dxVUCCGridsquares, $this->dxGridsquare); } else if ($this->dxGridsquare !== '') { - $refs[] = $this->dxGridsquare . ' ' .$this->getQrbLink($this->stationGridsquare, $this->dxVUCCGridsquares, $this->dxGridsquare); + $refs[] = '' . $this->dxGridsquare . ' ' .$this->getQrbLink($this->stationGridsquare, $this->dxVUCCGridsquares, $this->dxGridsquare); } if ($this->dxSOTAReference !== '') { - $refs[] = "SOTA:" . $this->dxSOTAReference; + $refs[] = "SOTA: " . '' . $this->dxSOTAReference. ''; + } + if ($this->dxPOTAReference !== '') { + $refs[] = "POTA: " . '' . $this->dxPOTAReference. ''; + } + if ($this->dxWWFFReference !== '') { + $refs[] = "WWFF: " . '' . $this->dxWWFFReference. ''; } if ($this->dxSig !== '') { $refs[] = $this->dxSig . ":" . $this->dxSigInfo; @@ -961,7 +992,7 @@ class QSO private function getIotaLink($iota) : string { if ($iota !== '') { - return '' . $iota . ''; + return ''.$iota.' '; } return ''; }