diff --git a/README.md b/README.md index e94862bb..c0aef174 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,6 @@ Thanks to Andy (VE7CXZ), Gavin (M1BXF), Graham (W5ISP), Robert (M0VFC), Corby (K Cloudlog is supported by Patreon and donations via PayPal, thanks to the following people: -Paul (M0TZO), Tim (G4VXE), Paul (N8HM), Michelle (W5NYV), Mitchell (AD0HJ), Dan (M0TCB), Martin (DK3ML), Juan Carlos (EA5WA), Iain (M0PCB), Charlie (GM1TGY), Ondrej (OK1CDJ), Trystan (G0KAY), Oliver (DL6KBG), Volkmar Schirmer, Jordan (M0PIR), Thomas Ziegler, Mathis (DB9MAT), Ken (VE3HLS), Tyler (WL7T), Jeremy Taylor, Ben Kuhn, Eric Thresher, Michael Cullen, Juuso (OH1JW), Anthony Castiglia, Fernando Ramirez-Ferrer, Robert Dixon, Mark Percival, Julia (KV1V), Timo Tomasini, Ant (NU1U), Christopher Williams, Danny Barnes, Vic, Tom (M0LTE), smurphboy, Lars (SM0TGU), Theo (PD9DP), Stefan (SM0RGM). Peter (G0ABI), Lou (KI5FTY), Michael (DG3NAB), Dragan (4O4A), minorsecond, Emily (W7AYQ), Steve (M0SKM), Rob (M0VFC), Doug (WA6L). +Paul (M0TZO), Tim (G4VXE), Paul (N8HM), Michelle (W5NYV), Mitchell (AD0HJ), Dan (M0TCB), Martin (DK3ML), Juan Carlos (EA5WA), Iain (M0PCB), Charlie (GM1TGY), Ondrej (OK1CDJ), Trystan (G0KAY), Oliver (DL6KBG), Volkmar Schirmer, Jordan (M0PIR), Thomas Ziegler, Mathis (DB9MAT), Ken (VE3HLS), Tyler (WL7T), Jeremy Taylor, Ben Kuhn, Eric Thresher, Michael Cullen, Juuso (OH1JW), Anthony Castiglia, Fernando Ramirez-Ferrer, Robert Dixon, Mark Percival, Julia (KV1V), Timo Tomasini, Ant (NU1U), Christopher Williams, Danny Barnes, Vic, Tom (M0LTE), smurphboy, Lars (SM0TGU), Theo (PD9DP), Stefan (SM0RGM). Peter (G0ABI), Lou (KI5FTY), Michael (DG3NAB), Dragan (4O4A), minorsecond, Emily (W7AYQ), Steve (M0SKM), Rob (M0VFC), Doug (WA6L), Petr (OK1PKR), Fabian (HB9HI). If you'd like to donate to Cloudlog to help allow @magicbug spend less time doing commercial work and more time coding Cloudlog then you can donate via [PayPal](https://paypal.me/PGoodhall), [Github Sponsor](https://github.com/sponsors/magicbug) or become a [Patreon](https://www.patreon.com/2m0sql) diff --git a/application/config/migration.php b/application/config/migration.php index 70bc112e..f11c7f7b 100644 --- a/application/config/migration.php +++ b/application/config/migration.php @@ -22,7 +22,7 @@ $config['migration_enabled'] = TRUE; | */ -$config['migration_version'] = 137; +$config['migration_version'] = 140; /* |-------------------------------------------------------------------------- diff --git a/application/controllers/Eqsl.php b/application/controllers/Eqsl.php index 8bb72380..f6a29e6b 100644 --- a/application/controllers/Eqsl.php +++ b/application/controllers/Eqsl.php @@ -277,13 +277,13 @@ class eqsl extends CI_Controller { return $table; } - // Build out the ADIF info string according to specs http://eqsl.cc/qslcard/ADIFContentSpecs.cfm + // Build out the ADIF info string according to specs https://eqsl.cc/qslcard/ADIFContentSpecs.cfm function generateAdif($qsl, $data) { $COL_QSO_DATE = date('Ymd',strtotime($qsl['COL_TIME_ON'])); $COL_TIME_ON = date('Hi',strtotime($qsl['COL_TIME_ON'])); # Set up the single record file - $adif = "http://www.eqsl.cc/qslcard/importADIF.cfm?"; + $adif = "https://www.eqsl.cc/qslcard/importADIF.cfm?"; $adif .= "ADIFData=CloudlogUpload%20"; /* Handy reference of escaping chars diff --git a/application/controllers/Logbook.php b/application/controllers/Logbook.php index fcd10061..95cb05ff 100644 --- a/application/controllers/Logbook.php +++ b/application/controllers/Logbook.php @@ -235,7 +235,8 @@ class Logbook extends CI_Controller { if($type == "SAT") { $this->db->where('COL_PROP_MODE', 'SAT'); } else { - $this->db->where('COL_MODE', $this->logbook_model->get_main_mode_from_mode($mode)); + $CI->load->model('logbook_model'); + $this->db->where('COL_MODE', $CI->logbook_model->get_main_mode_from_mode($mode)); $this->db->where('COL_BAND', $band); $this->db->where('COL_PROP_MODE !=','SAT'); diff --git a/application/controllers/Logbookadvanced.php b/application/controllers/Logbookadvanced.php index f25fe68f..456c3e26 100644 --- a/application/controllers/Logbookadvanced.php +++ b/application/controllers/Logbookadvanced.php @@ -233,4 +233,175 @@ class Logbookadvanced extends CI_Controller { $data['qslimages'] = $this->logbookadvanced_model->getQslsForQsoIds($cleanids); $this->load->view('logbookadvanced/qslcarousel', $data); } + + public function mapSelectedQsos() { + $this->load->model('logbookadvanced_model'); + + $searchCriteria = array( + 'user_id' => (int)$this->session->userdata('user_id'), + 'dateFrom' => '', + 'dateTo' => '', + 'de' => '', + 'dx' => '', + 'mode' => '', + 'band' => '', + 'qslSent' => '', + 'qslReceived' => '', + 'iota' => '', + 'dxcc' => '', + 'propmode' => '', + 'gridsquare' => '', + 'state' => '', + 'cqzone' => '', + 'qsoresults' => count($this->input->post('ids')), + 'sats' => '', + 'lotwSent' => '', + 'lotwReceived' => '', + 'eqslSent' => '', + 'eqslReceived' => '', + 'qslvia' => '', + 'sota' => '', + 'pota' => '', + 'wwff' => '', + 'qslimages' => '', + 'ids' => xss_clean($this->input->post('ids')) + ); + + $result = $this->logbookadvanced_model->searchDb($searchCriteria); + $this->prepareMappedQSos($result); + } + + public function mapQsos() { + $this->load->model('logbookadvanced_model'); + + $searchCriteria = array( + 'user_id' => (int)$this->session->userdata('user_id'), + 'dateFrom' => xss_clean($this->input->post('dateFrom')), + 'dateTo' => xss_clean($this->input->post('dateTo')), + 'de' => xss_clean($this->input->post('de')), + 'dx' => xss_clean($this->input->post('dx')), + 'mode' => xss_clean($this->input->post('mode')), + 'band' => xss_clean($this->input->post('band')), + 'qslSent' => xss_clean($this->input->post('qslSent')), + 'qslReceived' => xss_clean($this->input->post('qslReceived')), + 'iota' => xss_clean($this->input->post('iota')), + 'dxcc' => xss_clean($this->input->post('dxcc')), + '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')), + 'qslimages' => xss_clean($this->input->post('qslimages')), + ); + + $result = $this->logbookadvanced_model->searchDb($searchCriteria); + $this->prepareMappedQSos($result); + } + + public function prepareMappedQSos($qsos) { + if ($this->session->userdata('user_measurement_base') == NULL) { + $measurement_base = $this->config->item('measurement_base'); + } + else { + $measurement_base = $this->session->userdata('user_measurement_base'); + } + + $CI =& get_instance(); + // Get Date format + if($CI->session->userdata('user_date_format')) { + // If Logged in and session exists + $custom_date_format = $CI->session->userdata('user_date_format'); + } else { + // Get Default date format from /config/cloudlog.php + $custom_date_format = $CI->config->item('qso_date_format'); + } + + switch ($measurement_base) { + case 'M': + $var_dist = " miles"; + break; + case 'N': + $var_dist = " nautic miles"; + break; + case 'K': + $var_dist = " kilometers"; + break; + } + + $mappedcoordinates = array(); + foreach ($qsos as $qso) { + if (!empty($qso['COL_MY_GRIDSQUARE']) || !empty($qso['COL_MY_VUCC_GRIDS'])) { + if (!empty($qso['COL_GRIDSQUARE']) || !empty($qso['COL_VUCC_GRIDS'])) { + $mappedcoordinates[] = $this->calculate($qso, ($qso['COL_MY_GRIDSQUARE'] ?? '') == '' ? $qso['COL_MY_VUCC_GRIDS'] : $qso['COL_MY_GRIDSQUARE'], ($qso['COL_GRIDSQUARE'] ?? '') == '' ? $qso['COL_VUCC_GRIDS'] : $qso['COL_GRIDSQUARE'], $measurement_base, $var_dist, $custom_date_format); + } else { + if (!empty($qso['lat']) || !empty($qso['long'])) { + $mappedcoordinates[] = $this->calculateCoordinates($qso, $qso['lat'], $qso['long'], ($qso['COL_MY_GRIDSQUARE'] ?? '') == '' ? $qso['COL_MY_VUCC_GRIDS'] : $qso['COL_MY_GRIDSQUARE'], $measurement_base, $var_dist, $custom_date_format); + } + } + } + } + + header("Content-Type: application/json"); + print json_encode($mappedcoordinates); + } + + public function calculate($qso, $locator1, $locator2, $measurement_base, $var_dist, $custom_date_format) { + $this->load->library('Qra'); + + $data['distance'] = $this->qra->distance($locator1, $locator2, $measurement_base) . $var_dist; + $data['bearing'] = $this->qra->get_bearing($locator1, $locator2) . "º"; + $latlng1 = $this->qra->qra2latlong($locator1); + $latlng2 = $this->qra->qra2latlong($locator2); + $latlng1[0] = number_format((float)$latlng1[0], 3, '.', '');; + $latlng1[1] = number_format((float)$latlng1[1], 3, '.', '');; + $latlng2[0] = number_format((float)$latlng2[0], 3, '.', '');; + $latlng2[1] = number_format((float)$latlng2[1], 3, '.', '');; + + $data['latlng1'] = $latlng1; + $data['latlng2'] = $latlng2; + + $data['callsign'] = $qso['COL_CALL']; + $data['band'] = $qso['COL_BAND']; + $data['mode'] = $qso['COL_MODE']; + $data['gridsquare'] = $locator2; + $data['mygridsquare'] = $locator1; + $data['mycallsign'] = $qso['station_callsign']; + $data['datetime'] = date($custom_date_format, strtotime($qso['COL_TIME_ON'])). date(' H:i',strtotime($qso['COL_TIME_ON'])); + $data['satname'] = $qso['COL_SAT_NAME']; + + return $data; + } + + public function calculateCoordinates($qso, $lat, $long, $mygrid, $measurement_base, $var_dist, $custom_date_format) { + $this->load->library('Qra'); + + $latlng1 = $this->qra->qra2latlong($mygrid); + $latlng2[0] = $lat; + $latlng2[1] = $long; + $latlng1[0] = number_format((float)$latlng1[0], 3, '.', '');; + $latlng1[1] = number_format((float)$latlng1[1], 3, '.', '');; + $latlng2[0] = number_format((float)$latlng2[0], 3, '.', '');; + $latlng2[1] = number_format((float)$latlng2[1], 3, '.', '');; + + $data['latlng1'] = $latlng1; + $data['latlng2'] = $latlng2; + $data['callsign'] = $qso['COL_CALL']; + $data['band'] = $qso['COL_BAND']; + $data['mode'] = $qso['COL_MODE']; + $data['mygridsquare'] = $mygrid; + $data['mycallsign'] = $qso['station_callsign']; + $data['datetime'] = date($custom_date_format, strtotime($qso['COL_TIME_ON'])). date(' H:i',strtotime($qso['COL_TIME_ON'])); + $data['satname'] = $qso['COL_SAT_NAME']; + + return $data; + } } diff --git a/application/controllers/Logbooks.php b/application/controllers/Logbooks.php index a5f021c3..61938f5c 100644 --- a/application/controllers/Logbooks.php +++ b/application/controllers/Logbooks.php @@ -132,7 +132,7 @@ class Logbooks extends CI_Controller { public function save_publicsearch() { $this->load->model('logbooks_model'); $returndata = $this->logbooks_model->save_public_search($this->input->post('public_search'), $this->input->post('logbook_id')); - echo "
Public Search Setttings Saved
"; + echo "
Public Search Settings Saved
"; } public function save_publicslug() { diff --git a/application/controllers/Qslprint.php b/application/controllers/Qslprint.php index 9c391c1e..11a902f2 100644 --- a/application/controllers/Qslprint.php +++ b/application/controllers/Qslprint.php @@ -114,8 +114,8 @@ class QSLPrint extends CI_Controller { foreach ($myData->result() as $qso) { fputcsv($file, array($qso->STATION_CALLSIGN, - str_replace("0", "Ø", $qso->COL_CALL), - $qso->COL_QSL_VIA!=""?"Via ".str_replace("0", "Ø", $qso->COL_QSL_VIA):"", + $qso->COL_CALL, + $qso->COL_QSL_VIA!=""?"via ".$qso->COL_QSL_VIA:"", $qso->COL_TIME_ON, $qso->COL_MODE, $qso->COL_FREQ, diff --git a/application/controllers/Qso.php b/application/controllers/Qso.php index 1df36bae..395c8a67 100755 --- a/application/controllers/Qso.php +++ b/application/controllers/Qso.php @@ -78,6 +78,7 @@ class QSO extends CI_Controller { 'prop_mode' => $this->input->post('prop_mode'), 'radio' => $this->input->post('radio'), 'station_profile_id' => $this->input->post('station_profile'), + 'operator_callsign' => $this->input->post('operator_callsign'), 'transmit_power' => $this->input->post('transmit_power') ); // ]; diff --git a/application/controllers/User_options.php b/application/controllers/User_options.php new file mode 100755 index 00000000..3aa337de --- /dev/null +++ b/application/controllers/User_options.php @@ -0,0 +1,52 @@ +load->model('user_model'); + $this->load->model('user_options_model'); + if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); } + } + + public function add_edit_fav() { + $obj = json_decode(file_get_contents("php://input"), true); + foreach($obj as $option_key => $option_value) { + $obj[$option_key]=$this->security->xss_clean($option_value); + } + if ($obj['sat_name'] ?? '' != '') { + $option_name=$obj['sat_name'].'/'.$obj['mode']; + } else { + $option_name=$obj['band'].'/'.$obj['mode']; + } + $this->user_options_model->set_option('Favourite',$option_name, $obj); + $jsonout['success']=1; + header('Content-Type: application/json'); + echo json_encode($jsonout); + } + + public function get_fav() { + $result=$this->user_options_model->get_options('Favourite'); + $jsonout=[]; + foreach($result->result() as $options) { + $jsonout[$options->option_name][$options->option_key]=$options->option_value; + } + header('Content-Type: application/json'); + echo json_encode($jsonout); + } + + public function del_fav() { + $result=$this->user_options_model->get_options('Favourite'); + $obj = json_decode(file_get_contents("php://input"), true); + if ($obj['option_name'] ?? '' != '') { + $option_name=$this->security->xss_clean($obj['option_name']); + $this->user_options_model->del_option('Favourite',$option_name); + } + $jsonout['success']=1; + header('Content-Type: application/json'); + echo json_encode($jsonout); + } +} + + +?> diff --git a/application/language/czech/account_lang.php b/application/language/czech/account_lang.php index b7048da6..986504f5 100644 --- a/application/language/czech/account_lang.php +++ b/application/language/czech/account_lang.php @@ -35,10 +35,10 @@ $lang['account_timezone'] = 'Časové pásmo'; $lang['account_date_format'] = 'Formát data'; $lang['account_measurement_preferences'] = 'Nastavení měření'; $lang['account_select_how_you_would_like_dates_shown_when_logged_into_your_account'] = 'Vyberte, jak chcete, aby byla data zobrazena při přihlášení do vašeho účtu.'; -$lang['account_choose_which_unit_distances_will_be_shown_in'] = 'Vyberte, v jakých jednotkách se budou zobrazovat vzdálenosti.' +$lang['account_choose_which_unit_distances_will_be_shown_in'] = 'Vyberte, v jakých jednotkách se budou zobrazovat vzdálenosti.'; $lang['account_main_menu'] = 'Hlavní menu'; -$lang['account_show_notes_in_the_main_menu'] = 'Zobrazovat poznámky v hlavním menu.' +$lang['account_show_notes_in_the_main_menu'] = 'Zobrazovat poznámky v hlavním menu.'; $lang['account_main_menu'] = 'Hlavní menu'; $lang['account_show_notes_in_the_main_menu'] = 'Zobrazovat poznámky v hlavním menu.'; @@ -48,14 +48,14 @@ $lang['account_if_set_gridsquare_is_fetched_based_on_location_name'] = 'Pokud je $lang['account_sota_auto_lookup_gridsquare_and_name_for_summit'] = 'Automatické vyhledávání lokátoru a jména pro SOTA vrchol.'; $lang['account_wwff_auto_lookup_gridsquare_and_name_for_reference'] = 'Automatické vyhledávání lokátoru a jména pro WWFF referenci.'; $lang['account_pota_auto_lookup_gridsquare_and_name_for_park'] = 'Automatické vyhledávání lokátoru a jména pro POTA park.'; -$lang['account_if_set_name_and_gridsquare_is_fetched_from_the_api_and_filled_in_location_and_locator'] = 'Pokud je nastaveno, jméno a lokátor jsou získány z API a vyplněny do umístění a lokátoru.' +$lang['account_if_set_name_and_gridsquare_is_fetched_from_the_api_and_filled_in_location_and_locator'] = 'Pokud je nastaveno, jméno a lokátor jsou získány z API a vyplněny do umístění a lokátoru.'; $lang['account_previous_qsl_type'] = 'Předchozí typ QSL'; $lang['account_select_the_type_of_qsl_to_show_in_the_previous_qsos_section'] = 'Vyberte typ QSL k zobrazení v sekci předchozích QSOs.'; $lang['account_qrzcom_hamqthcom_images'] = 'Obrázky qrz.com/hamqth.com'; $lang['account_show_profile_picture_of_qso_partner_from_qrzcom_hamqthcom_profile_in_the_log_qso_section'] = 'Zobrazit profilový obrázek partnera z QSO záznamu z profilu qrz.com/hamqth.com v sekci protokolu QSO.'; -$lang['account_please_set_your_qrzcom_hamqthcom_credentials_in_the_general_config_file'] = 'Prosím, nastavte své přihlašovací údaje pro qrz.com/hamqth.com v obecném konfiguračním souboru.' +$lang['account_please_set_your_qrzcom_hamqthcom_credentials_in_the_general_config_file'] = 'Prosím, nastavte své přihlašovací údaje pro qrz.com/hamqth.com v obecném konfiguračním souboru.'; $lang['account_amsat_status_upload'] = 'Nahrávání stavu AMSAT'; $lang['account_upload_status_of_sat_qsos_to'] = 'Nahrávání stavu SAT QSOs na'; diff --git a/application/language/english/lotw_lang.php b/application/language/english/lotw_lang.php index 4ef6691c..3ed3245d 100644 --- a/application/language/english/lotw_lang.php +++ b/application/language/english/lotw_lang.php @@ -58,4 +58,5 @@ $lang['lotw_cert_expiring'] = 'At least one of your LoTW certificates is about t $lang['lotw_cert_expired'] = 'At least one of your LoTW certificates is expired!'; // Lotw User -$lang['lotw_user'] = 'This station uses LoTW. The last upload was'; +$lang['lotw_user'] = 'This station uses LoTW.'; +$lang['lotw_last_upload'] = 'Last upload'; diff --git a/application/language/english/qso_lang.php b/application/language/english/qso_lang.php index 3b27929f..b386c683 100644 --- a/application/language/english/qso_lang.php +++ b/application/language/english/qso_lang.php @@ -32,3 +32,5 @@ $lang['qso_btn_edit_qso'] = 'Edit QSO'; // QSO Details $lang['qso_details'] = 'QSO Details'; +$lang['fav_add'] = 'Add Band/Mode to Favs'; +$lang['qso_operator_callsign'] = 'Operator Callsign'; diff --git a/application/language/german/lotw_lang.php b/application/language/german/lotw_lang.php index 88485441..03b2d398 100644 --- a/application/language/german/lotw_lang.php +++ b/application/language/german/lotw_lang.php @@ -58,4 +58,5 @@ $lang['lotw_cert_expiring'] = 'Mindestens eines deiner LoTW-Zertifikate läuft b $lang['lotw_cert_expired'] = 'Mindestens eines deiner LoTW-Zertifikate ist abgelaufen!'; // Lotw User -$lang['lotw_user'] = 'Diese Station nutzt LoTW. Der letzte Upload war am'; +$lang['lotw_user'] = 'Diese Station nutzt LoTW.'; +$lang['lotw_last_upload'] = 'Letzter Upload'; diff --git a/application/language/german/qso_lang.php b/application/language/german/qso_lang.php index 0f1b0949..229d2bc2 100644 --- a/application/language/german/qso_lang.php +++ b/application/language/german/qso_lang.php @@ -32,3 +32,6 @@ $lang['qso_btn_edit_qso'] = 'Editiere QSO'; // QSO Details $lang['qso_details'] = 'QSO Details'; + +$lang['fav_add'] = 'Band/Mode zu Favoriten hinzufügen'; +$lang['qso_operator_callsign']='Operator Rufzeichen'; diff --git a/application/libraries/EqslImporter.php b/application/libraries/EqslImporter.php index 087ca036..2ca8ff4b 100644 --- a/application/libraries/EqslImporter.php +++ b/application/libraries/EqslImporter.php @@ -111,7 +111,7 @@ class EqslImporter foreach ($matches[2] as $match) { // Look for the link that has the .adi file, and download it to $file if (substr($match, -4, 4) == ".adi") { - file_put_contents($this->adif_file, file_get_contents("http://eqsl.cc/qslcard/" . $match)); + file_put_contents($this->adif_file, file_get_contents("https://eqsl.cc/qslcard/" . $match)); return $this->import(); } } diff --git a/application/libraries/Qra.php b/application/libraries/Qra.php index db55dc93..a9122c29 100644 --- a/application/libraries/Qra.php +++ b/application/libraries/Qra.php @@ -23,12 +23,6 @@ class Qra { // calculate the bearing between two squares function bearing($tx, $rx, $unit = 'M') { - if(strlen($tx) > 6) { - $tx = substr($tx, 0, 6); - } - if(strlen($rx) > 6) { - $rx = substr($rx, 0, 6); - } $my = qra2latlong($tx); $stn = qra2latlong($rx); @@ -44,12 +38,6 @@ class Qra { * */ function distance($tx, $rx, $unit = 'M') { - if(strlen($tx) > 6) { - $tx = substr($tx, 0, 6); - } - if(strlen($rx) > 6) { - $rx = substr($rx, 0, 6); - } // Calc LatLongs $my = qra2latlong($tx); $stn = qra2latlong($rx); @@ -176,9 +164,38 @@ function get_bearing($lat1, $lon1, $lat2, $lon2) { } function qra2latlong($strQRA) { - if (strpos($strQRA, ',') !== false) { - $gridsquareArray = explode(',', $strQRA); - $strQRA = $gridsquareArray[0]; + if (substr_count($strQRA, ',') > 0) { + if (substr_count($strQRA, ',') == 3) { + // Handle grid corners + $grids = explode(',', $strQRA); + $coords = array(0, 0); + for($i=0; $i<4; $i++) { + $cornercoords[$i] = qra2latlong($grids[$i]); + $coords[0] += $cornercoords[$i][0]; + $coords[1] += $cornercoords[$i][1]; + } + return array (round($coords[0]/4), round($coords[1]/4)); + } else if (substr_count($strQRA, ',') == 1) { + // Handle grid lines + $grids = explode(',', $strQRA); + $coords = array(0, 0); + for($i=0; $i<2; $i++) { + $linecoords[$i] = qra2latlong($grids[$i]); + } + if ($linecoords[0][0] != $linecoords[1][0]) { + $coords[0] = round((($linecoords[0][0] + $linecoords[1][0]) / 2),1); + } else { + $coords[0] = round($linecoords[0][0],1); + } + if ($linecoords[0][1] != $linecoords[1][1]) { + $coords[1] = round(($linecoords[0][1] + $linecoords[1][1]) / 2); + } else { + $coords[1] = round($linecoords[0][1]); + } + return $coords; + } else { + return false; + } } if ((strlen($strQRA) % 2 == 0) && (strlen($strQRA) <= 8)) { // Check if QRA is EVEN (the % 2 does that) and smaller/equal 8 @@ -200,7 +217,6 @@ function qra2latlong($strQRA) { $g = ord($g) - ord('0'); $h = ord($h) - ord('0'); - $nLong = ($a*20) + ($c*2) + (($e+0.5)/12) + (($g-5)/120) - 180; // the 4th pair is "in the middle", so we've to substract 5 $nLat = ($b*10) + $d + (($f+0.5)/24) + (($h-5)/240) - 90; diff --git a/application/migrations/058_new_options_table.php b/application/migrations/058_new_options_table.php index 99bc8239..6c888985 100644 --- a/application/migrations/058_new_options_table.php +++ b/application/migrations/058_new_options_table.php @@ -11,35 +11,38 @@ class Migration_new_options_table extends CI_Migration { public function up() { - $this->dbforge->add_field(array( - 'option_id' => array( - 'type' => 'BIGINT', - 'constraint' => 20, - 'unsigned' => TRUE, - 'auto_increment' => TRUE - ), - - 'option_name' => array( - 'type' => 'VARCHAR', - 'constraint' => '191', - 'null' => TRUE, - 'unique' => TRUE, - ), - - 'option_value' => array( - 'type' => 'longtext', - ), - - 'autoload' => array( - 'type' => 'varchar', - 'constraint' => '20', - 'null' => TRUE, - ) - )); - - $this->dbforge->add_key('option_id', TRUE); - - $this->dbforge->create_table('options'); + // if table options doesn't exist + if (!$this->db->table_exists('options')) { + $this->dbforge->add_field(array( + 'option_id' => array( + 'type' => 'BIGINT', + 'constraint' => 20, + 'unsigned' => TRUE, + 'auto_increment' => TRUE + ), + + 'option_name' => array( + 'type' => 'VARCHAR', + 'constraint' => '191', + 'null' => TRUE, + 'unique' => TRUE, + ), + + 'option_value' => array( + 'type' => 'longtext', + ), + + 'autoload' => array( + 'type' => 'varchar', + 'constraint' => '20', + 'null' => TRUE, + ) + )); + + $this->dbforge->add_key('option_id', TRUE); + + $this->dbforge->create_table('options'); + } } public function down() diff --git a/application/migrations/102_add_version_two_trigger_to_options.php b/application/migrations/102_add_version_two_trigger_to_options.php index e0dac738..f1da0867 100644 --- a/application/migrations/102_add_version_two_trigger_to_options.php +++ b/application/migrations/102_add_version_two_trigger_to_options.php @@ -11,6 +11,7 @@ class Migration_add_version_two_trigger_to_options extends CI_Migration { public function up() { + $data = array( array('option_name' => "version2_trigger", 'option_value' => "false", 'autoload' => "yes"), ); @@ -19,6 +20,7 @@ class Migration_add_version_two_trigger_to_options extends CI_Migration { if($query->num_rows() == 0) { $this->db->insert_batch('options', $data); } + } public function down() diff --git a/application/migrations/138_user_options_table.php b/application/migrations/138_user_options_table.php new file mode 100644 index 00000000..8961d37d --- /dev/null +++ b/application/migrations/138_user_options_table.php @@ -0,0 +1,19 @@ +db->table_exists('user_options')) { + $this->db->query("CREATE TABLE `user_options` ( `user_id` int(11) NOT NULL, `option_type` varchar(45) NOT NULL, `option_name` varchar(45) NOT NULL, `option_key` varchar(45) NOT NULL, `option_value` varchar(45) DEFAULT NULL, PRIMARY KEY (`user_id`,`option_type`,`option_key`,`option_name`))"); + } + + } + + public function down(){ + if ($this->db->table_exists('user_options')) { + $this->dbforge->drop_table('user_options'); + } + } +} diff --git a/application/migrations/139_modify_eQSL_url.php b/application/migrations/139_modify_eQSL_url.php new file mode 100644 index 00000000..ab8cbba4 --- /dev/null +++ b/application/migrations/139_modify_eQSL_url.php @@ -0,0 +1,16 @@ +db->query($sql); + } + + public function down() + { + // Will not go back to insecure connections + } +} +?> diff --git a/application/migrations/140_tag_2_4_8.php b/application/migrations/140_tag_2_4_8.php new file mode 100644 index 00000000..ee070205 --- /dev/null +++ b/application/migrations/140_tag_2_4_8.php @@ -0,0 +1,24 @@ +db->where('option_name', 'version'); + $this->db->update('options', array('option_value' => '2.4.8')); + } + + public function down() + { + $this->db->where('option_name', 'version'); + $this->db->update('options', array('option_value' => '2.4.7')); + } +} \ No newline at end of file diff --git a/application/models/Distances_model.php b/application/models/Distances_model.php index 068d1906..3aa17c0c 100644 --- a/application/models/Distances_model.php +++ b/application/models/Distances_model.php @@ -4,17 +4,16 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); class Distances_model extends CI_Model { - function get_distances($postdata, $measurement_base) - { + function get_distances($postdata, $measurement_base) { $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) { - header('Content-Type: application/json'); - echo json_encode(array('Error' => 'No QSOs found to plot.')); - return; - } + if (!$logbooks_locations_array) { + header('Content-Type: application/json'); + echo json_encode(array('Error' => 'No QSOs found to plot.')); + return; + } $result = array(); @@ -25,7 +24,7 @@ class Distances_model extends CI_Model if ($station_gridsquare != null) { $gridsquare = explode(',', $station_gridsquare); // We need to convert to an array, since a user can enter several gridsquares - $this->db->select('col_call callsign, col_gridsquare grid'); + $this->db->select('COL_PRIMARY_KEY,COL_DISTANCE,col_call callsign, col_gridsquare grid'); $this->db->where('LENGTH(col_gridsquare) >', 0); if ($postdata['band'] == 'sat') { @@ -41,12 +40,12 @@ class Distances_model extends CI_Model $this->db->where('station_id', $station_id); $queryresult = $this->db->get($this->config->item('table_name')); - if ($queryresult->result_array()) { - $temp = $this->plot($queryresult->result_array(), $gridsquare, $measurement_base); + if ($queryresult->result_array()) { + $temp = $this->plot($queryresult->result_array(), $gridsquare, $measurement_base); - $result = $this->mergeresult($result, $temp); + $result = $this->mergeresult($result, $temp); - } + } } @@ -61,13 +60,13 @@ class Distances_model extends CI_Model echo json_encode(array('Error' => 'No QSOs found to plot.')); } - } + } /* * We merge the result from several station_id's. They can have different gridsquares, so we need to use the correct gridsquare to calculate the correct distance. */ - function mergeresult($result, $add) { - if (sizeof($result) > 0) { + function mergeresult($result, $add) { + if (sizeof($result) > 0) { if ($result['qrb']['Distance'] < $add['qrb']['Distance']) { $result['qrb']['Distance'] = $add['qrb']['Distance']; $result['qrb']['Grid'] = $add['qrb']['Grid']; @@ -77,29 +76,29 @@ class Distances_model extends CI_Model for ($i = 0; $i <= 399; $i++) { - if(isset($result['qsodata'][$i]['count'])) { - $result['qsodata'][$i]['count'] += $add['qsodata'][$i]['count']; - } + if(isset($result['qsodata'][$i]['count'])) { + $result['qsodata'][$i]['count'] += $add['qsodata'][$i]['count']; + } - if(isset($result['qsodata'][$i]['callcount'])) { - if ($result['qsodata'][$i]['callcount'] < 5 && $add['qsodata'][$i]['callcount'] > 0) { - $calls = explode(',', $add['qsodata'][$i]['calls']); - foreach ($calls as $c) { - if ($result['qsodata'][$i]['callcount'] < 5) { - if ($result['qsodata'][$i]['callcount'] > 0) { - $result['qsodata'][$i]['calls'] .= ', '; - } - $result['qsodata'][$i]['calls'] .= $c; - $result['qsodata'][$i]['callcount']++; - } - } - } - } + if(isset($result['qsodata'][$i]['callcount'])) { + if ($result['qsodata'][$i]['callcount'] < 5 && $add['qsodata'][$i]['callcount'] > 0) { + $calls = explode(',', $add['qsodata'][$i]['calls']); + foreach ($calls as $c) { + if ($result['qsodata'][$i]['callcount'] < 5) { + if ($result['qsodata'][$i]['callcount'] > 0) { + $result['qsodata'][$i]['calls'] .= ', '; + } + $result['qsodata'][$i]['calls'] .= $c; + $result['qsodata'][$i]['callcount']++; + } + } + } + } } return $result; } - return $add; + return $add; } /* @@ -108,11 +107,11 @@ class Distances_model extends CI_Model function find_gridsquare($station_id) { $this->db->where('station_id', $station_id); - $result = $this->db->get('station_profile')->row_array(); + $result = $this->db->get('station_profile')->row_array(); - if ($result) { - return $result['station_gridsquare']; - } + if ($result) { + return $result['station_gridsquare']; + } return null; } @@ -121,152 +120,101 @@ class Distances_model extends CI_Model // then calculates distance between homelocator and locator given in qso. // It builds an array, which has 50km intervals, then inputs each length into the correct spot // The function returns a json-encoded array. - function plot($qsoArray, $gridsquare, $measurement_base) { + function plot($qsoArray, $gridsquare, $measurement_base) { + $this->load->library('Qra'); + $stationgrid = strtoupper($gridsquare[0]); // We use only the first entered gridsquare from the active profile + if (strlen($stationgrid) == 4) $stationgrid .= 'MM'; // adding center of grid if only 4 digits are specified - $stationgrid = strtoupper($gridsquare[0]); // We use only the first entered gridsquare from the active profile - if (strlen($stationgrid) == 4) $stationgrid .= 'MM'; // adding center of grid if only 4 digits are specified + switch ($measurement_base) { + case 'M': + $unit = "mi"; + $dist = '13000'; + break; + case 'K': + $unit = "km"; + $dist = '20000'; + break; + case 'N': + $unit = "nmi"; + $dist = '11000'; + break; + default: + $unit = "km"; + $dist = '20000'; + } - switch ($measurement_base) { - case 'M': - $unit = "mi"; - $dist = '13000'; - break; - case 'K': - $unit = "km"; - $dist = '20000'; - break; - case 'N': - $unit = "nmi"; - $dist = '11000'; - break; - default: - $unit = "km"; - $dist = '20000'; - } + if (!$this->valid_locator($stationgrid)) { + header('Content-Type: application/json'); + echo json_encode(array('Error' => 'Error. There is a problem with the gridsquare set in your profile!')); + exit; + } else { + // Making the array we will use for plotting, we save occurrences of the length of each qso in the array + $j = 0; + for ($i = 0; $j < $dist; $i++) { + $dataarray[$i]['dist'] = $j . $unit . ' - ' . ($j + 50) . $unit; + $dataarray[$i]['count'] = 0; + $dataarray[$i]['calls'] = ''; + $dataarray[$i]['callcount'] = 0; + $j += 50; + } - if (!$this->valid_locator($stationgrid)) { - header('Content-Type: application/json'); - echo json_encode(array('Error' => 'Error. There is a problem with the gridsquare set in your profile!')); - exit; - } - else { - // Making the array we will use for plotting, we save occurrences of the length of each qso in the array - $j = 0; - for ($i = 0; $j < $dist; $i++) { - $dataarray[$i]['dist'] = $j . $unit . ' - ' . ($j + 50) . $unit; - $dataarray[$i]['count'] = 0; - $dataarray[$i]['calls'] = ''; - $dataarray[$i]['callcount'] = 0; - $j += 50; - } + $qrb = array ( // Used for storing the QSO with the longest QRB + 'Callsign' => '', + 'Grid' => '', + 'Distance' => '', + 'Qsos' => '', + 'Grids' => '' + ); - $qrb = array ( // Used for storing the QSO with the longest QRB - 'Callsign' => '', - 'Grid' => '', - 'Distance' => '', - 'Qsos' => '', - 'Grids' => '' - ); - - foreach ($qsoArray as $qso) { - $qrb['Qsos']++; // Counts up number of qsos - $bearingdistance = $this->bearing_dist($stationgrid, $qso['grid'], $measurement_base); // Calculates distance based on grids - $arrayplacement = (int)($bearingdistance / 50); // Resolution is 50, calculates where to put result in array - if ($bearingdistance > $qrb['Distance']) { // Saves the longest QSO - $qrb['Distance'] = $bearingdistance; - $qrb['Callsign'] = $qso['callsign']; - $qrb['Grid'] = $qso['grid']; - } - $dataarray[$arrayplacement]['count']++; // Used for counting total qsos plotted - if ($dataarray[$arrayplacement]['callcount'] < 5) { // Used for tooltip in graph, set limit to 5 calls shown - if ($dataarray[$arrayplacement]['callcount'] > 0) { - $dataarray[$arrayplacement]['calls'] .= ', '; - } - $dataarray[$arrayplacement]['calls'] .= $qso['callsign']; - $dataarray[$arrayplacement]['callcount']++; - } - } + foreach ($qsoArray as $qso) { + $qrb['Qsos']++; // Counts up number of qsos + $bearingdistance = $this->qra->distance($stationgrid, $qso['grid'], $measurement_base); + if ($bearingdistance != $qso['COL_DISTANCE']) { + $data = array('COL_DISTANCE' => $bearingdistance); + $this->db->where('COL_PRIMARY_KEY', $qso['COL_PRIMARY_KEY']); + $this->db->update($this->config->item('table_name'), $data); + } + $arrayplacement = (int)($bearingdistance / 50); // Resolution is 50, calculates where to put result in array + if ($bearingdistance > $qrb['Distance']) { // Saves the longest QSO + $qrb['Distance'] = $bearingdistance; + $qrb['Callsign'] = $qso['callsign']; + $qrb['Grid'] = $qso['grid']; + } + $dataarray[$arrayplacement]['count']++; // Used for counting total qsos plotted + if ($dataarray[$arrayplacement]['callcount'] < 5) { // Used for tooltip in graph, set limit to 5 calls shown + if ($dataarray[$arrayplacement]['callcount'] > 0) { + $dataarray[$arrayplacement]['calls'] .= ', '; + } + $dataarray[$arrayplacement]['calls'] .= $qso['callsign']; + $dataarray[$arrayplacement]['callcount']++; + } + } $data['ok'] = 'OK'; $data['qrb'] = $qrb; $data['qsodata'] = $dataarray; $data['unit'] = $unit; - return $data; - } - } + return $data; + } + } /* * Checks the validity of the locator * Input: locator * Returns: bool */ - function valid_locator ($loc) { - $regex = '^[A-R]{2}[0-9]{2}[A-X]{2}$'; - if (preg_match("%{$regex}%i", $loc)) { - return true; - } - else { - return false; - } - } + function valid_locator ($loc) { + $regex = '^[A-R]{2}[0-9]{2}[A-X]{2}$'; + if (preg_match("%{$regex}%i", $loc)) { + return true; + } + else { + return false; + } + } - /* - * Converts locator to latitude and longitude - * Input: locator - * Returns: array with longitude and latitude - */ - function loc_to_latlon ($loc) { - /* lat */ - $l[0] = - (ord(substr($loc, 1, 1))-65) * 10 - 90 + - (ord(substr($loc, 3, 1))-48) + - (ord(substr($loc, 5, 1))-65) / 24 + 1/48; - $l[0] = $this->deg_to_rad($l[0]); - /* lon */ - $l[1] = - (ord(substr($loc, 0, 1))-65) * 20 - 180 + - (ord(substr($loc, 2, 1))-48) * 2 + - (ord(substr($loc, 4, 1))-65) / 12 + 1/24; - $l[1] = $this->deg_to_rad($l[1]); - - return $l; - } - - function deg_to_rad ($deg) { - return (M_PI * $deg/180); - } - - function bearing_dist($loc1, $loc2, $measurement_base) { - $loc1 = strtoupper($loc1); - $loc2 = strtoupper($loc2); - - if (strlen($loc1) == 4) $loc1 .= 'MM'; - if (strlen($loc2) == 4) $loc2 .= 'MM'; - - if (!$this->valid_locator($loc1) || !$this->valid_locator($loc2)) { - return 0; - } - - $l1 = $this->loc_to_latlon($loc1); - $l2 = $this->loc_to_latlon($loc2); - - $co = cos($l1[1] - $l2[1]) * cos($l1[0]) * cos($l2[0]) + sin($l1[0]) * sin($l2[0]); - $ca = atan2(sqrt(1 - $co*$co), $co); - - switch ($measurement_base) { - case 'M': - return ceil(6371*$ca/1.609344); - case 'K': - return ceil(6371*$ca); - case 'N': - return ceil(6371*$ca/1.852); - default: - return ceil(6371*$ca); - } - } - - /* + /* * Used to fetch QSOs from the logbook in the awards */ public function qso_details($distance, $band, $sat){ @@ -282,7 +230,7 @@ class Distances_model extends CI_Model $this->db->where('COL_DISTANCE <=', $distarray[1]); $this->db->where('LENGTH(col_gridsquare) >', 0); - $this->db->where_in($this->config->item('table_name').'.station_id', $logbooks_locations_array); + $this->db->where_in($this->config->item('table_name').'.station_id', $logbooks_locations_array); if ($band != 'All') { if($band != "sat") { @@ -303,7 +251,7 @@ class Distances_model extends CI_Model function getdistparams($distance) { $temp = explode('-', $distance); $regex = '[a-zA-Z]+'; - preg_match("%{$regex}%i", $temp[0], $unit); + preg_match("%{$regex}%i", $temp[0], $unit); $result = []; $result[0] = filter_var($temp[0], FILTER_SANITIZE_NUMBER_INT); diff --git a/application/models/Eqslmethods_model.php b/application/models/Eqslmethods_model.php index 5ad652dd..5972bd5d 100644 --- a/application/models/Eqslmethods_model.php +++ b/application/models/Eqslmethods_model.php @@ -154,8 +154,8 @@ 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 + // We could also probably use this use this: https://eqsl.cc/qslcard/VerifyQSO.txt + // https://www.eqsl.cc/qslcard/ImportADIF.txt 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 diff --git a/application/models/Logbook_model.php b/application/models/Logbook_model.php index f0e54c2e..42fe8bbc 100755 --- a/application/models/Logbook_model.php +++ b/application/models/Logbook_model.php @@ -195,7 +195,7 @@ class Logbook_model extends CI_Model { 'COL_QSL_RCVD_VIA' => $this->input->post('qsl_rcvd_method'), 'COL_QSL_VIA' => $this->input->post('qsl_via'), 'COL_QSLMSG' => $this->input->post('qslmsg'), - 'COL_OPERATOR' => $this->session->userdata('user_callsign'), + 'COL_OPERATOR' => $this->input->post('operator_callsign') ?? $this->session->userdata('operator_callsign'), 'COL_QTH' => $this->input->post('qth'), 'COL_PROP_MODE' => $prop_mode, 'COL_IOTA' => $this->input->post('iota_ref') == null ? '' : trim($this->input->post('iota_ref')), @@ -3184,15 +3184,15 @@ class Logbook_model extends CI_Model { if ($markHrd != null) { $input_hrdlog_qso_upload_status = 'Y'; $input_hrdlog_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'] : ''; } 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'] : ''; + } else { $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'] : ''; } diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php index de032084..d3f1eddf 100644 --- a/application/models/Logbookadvanced_model.php +++ b/application/models/Logbookadvanced_model.php @@ -2,11 +2,8 @@ use Cloudlog\QSLManager\QSO; class Logbookadvanced_model extends CI_Model { - /* - * @param array $searchCriteria - * @return array - */ - public function searchQsos($searchCriteria) : array { + + public function searchDb($searchCriteria) { $conditions = []; $binding = [$searchCriteria['user_id']]; @@ -161,6 +158,10 @@ class Logbookadvanced_model extends CI_Model { } } + if (($searchCriteria['ids'] ?? '') !== '') { + $conditions[] = "qsos.COL_PRIMARY_KEY in (".implode(",",$searchCriteria['ids']).")"; + } + $where = trim(implode(" AND ", $conditions)); if ($where != "") { $where = "AND $where"; @@ -179,7 +180,6 @@ class Logbookadvanced_model extends CI_Model { } } - $sql = " SELECT * FROM " . $this->config->item('table_name') . " qsos @@ -202,12 +202,22 @@ class Logbookadvanced_model extends CI_Model { $results = $data->result('array'); + return $results; + } + + /* + * @param array $searchCriteria + * @return array + */ + public function searchQsos($searchCriteria) : array { + $results = $this->searchDb($searchCriteria); + $qsos = []; foreach ($results as $data) { $qsos[] = new QSO($data); } - return $qsos; + return $qsos; } public function getQsosForAdif($ids, $user_id, $sortorder = null) : object { diff --git a/application/models/User_model.php b/application/models/User_model.php index f2ca673b..57dadbdf 100644 --- a/application/models/User_model.php +++ b/application/models/User_model.php @@ -316,6 +316,7 @@ class User_Model extends CI_Model { 'user_name' => $u->row()->user_name, 'user_type' => $u->row()->user_type, 'user_callsign' => $u->row()->user_callsign, + 'operator_callsign' => ((($this->session->userdata('operator_callsign') ?? '') == '') ? $u->row()->user_callsign : $this->session->userdata('operator_callsign')), 'user_locator' => $u->row()->user_locator, 'user_lotw_name' => $u->row()->user_lotw_name, 'user_eqsl_name' => $u->row()->user_eqsl_name, diff --git a/application/models/User_options_model.php b/application/models/User_options_model.php new file mode 100644 index 00000000..9a383338 --- /dev/null +++ b/application/models/User_options_model.php @@ -0,0 +1,33 @@ +db->where('user_id', $this->session->userdata('user_id')); + $this->db->where('option_type', $option_type); + return $this->db->get('user_options'); + } + + public function set_option($option_type, $option_name, $option_array) { + $uid=$this->session->userdata('user_id'); + $sql='insert into user_options (user_id,option_type,option_name,option_key,option_value) values (?,?,?,?,?) ON DUPLICATE KEY UPDATE option_value=?'; + foreach($option_array as $option_key => $option_value) { + $query = $this->db->query($sql, array($uid, $option_type, $option_name, $option_key, $option_value, $option_value)); + } + } + + public function get_options($option_type) { + $uid=$this->session->userdata('user_id'); + $sql='select option_name,option_key,option_value from user_options where user_id=? and option_type=?'; + return $this->db->query($sql, array($uid, $option_type)); + } + + public function del_option($option_type, $option_name) { + $uid=$this->session->userdata('user_id'); + $sql='delete from user_options where user_id=? and option_type=? and option_name=?'; + return $this->db->query($sql, array($uid, $option_type,$option_name)); + } + +} + +?> diff --git a/application/views/contesting/index.php b/application/views/contesting/index.php index f4f3ea14..aaa54a6c 100644 --- a/application/views/contesting/index.php +++ b/application/views/contesting/index.php @@ -30,6 +30,11 @@ } ?> + + +
+ ' required> +
diff --git a/application/views/eqsl/import.php b/application/views/eqsl/import.php index 2c9edf72..f0167906 100644 --- a/application/views/eqsl/import.php +++ b/application/views/eqsl/import.php @@ -30,7 +30,7 @@ Import from file...

-

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

+

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



diff --git a/application/views/gridmap/index.php b/application/views/gridmap/index.php index 43168a75..cd6f79fe 100644 --- a/application/views/gridmap/index.php +++ b/application/views/gridmap/index.php @@ -74,7 +74,7 @@ submode == null) { + if ($mode->submode ?? '' == '') { echo ''."\n"; } } diff --git a/application/views/interface_assets/footer.php b/application/views/interface_assets/footer.php index 27ecf041..262abec5 100644 --- a/application/views/interface_assets/footer.php +++ b/application/views/interface_assets/footer.php @@ -583,7 +583,7 @@ function newpath(latlng1, latlng2, locator1, locator2) { var osmUrl='optionslib->get_option('option_map_tile_server');?>'; var osmAttrib='Map data © OpenStreetMap contributors'; - var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 9, attribution: osmAttrib}); + var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 12, attribution: osmAttrib}); var redIcon = L.icon({ iconUrl: icon_dot_url, @@ -637,7 +637,7 @@ function showActivatorsMap(call, count, grids) { var osmUrl='optionslib->get_option('option_map_tile_server');?>'; var osmAttrib='Map data © OpenStreetMap contributors'; - var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 9, attribution: osmAttrib}); + var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 12, attribution: osmAttrib}); map.addLayer(osm); } diff --git a/application/views/interface_assets/header.php b/application/views/interface_assets/header.php index 42f3dbfe..234a479f 100644 --- a/application/views/interface_assets/header.php +++ b/application/views/interface_assets/header.php @@ -198,7 +198,7 @@
- +
diff --git a/application/views/logbookadvanced/index.php b/application/views/logbookadvanced/index.php index 49d63ce3..bd7fee3b 100644 --- a/application/views/logbookadvanced/index.php +++ b/application/views/logbookadvanced/index.php @@ -1,63 +1,93 @@ +
- session->flashdata('message')) { ?> - -
-

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

-
- -
+ session->flashdata('message')) { ?> + +
+

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

+
+ +
-
" method="post"> -
-
-
- -
- -
-
-
-
-
-
- -
- -
-
-
-
-
-
- - +
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + -
-
- - -
-
- - +
+
+ + -
-
- - + + tag; echo '>' . $iota->tag . ' - ' . $iota->name . ''; } ?> - -
-
- - -
-
- - -
-
- - +
+
+ + +
+
+ + -
-
- - + + - -
- -
- - -
-
- - + + + + + + + + + + + + + + + + + + + + +
+
+ + -
-
- - -
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - - - - - - - - -
-
- - -
-
-
+ ?> + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + + + + + + + +
+
+ + +
+
+
-
-
- With selected: - - - - - - - - - - - - - - - -
-
-
-
- Quick search with selected: - - - - - - - - - - - -
-
- +
+
+ With selected: + + + + + + + + + + + + + + + +
+
+
+
+ Quick search with selected: + + + + + + + + + + + +
+
-
- - - - - - - +
+ + + + + + + + + +
-
- - - - - - - - - - - - - - - - - session->userdata('user_eqsl_name') != ""){ +
Date/TimeDeDxModeRST (S)RST (R)BandMy RefsRefsNameQSL ViaQSL
+ + + + + + + + + + + + + + + + session->userdata('user_eqsl_name') != ""){ echo ''; } ?> - session->userdata('user_lotw_name') != ""){ + session->userdata('user_lotw_name') != ""){ echo ''; } ?> - - - - - - - - - -
+
+
Date/TimeDeDxModeRST (S)RST (R)BandMy RefsRefsNameQSL ViaQSLeQSLLoTWQSL MsgDXCCStateCQ ZoneIOTA
+ QSL Msg + DXCC + State + CQ Zone + IOTA + + + + + diff --git a/application/views/qso/index.php b/application/views/qso/index.php index 93ccd14d..5c257555 100755 --- a/application/views/qso/index.php +++ b/application/views/qso/index.php @@ -34,7 +34,17 @@ - + + + +
@@ -65,7 +75,7 @@
optionslib->get_option('dxcache_url') != '') { ?>  - +
@@ -211,7 +221,13 @@
-
+ +
+ + +
+ +
diff --git a/application/views/view_log/partial/log_ajax.php b/application/views/view_log/partial/log_ajax.php index e0afda10..e0e55f26 100644 --- a/application/views/view_log/partial/log_ajax.php +++ b/application/views/view_log/partial/log_ajax.php @@ -112,7 +112,7 @@ function echoQrbCalcLink($mygrid, $grid, $vucc) { } elseif ($diff > 7) { $lotw_hint = ' lotw_info_yellow'; } - $timestamp = strtotime($row->lastupload); echo ($row->callsign == '' ? '' : ' L'); + $timestamp = strtotime($row->lastupload); echo ($row->callsign == '' ? '' : ' L'); } ?> diff --git a/application/views/view_log/qso.php b/application/views/view_log/qso.php index 5aa66b60..fdba5f55 100644 --- a/application/views/view_log/qso.php +++ b/application/views/view_log/qso.php @@ -354,7 +354,7 @@ lotwuser != null) { ?> -

lastupload); echo date($custom_date_format, $timestamp); $timestamp = strtotime($row->lastupload); echo " at ".date('H:i', $timestamp);?> UTC.

+

: '; ?>lastupload); echo date($custom_date_format, $timestamp); $timestamp = strtotime($row->lastupload); echo " ".date('H:i', $timestamp);?> UTC.

COL_LOTW_QSL_RCVD == "Y") { ?> diff --git a/assets/css/cyborg/overrides.css b/assets/css/cyborg/overrides.css index fe94a530..bef177b5 100644 --- a/assets/css/cyborg/overrides.css +++ b/assets/css/cyborg/overrides.css @@ -116,4 +116,24 @@ path.grid-worked { .selectize-dropdown, .selectize-dropdown.form-control { border-radius: 0; -} \ No newline at end of file +} + + +#lotw_badge { + float:right; +} + +#edit_qso:not(.btn) { float:left; +} + +.qso_call { + float:left; + width:140px; +} + +.qso_icons { + float:right; +} + +#qsoList_wrapper th { text-align: left !important; white-space: nowrap;} +#qsoList_wrapper td { text-align: left !important; white-space: nowrap;} diff --git a/assets/css/darkly/overrides.css b/assets/css/darkly/overrides.css index 9d5ea2bf..39e30072 100644 --- a/assets/css/darkly/overrides.css +++ b/assets/css/darkly/overrides.css @@ -108,4 +108,24 @@ div.alert-success a, div.alert-danger a, div.alert-danger { .selectize-dropdown, .selectize-dropdown.form-control { border-radius: 0; -} \ No newline at end of file +} + +#lotw_badge { + float:right; +} + +#edit_qso:not(.btn) { + float:left; +} + +.qso_call { + float:left; + width:140px; +} + +.qso_icons { + float:right; +} + +#qsoList_wrapper th { text-align: left !important; white-space: nowrap;} +#qsoList_wrapper td { text-align: left !important; white-space: nowrap;} diff --git a/assets/css/default/overrides.css b/assets/css/default/overrides.css index 57b583fb..84d4d651 100644 --- a/assets/css/default/overrides.css +++ b/assets/css/default/overrides.css @@ -4,4 +4,24 @@ thead>tr>td { .selectize-input { border: 1px solid #ced4da; -} \ No newline at end of file +} + +#lotw_badge { + float:right; +} + +#edit_qso:not(.btn) { + float:left; +} + +.qso_call { + float:left; + width:140px; +} + +.qso_icons { + float:right; +} + +#qsoList_wrapper th { text-align: left !important; white-space: nowrap;} +#qsoList_wrapper td { text-align: left !important; white-space: nowrap;} diff --git a/assets/css/general.css b/assets/css/general.css index a4705e96..a4ba54d6 100644 --- a/assets/css/general.css +++ b/assets/css/general.css @@ -515,4 +515,17 @@ div#station_logbooks_linked_table_paginate { .previous-qsos table { margin-bottom: 0px; +} + +#advancedmap { + height: calc(100vh - 280px) !important; + max-height: 1000px !important; +} + +.lotw-cert-list table { + margin-bottom: 0px; +} + +.qso_panel a i.fa.fa-star:hover { + color: #FFD700 !important; } \ No newline at end of file diff --git a/assets/css/superhero/overrides.css b/assets/css/superhero/overrides.css index 33a991cb..4871dfc5 100644 --- a/assets/css/superhero/overrides.css +++ b/assets/css/superhero/overrides.css @@ -112,4 +112,24 @@ div.alert-danger { .selectize-dropdown, .selectize-dropdown.form-control { border-radius: 0; -} \ No newline at end of file +} + +.qso_call { + float:left; + width:140px; +} + +.qso_icons { + float:right; +} + +#qsoList_wrapper th { text-align: left !important; white-space: nowrap;} +#qsoList_wrapper td { text-align: left !important; white-space: nowrap;} + +#lotw_badge { + float:right; +} + +#edit_qso:not(.btn) { + float:left; +} diff --git a/assets/js/leaflet/leafembed.js b/assets/js/leaflet/leafembed.js index c0ece429..5b8e556e 100644 --- a/assets/js/leaflet/leafembed.js +++ b/assets/js/leaflet/leafembed.js @@ -25,7 +25,7 @@ function initmap(ShowGrid = 'No', MapTag = 'map') { // create the tile layer with correct attribution var osmAttrib='Map data © OpenStreetMap contributors'; - var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 9, attribution: osmAttrib}); + var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 12, attribution: osmAttrib}); var printer = L.easyPrint({ tileLayer: osm, diff --git a/assets/js/sections/common.js b/assets/js/sections/common.js index 265f27f1..158b1228 100644 --- a/assets/js/sections/common.js +++ b/assets/js/sections/common.js @@ -345,13 +345,13 @@ function calculateQrb() { data: {'locator1': locator1, 'locator2': locator2}, success: function (html) { - + var result = "
Negative latitudes are south of the equator, negative longitudes are west of Greenwich.
"; result += ' ' + locator1.toUpperCase() + ' Latitude = ' + html['latlng1'][0] + ' Longitude = ' + html['latlng1'][1] + '
'; result += ' ' + locator2.toUpperCase() + ' Latitude = ' + html['latlng2'][0] + ' Longitude = ' + html['latlng2'][1] + '
'; result += 'Distance between ' + locator1.toUpperCase() + ' and ' + locator2.toUpperCase() + ' is ' + html['distance'] + '.
'; result += 'The bearing is ' + html['bearing'] + '.
'; - + $(".qrbResult").html(result); newpath(html['latlng1'], html['latlng2'], locator1, locator2); } @@ -362,10 +362,14 @@ function calculateQrb() { } function validateLocator(locator) { + vucc_gridno = locator.split(",").length; + if(vucc_gridno == 3 || vucc_gridno > 4) { + return false; + } if(locator.length < 4 && !(/^[a-rA-R]{2}[0-9]{2}[a-xA-X]{0,2}[0-9]{0,2}[a-xA-X]{0,2}$/.test(locator))) { return false; } - + return true; } diff --git a/assets/js/sections/gridmap.js b/assets/js/sections/gridmap.js index b8ab1687..922397e9 100644 --- a/assets/js/sections/gridmap.js +++ b/assets/js/sections/gridmap.js @@ -51,7 +51,7 @@ function gridPlot(form) { grid_four_confirmed = data.grid_4char_confirmed; grid_six_confirmed = data.grid_6char_confirmed; var layer = L.tileLayer(jslayer, { - maxZoom: 9, + maxZoom: 12, attribution: jsattribution, id: 'mapbox.streets' }); diff --git a/assets/js/sections/logbookadvanced.js b/assets/js/sections/logbookadvanced.js index 6b393de5..824da49a 100644 --- a/assets/js/sections/logbookadvanced.js +++ b/assets/js/sections/logbookadvanced.js @@ -26,7 +26,7 @@ function updateRow(qso) { let c = 1; cells.eq(c++).text(qso.qsoDateTime); cells.eq(c++).text(qso.de); - cells.eq(c++).html(''+qso.dx+'' + (qso.callsign == '' ? '' : ' L') + ' Lookup ' + qso.dx + ' on QRZ.com Lookup ' + qso.dx + ' on HamQTH'); + cells.eq(c++).html(''+qso.dx+'' + (qso.callsign == '' ? '' : ' L') + ' Lookup ' + qso.dx + ' on QRZ.com Lookup ' + qso.dx + ' on HamQTH'); cells.eq(c++).text(qso.mode); cells.eq(c++).text(qso.rstS); cells.eq(c++).text(qso.rstR); @@ -81,7 +81,7 @@ function loadQSOTable(rows) { data.push('
'); data.push(qso.qsoDateTime); data.push(qso.de); - data.push(''+qso.dx+'' + (qso.callsign == '' ? '' : ' L') + ' Lookup ' + qso.dx + ' on QRZ.com Lookup ' + qso.dx + ' on HamQTH'); + data.push(''+qso.dx+'' + (qso.callsign == '' ? '' : ' L') + ' Lookup ' + qso.dx + ' on QRZ.com Lookup ' + qso.dx + ' on HamQTH'); data.push(qso.mode); data.push(qso.rstS); data.push(qso.rstR); @@ -167,6 +167,17 @@ $(document).ready(function () { }); $('#searchForm').submit(function (e) { + var container = L.DomUtil.get('advancedmap'); + + if(container != null){ + container._leaflet_id = null; + container.remove(); + } + + $("#qsoList").attr("Hidden", false); + $("#qsoList_wrapper").attr("Hidden", false); + $("#qsoList_info").attr("Hidden", false); + $('#searchButton').prop("disabled", true); $.ajax({ @@ -675,3 +686,237 @@ function printlabel() { }); } +function mapQsos(form) { + $('#mapButton').prop("disabled", true); + + var id_list=[]; + var elements = $('#qsoList tbody input:checked'); + var nElements = elements.length; + + elements.each(function() { + let id = $(this).first().closest('tr').data('qsoID') + id_list.push(id); + unselectQsoID(id); + }); + + $("#qsoList").attr("Hidden", true); + $("#qsoList_wrapper").attr("Hidden", true); + $("#qsoList_info").attr("Hidden", true); + + var amap = $('#advancedmap').val(); + if (amap == undefined) { + $(".qso_manager").append('
'); + } + + if (id_list.length > 0) { + $.ajax({ + url: base_url + 'index.php/logbookadvanced/mapSelectedQsos', + type: 'post', + data: { + ids: id_list + }, + success: function(data) { + loadMap(data); + }, + error: function() { + $('#mapButton').prop("disabled", false); + }, + }); + } else { + $.ajax({ + url: base_url + 'index.php/logbookadvanced/mapQsos', + type: 'post', + data: { + dateFrom: form.dateFrom.value, + dateTo: form.dateTo.value, + de: form.de.value, + dx: form.dx.value, + mode: form.mode.value, + band: form.band.value, + qslSent: form.qslSent.value, + qslReceived: form.qslReceived.value, + iota: form.iota.value, + dxcc: form.dxcc.value, + propmode: form.selectPropagation.value, + gridsquare: form.gridsquare.value, + state: form.state.value, + qsoresults: form.qsoResults.value, + sats: form.sats.value, + cqzone: form.cqzone.value, + lotwSent: form.lotwSent.value, + lotwReceived: form.lotwReceived.value, + eqslSent: form.eqslSent.value, + eqslReceived: form.eqslReceived.value, + qslvia: $('[name="qslviainput"]').val(), + sota: form.sota.value, + pota: form.pota.value, + wwff: form.wwff.value, + qslimages: form.qslimages.value, + }, + success: function(data) { + loadMap(data); + }, + error: function() { + $('#mapButton').prop("disabled", false); + }, + }); + } +}; + +function loadMap(data) { + $('#mapButton').prop("disabled", false); + var osmUrl='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; + var osmAttrib='Map data © OpenStreetMap contributors'; + // If map is already initialized + var container = L.DomUtil.get('advancedmap'); + + if(container != null){ + container._leaflet_id = null; + container.remove(); + $(".qso_manager").append('
'); + } + + var map = new L.Map('advancedmap', { + fullscreenControl: true, + fullscreenControlOptions: { + position: 'topleft' + }, + }); + + L.tileLayer( + osmUrl, + { + attribution: '© OpenStreetMap contributors, CC-BY-SA', + maxZoom: 18, + zoom: 3, + minZoom: 2, + } + ).addTo(map); + + map.setView([30, 0], 1.5); + + var maidenhead = L.maidenheadqrb().addTo(map); + + var osm = new L.TileLayer(osmUrl, {minZoom: 1, maxZoom: 9, attribution: osmAttrib}); + + map.addLayer(osm); + + var linecolor = 'blue'; + + if (isDarkModeTheme()) { + linecolor = 'red'; + } + + var redIcon = L.icon({ + iconUrl: icon_dot_url, + iconSize: [10, 10], // size of the icon + }); + + var counter = 0; + + $.each(data, function(k, v) { + counter++; + // Need to fix so that marker is placed at same place as end of line, but this only needs to be done when longitude is < -170 + if (this.latlng2[1] < -170) { + this.latlng2[1] = parseFloat(this.latlng2[1])+360; + } + if (this.latlng1[1] < -170) { + this.latlng1[1] = parseFloat(this.latlng1[1])+360; + } + + var popupmessage = createContentMessage(this); + var popupmessage2 = createContentMessageDx(this); + + var marker = L.marker([this.latlng1[0], this.latlng1[1]], {icon: redIcon}, {closeOnClick: false, autoClose: false}).addTo(map).bindPopup(popupmessage); + marker.on('mouseover',function(ev) { + ev.target.openPopup(); + }); + + var marker2 = L.marker([this.latlng2[0], this.latlng2[1]], {icon: redIcon},{closeOnClick: false, autoClose: false}).addTo(map).bindPopup(popupmessage2);; + marker2.on('mouseover',function(ev) { + ev.target.openPopup(); + }); + + const multiplelines = []; + multiplelines.push( + new L.LatLng(this.latlng1[0], this.latlng1[1]), + new L.LatLng(this.latlng2[0], this.latlng2[1]) + ) + + const geodesic = L.geodesic(multiplelines, { + weight: 1, + opacity: 1, + color: linecolor, + wrap: false, + steps: 100 + }).addTo(map); + }); + + /*Legend specific*/ + var legend = L.control({ position: "topright" }); + + legend.onAdd = function(map) { + var div = L.DomUtil.create("div", "legend"); + div.innerHTML += "

" + counter + " QSOs plotted

"; + return div; + }; + + legend.addTo(map); +} + + function createContentMessage(qso) { + var table = '' + + '' + + '" + + '' + + '"; + return (table += "
' + + 'Station callsign: ' + qso.mycallsign + + "
' + + 'Gridsquare: ' + qso.mygridsquare + + "
"); + } + + function createContentMessageDx(qso) { + var table = '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + if (qso.satname != "") { + table += '' + + '' + + '' + + ''; + } else { + table += '' + + '' + + '' + + ''; + } + table += '' + + '' + + '' + + ''; + if (qso.gridsquare != undefined) { + table += '' + + '' + + ''; + } + if (qso.distance != undefined) { + table += '' + + '' + + ''; + } + if (qso.bearing != undefined) { + table += '' + + '' + + ''; + } + return (table += '
Callsign' + qso.callsign + '
Date/time' + qso.datetime + '
Band' + qso.satname + '
Band' + qso.band + '
Mode' + qso.mode + '
Gridsquare' + qso.gridsquare + '
Distance' + qso.distance + '
Bearing' + qso.bearing + '
'); + } diff --git a/assets/js/sections/qso.js b/assets/js/sections/qso.js index 3ad082e5..9e2c92d2 100644 --- a/assets/js/sections/qso.js +++ b/assets/js/sections/qso.js @@ -1,5 +1,81 @@ $( document ).ready(function() { +var favs={}; + get_fav(); + + $('#fav_add').click(function (event) { + save_fav(); + }); + + $(document).on("click", "#fav_del", function (event) { + del_fav($(this).attr('name')); + }); + + $(document).on("click", "#fav_recall", function (event) { + $('#sat_name').val(favs[this.innerText].sat_name); + $('#sat_mode').val(favs[this.innerText].sat_mode); + $('#band_rx').val(favs[this.innerText].band_rx); + $('#band').val(favs[this.innerText].band); + $('#frequency_rx').val(favs[this.innerText].frequency_rx); + $('#frequency').val(favs[this.innerText].frequency); + $('#selectPropagation').val(favs[this.innerText].prop_mode); + $('#mode').val(favs[this.innerText].mode); + }); + + + function del_fav(name) { + if (confirm("Are you sure to delete Fav?")) { + $.ajax({ + url: base_url+'index.php/user_options/del_fav', + method: 'POST', + dataType: 'json', + contentType: "application/json; charset=utf-8", + data: JSON.stringify({ "option_name": name }), + success: function(result) { + get_fav(); + } + }); + } + } + + function get_fav() { + $.ajax({ + url: base_url+'index.php/user_options/get_fav', + method: 'GET', + dataType: 'json', + contentType: "application/json; charset=utf-8", + success: function(result) { + $("#fav_menu").empty(); + for (const key in result) { + $("#fav_menu").append(''); + } + favs=result; + } + }); + } + + function save_fav() { + var payload={}; + payload.sat_name=$('#sat_name').val(); + payload.sat_mode=$('#sat_mode').val(); + payload.band_rx=$('#band_rx').val(); + payload.band=$('#band').val(); + payload.frequency_rx=$('#frequency_rx').val(); + payload.frequency=$('#frequency').val(); + payload.prop_mode=$('#selectPropagation').val(); + payload.mode=$('#mode').val(); + $.ajax({ + url: base_url+'index.php/user_options/add_edit_fav', + method: 'POST', + dataType: 'json', + contentType: "application/json; charset=utf-8", + data: JSON.stringify(payload), + success: function(result) { + get_fav(); + } + }); + } + var bc_bandmap = new BroadcastChannel('qso_window'); bc_bandmap.onmessage = function (ev) { @@ -495,6 +571,8 @@ $("#callsign").focusout(function() { } else if (result.lotw_days > 7) { $('#lotw_info').addClass('lotw_info_yellow'); } + $('#lotw_link').attr('href',"https://lotw.arrl.org/lotwuser/act?act="+find_callsign); + $('#lotw_link').attr('target',"_blank"); $('#lotw_info').attr('data-toggle',"tooltip"); $('#lotw_info').attr('data-original-title',"LoTW User. Last upload was "+result.lotw_days+" days ago"); $('[data-toggle="tooltip"]').tooltip(); @@ -867,4 +945,4 @@ function closeModal() { container.removeChild(backdrop) container.removeChild(modal) }, 200) -} \ No newline at end of file +} diff --git a/docker/Dockerfile b/docker/Dockerfile index 725bc2c6..da2bfd74 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,24 +1,24 @@ -FROM php:7.4-apache +FROM php:8.2-apache +# Enabling custom upload settings in PHP RUN touch /usr/local/etc/php/conf.d/uploads.ini \ && echo "file_uploads = On" >> /usr/local/etc/php/conf.d/uploads.ini \ && echo "memory_limit = 64M" >> /usr/local/etc/php/conf.d/uploads.ini \ && echo "upload_max_filesize = 64M" >> /usr/local/etc/php/conf.d/uploads.ini \ && echo "post_max_size = 64M" >> /usr/local/etc/php/conf.d/uploads.ini \ && echo "max_execution_time = 60" >> /usr/local/etc/php/conf.d/uploads.ini +# Adding required libraries and modules RUN apt-get update \ && apt-get install -y git curl libxml2-dev libonig-dev RUN docker-php-ext-install mysqli mbstring xml -#RUN docker-php-ext-install curl -#RUN docker-php-ext-install openssl +# Cleanup RUN rm -rf /var/www/html/docker/ +# Copy proper file to target image COPY ./ /var/www/html/ WORKDIR /var/www/html # Setting permissions as: https://github.com/magicbug/Cloudlog/wiki/Installation RUN cd /var/www/html \ -&& echo "Setting root as owner of the html folder" \ && chown -R root:www-data /var/www/html -RUN echo "Setting permissions to the install folder" \ -&& chmod -R g+rw ./application/config/ \ +RUN chmod -R g+rw ./application/config/ \ && chmod -R g+rw ./application/logs/ \ && chmod -R g+rw ./assets/qslcard/ \ && chmod -R g+rw ./backup/ \ diff --git a/install/assets/install.sql b/install/assets/install.sql index 3fccb104..3d574d07 100755 --- a/install/assets/install.sql +++ b/install/assets/install.sql @@ -296,6 +296,26 @@ CREATE TABLE `TABLE_HRD_CONTACTS_V01` ( -- Records of TABLE_HRD_CONTACTS_V01 -- ---------------------------- + +CREATE TABLE `options` ( + `option_id` bigint(20) UNSIGNED NOT NULL, + `option_name` varchar(191) DEFAULT NULL, + `option_value` longtext NOT NULL, + `autoload` varchar(20) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +ALTER TABLE `options` + ADD PRIMARY KEY (`option_id`), + ADD UNIQUE KEY `option_name` (`option_name`); + +ALTER TABLE `options` + MODIFY `option_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; + + +-- +-- Dumping data for table `options` that stops the version2 trigger from firing +INSERT INTO `options` (`option_id`, `option_name`, `option_value`, `autoload`) VALUES (NULL, 'version2_trigger', 'true', 'yes'); + -- ---------------------------- -- Table structure for timezones -- ---------------------------- diff --git a/install/index.php b/install/index.php index 1e65398d..9524e520 100644 --- a/install/index.php +++ b/install/index.php @@ -19,9 +19,9 @@ function delDir($dir) { } } // This step may be not needed - if (file_exists($dir)) { - rmdir( $dir ); - } + // if (file_exists($dir)) { + // rmdir( $dir ); + // } } if (file_exists($db_file_path)) { diff --git a/src/QSLManager/QSO.php b/src/QSLManager/QSO.php index 97c98d26..f488fdc2 100644 --- a/src/QSLManager/QSO.php +++ b/src/QSLManager/QSO.php @@ -202,8 +202,8 @@ class QSO } else { $this->end = null; } - $this->callsign = ($data['callsign'] ?? null === null) ? '' :$data['callsign']; - $this->lastupload = ($data['lastupload'] ?? null === null) ? '' : date($custom_date_format . " H:i", strtotime($data['lastupload'] ?? null)); + $this->callsign = (($data['callsign'] ?? null) === null) ? '' : $data['callsign']; + $this->lastupload = (($data['lastupload'] ?? null) === null) ? '' : date($custom_date_format . " H:i", strtotime($data['lastupload'] ?? null)); $this->lotw_hint = $this->getLotwHint($data['lastupload'] ?? null); } diff --git a/update_cloudlog.sh b/update_cloudlog.sh index 6a0927e7..fa1a0f20 100644 --- a/update_cloudlog.sh +++ b/update_cloudlog.sh @@ -10,7 +10,7 @@ # The user and group that own the CLOUDLOG_SUBDIR directories. Passed to 'chown' as-is. DIR_OWNERSHIP="root:www-data" # The list of directories that need to have ownership restored after a git pull -declare -a CLOUDLOG_SUBDIRS=("application/config" "assets" "backup" "updates" "uploads") +declare -a CLOUDLOG_SUBDIRS=("application/config" "assets" "backup" "updates" "uploads" "images/eqsl_card_images") # The name of the Git remote to fetch/pull from GIT_REMOTE="origin" # If true, pull from the HEAD of the configured origin, otherwise the latest tag