2023-07-07 10:03:52 +02:00
< ? php
2022-12-18 16:49:54 +01:00
2024-01-17 14:20:10 +00:00
use Wavelog\QSLManager\QSO ;
2022-12-18 16:49:54 +01:00
if ( ! defined ( 'BASEPATH' )) exit ( 'No direct script access allowed' );
class Logbookadvanced extends CI_Controller {
function __construct ()
{
parent :: __construct ();
$this -> load -> helper ( array ( 'form' , 'url' , 'psr4_autoloader' ));
if ( ! $this -> user_model -> authorize ( 2 )) {
2024-08-16 10:08:44 +02:00
$this -> session -> set_flashdata ( 'error' , __ ( " You're not allowed to do that! " ));
2022-12-18 16:49:54 +01:00
redirect ( 'dashboard' );
}
2025-06-23 19:22:38 +00:00
if ( ! $this -> load -> is_loaded ( 'DxccFlag' )) {
$this -> load -> library ( 'DxccFlag' );
}
2022-12-18 16:49:54 +01:00
}
function index () {
$this -> load -> model ( 'stations' );
$this -> load -> model ( 'logbookadvanced_model' );
$this -> load -> model ( 'logbook_model' );
$this -> load -> model ( 'bands' );
$this -> load -> model ( 'iota' );
$this -> load -> model ( 'dxcc' );
2023-08-30 08:54:06 +02:00
$this -> load -> model ( 'user_options_model' );
2022-12-18 16:49:54 +01:00
$data = [];
2024-06-08 11:01:59 +02:00
$data [ 'page_title' ] = __ ( " Advanced logbook " );
2022-12-18 16:49:54 +01:00
$data [ 'hasDatePicker' ] = true ;
2023-08-30 08:54:06 +02:00
$userOptions = $this -> user_options_model -> get_options ( 'LogbookAdvanced' ) -> result ();
2023-08-30 12:53:49 +02:00
if ( isset ( $userOptions [ 0 ])) {
$data [ 'options' ] = $userOptions [ 0 ] -> option_value ;
}
2023-08-30 08:54:06 +02:00
2024-02-15 12:08:56 +01:00
$mapoptions [ 'gridsquare_layer' ] = $this -> user_options_model -> get_options ( 'LogbookAdvancedMap' , array ( 'option_name' => 'gridsquare_layer' , 'option_key' => 'boolean' )) -> row ();
$mapoptions [ 'path_lines' ] = $this -> user_options_model -> get_options ( 'LogbookAdvancedMap' , array ( 'option_name' => 'path_lines' , 'option_key' => 'boolean' )) -> row ();
$mapoptions [ 'cqzones_layer' ] = $this -> user_options_model -> get_options ( 'LogbookAdvancedMap' , array ( 'option_name' => 'cqzones_layer' , 'option_key' => 'boolean' )) -> row ();
$mapoptions [ 'ituzones_layer' ] = $this -> user_options_model -> get_options ( 'LogbookAdvancedMap' , array ( 'option_name' => 'ituzones_layer' , 'option_key' => 'boolean' )) -> row ();
$mapoptions [ 'nightshadow_layer' ] = $this -> user_options_model -> get_options ( 'LogbookAdvancedMap' , array ( 'option_name' => 'nightshadow_layer' , 'option_key' => 'boolean' )) -> row ();
$data [ 'mapoptions' ] = $mapoptions ;
2024-05-31 15:52:38 +02:00
$data [ 'user_map_custom' ] = $this -> optionslib -> get_map_custom ();
2024-02-15 12:08:56 +01:00
2026-05-07 22:07:12 +02:00
$data [ 'adif_propmodes' ] = $this -> config -> item ( 'adif_propmodes' );
2026-05-07 15:39:10 +02:00
2024-01-25 11:22:25 +01:00
$active_station_id = $this -> stations -> find_active ();
2025-03-29 14:08:48 +01:00
$station_profile = $this -> stations -> profile ( $active_station_id );
2024-01-25 11:22:25 +01:00
2022-12-18 16:49:54 +01:00
$pageData = [];
$pageData [ 'datePlaceholder' ] = 'DD/MM/YYYY' ;
2022-12-27 18:56:04 +01:00
$pageData [ 'modes' ] = $this -> logbookadvanced_model -> get_modes ();
2022-12-18 16:49:54 +01:00
$pageData [ 'dxccarray' ] = $this -> logbook_model -> fetchDxcc ();
$pageData [ 'iotaarray' ] = $this -> logbook_model -> fetchIota ();
2025-01-24 15:55:20 +01:00
$pageData [ 'sats' ] = $this -> logbookadvanced_model -> get_worked_sats ();
2024-04-10 01:06:47 +02:00
$pageData [ 'orbits' ] = $this -> bands -> get_worked_orbits ();
2026-06-20 12:43:58 -07:00
if ( ! empty ( $this -> session -> userdata ( 'user_stations_active_log_only' ))) {
2026-06-21 09:52:51 -07:00
$pageData [ 'station_profile' ] = $this -> logbooks_model -> list_logbooks_linked ( $this -> session -> userdata ( 'active_station_logbook' ));
2026-06-20 12:43:58 -07:00
} else {
2026-06-21 09:52:51 -07:00
$pageData [ 'station_profile' ] = $this -> stations -> all_of_user ();
2026-06-20 12:43:58 -07:00
}
2024-01-25 11:22:25 +01:00
$pageData [ 'active_station_info' ] = $station_profile -> row ();
2024-02-08 12:57:58 +01:00
$pageData [ 'homegrid' ] = explode ( ',' , $this -> stations -> find_gridsquare ());
2024-05-24 11:25:44 +02:00
$pageData [ 'active_station_id' ] = $active_station_id ;
2023-07-07 10:03:52 +02:00
2025-01-24 15:55:20 +01:00
$pageData [ 'bands' ] = $this -> logbookadvanced_model -> get_worked_bands ();
2023-05-27 19:05:11 +02:00
// Get Date format
2024-05-19 09:43:43 +02:00
if ( $this -> session -> userdata ( 'user_date_format' )) {
2023-05-27 19:05:11 +02:00
// If Logged in and session exists
2024-05-19 09:43:43 +02:00
$pageData [ 'custom_date_format' ] = $this -> session -> userdata ( 'user_date_format' );
2023-05-27 19:05:11 +02:00
} else {
2024-01-17 14:13:23 +00:00
// Get Default date format from /config/wavelog.php
2024-05-19 09:43:43 +02:00
$pageData [ 'custom_date_format' ] = $this -> config -> item ( 'qso_date_format' );
2023-05-27 19:05:11 +02:00
}
switch ( $pageData [ 'custom_date_format' ]) {
case " d/m/y " : $pageData [ 'custom_date_format' ] = 'DD/MM/YY' ; break ;
case " d/m/Y " : $pageData [ 'custom_date_format' ] = 'DD/MM/YYYY' ; break ;
case " m/d/y " : $pageData [ 'custom_date_format' ] = 'MM/DD/YY' ; break ;
case " m/d/Y " : $pageData [ 'custom_date_format' ] = 'MM/DD/YYYY' ; break ;
case " d.m.Y " : $pageData [ 'custom_date_format' ] = 'DD.MM.YYYY' ; break ;
case " y/m/d " : $pageData [ 'custom_date_format' ] = 'YY/MM/DD' ; break ;
case " Y-m-d " : $pageData [ 'custom_date_format' ] = 'YYYY-MM-DD' ; break ;
case " M d, Y " : $pageData [ 'custom_date_format' ] = 'MMM DD, YYYY' ; break ;
case " M d, y " : $pageData [ 'custom_date_format' ] = 'MMM DD, YY' ; break ;
default : $pageData [ 'custom_date_format' ] = 'DD/MM/YYYY' ;
}
2022-12-18 16:49:54 +01:00
$footerData = [];
$footerData [ 'scripts' ] = [
'assets/js/moment.min.js' ,
2023-05-27 19:05:11 +02:00
'assets/js/datetime-moment.js' ,
2026-02-13 16:58:57 +01:00
'assets/js/sections/logbookadvanced.js' ,
'assets/js/sections/logbookadvanced_edit.js' ,
'assets/js/sections/logbookadvanced_map.js' ,
'assets/js/sections/cqmap_geojson.js' ,
'assets/js/sections/itumap_geojson.js' ,
'assets/js/leaflet/L.Terminator.js' ,
2024-02-08 12:57:58 +01:00
'assets/js/leaflet/geocoding.js' ,
2026-02-13 16:58:57 +01:00
'assets/js/globe/globe.gl.js' ,
'assets/js/bootstrap-multiselect.js' ,
2026-01-17 20:26:14 +01:00
'assets/js/leaflet/L.MaidenheadColouredGridMap.js' ,
2022-12-18 16:49:54 +01:00
];
$this -> load -> view ( 'interface_assets/header' , $data );
$this -> load -> view ( 'logbookadvanced/index' , $pageData );
$this -> load -> view ( 'interface_assets/footer' , $footerData );
}
2025-06-10 16:22:56 +02:00
function mapParameters () {
return array (
2022-12-18 16:49:54 +01:00
'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' )),
2023-10-04 09:27:28 +02:00
'qslSentMethod' => xss_clean ( $this -> input -> post ( 'qslSentMethod' )),
'qslReceivedMethod' => xss_clean ( $this -> input -> post ( 'qslReceivedMethod' )),
2022-12-18 16:49:54 +01:00
'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' )),
2025-06-07 07:36:09 +02:00
'county' => xss_clean ( $this -> input -> post ( 'county' )),
2023-07-05 09:29:13 +02:00
'cqzone' => xss_clean ( $this -> input -> post ( 'cqzone' )),
2024-04-28 09:23:21 +02:00
'ituzone' => xss_clean ( $this -> input -> post ( 'ituzone' )),
2022-12-19 18:20:55 +01:00
'qsoresults' => xss_clean ( $this -> input -> post ( 'qsoresults' )),
2023-05-01 08:58:13 +02:00
'sats' => xss_clean ( $this -> input -> post ( 'sats' )),
2024-04-10 01:06:47 +02:00
'orbits' => xss_clean ( $this -> input -> post ( 'orbits' )),
2023-06-29 18:59:12 +02:00
'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' )),
2025-09-08 09:24:04 +02:00
'dclSent' => xss_clean ( $this -> input -> post ( 'dclSent' )),
'dclReceived' => xss_clean ( $this -> input -> post ( 'dclReceived' )),
2024-07-02 17:46:06 +00:00
'clublogSent' => xss_clean ( $this -> input -> post ( 'clublogSent' )),
'clublogReceived' => xss_clean ( $this -> input -> post ( 'clublogReceived' )),
2023-07-07 10:03:52 +02:00
'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' )),
2023-08-11 19:13:13 +02:00
'qslimages' => xss_clean ( $this -> input -> post ( 'qslimages' )),
2023-10-17 10:14:10 +00:00
'dupes' => xss_clean ( $this -> input -> post ( 'dupes' )),
2025-12-22 08:25:26 +01:00
'dupedate' => xss_clean ( $this -> input -> post ( 'dupedate' )),
'dupemode' => xss_clean ( $this -> input -> post ( 'dupemode' )),
'dupeband' => xss_clean ( $this -> input -> post ( 'dupeband' )),
'dupesat' => xss_clean ( $this -> input -> post ( 'dupesat' )),
2023-12-04 13:21:59 +00:00
'operator' => xss_clean ( $this -> input -> post ( 'operator' )),
2024-06-28 21:17:05 +02:00
'contest' => xss_clean ( $this -> input -> post ( 'contest' )),
2024-08-29 12:49:14 +02:00
'invalid' => xss_clean ( $this -> input -> post ( 'invalid' )),
2024-09-05 10:17:32 +02:00
'continent' => xss_clean ( $this -> input -> post ( 'continent' )),
2025-01-28 09:08:47 +01:00
'comment' => xss_clean ( $this -> input -> post ( 'comment' )),
2025-07-01 15:28:47 +02:00
'qsoids' => xss_clean ( $this -> input -> post ( 'qsoids' )),
2025-11-05 12:25:31 +01:00
'dok' => xss_clean ( $this -> input -> post ( 'dok' )),
'qrzSent' => xss_clean ( $this -> input -> post ( 'qrzSent' )),
2025-11-17 10:07:45 +01:00
'qrzReceived' => xss_clean ( $this -> input -> post ( 'qrzReceived' )),
2025-11-30 15:12:20 +01:00
'distance' => xss_clean ( $this -> input -> post ( 'distance' )),
2026-01-03 11:07:00 +01:00
'sortcolumn' => xss_clean ( $this -> input -> post ( 'sortcolumn' )),
2026-02-22 10:18:14 +01:00
'sortdirection' => xss_clean ( $this -> input -> post ( 'sortdirection' )),
'duration' => xss_clean ( $this -> input -> post ( 'duration' ))
2022-12-18 16:49:54 +01:00
);
2025-06-10 16:22:56 +02:00
}
public function search () {
$this -> load -> model ( 'logbookadvanced_model' );
2022-12-18 16:49:54 +01:00
2025-06-10 16:22:56 +02:00
$searchCriteria = $this -> mapParameters ();
2022-12-18 16:49:54 +01:00
$qsos = [];
2024-11-04 12:42:09 +01:00
2022-12-18 16:49:54 +01:00
foreach ( $this -> logbookadvanced_model -> searchQsos ( $searchCriteria ) as $qso ) {
2025-06-22 23:03:30 +02:00
$qsoArray = $qso -> toArray ();
$flag = $this -> dxccflag -> get ( $qso -> getDXCCId ());
2026-06-06 14:00:57 +02:00
$qsoArray [ 'flag' ] = $this -> flag_html ( $flag );
2025-06-22 23:03:30 +02:00
$qsos [] = $qsoArray ;
2022-12-18 16:49:54 +01:00
}
header ( " Content-Type: application/json " );
print json_encode ( $qsos );
}
public function updateFromCallbook () {
2025-01-02 10:22:23 +01:00
if ( ! clubaccess_check ( 9 )) return ;
2022-12-18 16:49:54 +01:00
$this -> load -> model ( 'logbook_model' );
2022-12-20 22:23:22 +01:00
$this -> load -> model ( 'logbookadvanced_model' );
2022-12-18 16:49:54 +01:00
2024-11-20 16:16:45 +01:00
$qsoID [] = xss_clean ( $this -> input -> post ( 'qsoID' ));
$qso = $this -> logbookadvanced_model -> getQsosForAdif ( json_encode ( $qsoID ), $this -> session -> userdata ( 'user_id' )) -> row_array ();
2022-12-18 16:49:54 +01:00
if ( $qso === null ) {
header ( " Content-Type: application/json " );
echo json_encode ([]);
return ;
}
$callbook = $this -> logbook_model -> loadCallBook ( $qso [ 'COL_CALL' ], $this -> config -> item ( 'use_fullname' ));
2025-11-28 19:22:30 +01:00
$gridsquareAccuracyCheck = xss_clean ( $this -> input -> post ( 'gridsquareAccuracyCheck' ));
2022-12-18 16:49:54 +01:00
2023-08-10 09:07:24 +02:00
if ( $callbook [ 'callsign' ] ? ? " " !== " " ) {
2025-03-29 14:08:48 +01:00
$this -> load -> model ( 'stations' );
$active_station_id = $this -> stations -> find_active ();
$station_profile = $this -> stations -> profile ( $active_station_id ) -> row_array ();
2025-11-28 19:22:30 +01:00
$this -> logbookadvanced_model -> updateQsoWithCallbookInfo ( $qso [ 'COL_PRIMARY_KEY' ], $qso , $callbook , $gridsquareAccuracyCheck , $station_profile [ 'station_gridsquare' ]);
2024-11-20 16:16:45 +01:00
$qso = $this -> logbookadvanced_model -> getQsosForAdif ( json_encode ( $qsoID ), $this -> session -> userdata ( 'user_id' )) -> row_array ();
2025-07-13 20:22:15 +02:00
}
2022-12-18 16:49:54 +01:00
2025-07-13 20:22:15 +02:00
$qsoObj = new QSO ( $qso ); // Redirection via Object to clean/convert QSO (get rid of cols)
$cleaned_qso = $qsoObj -> toArray (); // And back to Array for the JSON
2025-06-30 15:00:44 +00:00
2025-07-13 20:22:15 +02:00
$flag = $this -> dxccflag -> get ( $qsoObj -> getDXCCId ());
2026-06-06 14:00:57 +02:00
$cleaned_qso [ 'flag' ] = $this -> flag_html ( $flag );
2022-12-18 16:49:54 +01:00
header ( " Content-Type: application/json " );
2025-06-30 15:00:44 +00:00
echo json_encode ( $cleaned_qso );
2022-12-18 16:49:54 +01:00
}
function export_to_adif () {
2025-01-02 10:22:23 +01:00
if ( ! clubaccess_check ( 9 )) return ;
2024-05-27 19:11:53 +02:00
ini_set ( 'memory_limit' , '-1' );
set_time_limit ( 0 );
2022-12-18 16:49:54 +01:00
$this -> load -> model ( 'logbookadvanced_model' );
$ids = xss_clean ( $this -> input -> post ( 'id' ));
2026-01-03 11:27:30 +01:00
$sortcolumn = xss_clean ( $this -> input -> post ( 'sortcolumn' ));
$sortdirection = xss_clean ( $this -> input -> post ( 'sortdirection' ));
2022-12-18 16:49:54 +01:00
$user_id = ( int ) $this -> session -> userdata ( 'user_id' );
2026-05-04 14:18:18 +02:00
$data [ 'reverse' ] = ( xss_clean ( $this -> input -> post ( 'reverse' )) == " true " ) ? true : false ;
2026-01-03 11:27:30 +01:00
$data [ 'qsos' ] = $this -> logbookadvanced_model -> getQsosForAdif ( $ids , $user_id , $sortcolumn , $sortdirection );
2022-12-18 16:49:54 +01:00
$this -> load -> view ( 'adif/data/exportall' , $data );
}
2024-05-07 18:22:52 +02:00
function export_to_adif_params () {
2025-01-02 10:22:23 +01:00
if ( ! clubaccess_check ( 9 )) return ;
2024-05-27 19:11:53 +02:00
ini_set ( 'memory_limit' , '-1' );
set_time_limit ( 0 );
2024-05-07 18:22:52 +02:00
$this -> load -> model ( 'logbookadvanced_model' );
2025-06-10 16:22:56 +02:00
$postdata = $this -> mapParameters ();
$postdata [ 'de' ] = explode ( ',' , $postdata [ 'de' ]); // The reason for doing this different, is that the parameter is sent in differently than the regular search
$postdata [ 'qsoresults' ] = 'All' ; // We want all the QSOs regardless of what is set in the qsoresults, to be able to export all QSOs with the filter critera
2024-05-07 18:22:52 +02:00
$data [ 'qsos' ] = $this -> logbookadvanced_model -> getSearchResult ( $postdata );
$this -> load -> view ( 'adif/data/exportall' , $data );
}
2022-12-18 16:49:54 +01:00
function update_qsl () {
2025-01-02 10:22:23 +01:00
if ( ! clubaccess_check ( 9 )) return ;
2022-12-18 16:49:54 +01:00
$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 -> updateQsl ( $ids , $user_id , $method , $sent );
$data = $this -> logbookadvanced_model -> getQsosForAdif ( $ids , $user_id );
$results = $data -> result ( 'array' );
2023-07-07 10:03:52 +02:00
2025-06-23 19:22:38 +00:00
$qsos = [];
foreach ( $results as $data ) {
$qsos [] = new QSO ( $data );
}
2022-12-18 16:49:54 +01:00
$q = [];
foreach ( $qsos as $qso ) {
2025-06-23 19:22:38 +00:00
$singleQso = $qso -> toArray ();
$flag = $this -> dxccflag -> get ( $qso -> getDXCCId ());
2026-06-06 14:00:57 +02:00
$singleQso [ 'flag' ] = $this -> flag_html ( $flag );
2025-06-23 19:22:38 +00:00
$q [] = $singleQso ;
2022-12-18 16:49:54 +01:00
}
header ( " Content-Type: application/json " );
print json_encode ( $q );
}
2023-06-28 08:27:44 +02:00
function update_qsl_received () {
2025-01-02 10:22:23 +01:00
if ( ! clubaccess_check ( 9 )) return ;
2023-06-28 08:27:44 +02:00
$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' );
2023-07-07 10:03:52 +02:00
2025-06-23 19:22:38 +00:00
$qsos = [];
foreach ( $results as $data ) {
$qsos [] = new QSO ( $data );
}
2023-06-28 08:27:44 +02:00
$q = [];
foreach ( $qsos as $qso ) {
2025-06-23 19:22:38 +00:00
$singleQso = $qso -> toArray ();
$flag = $this -> dxccflag -> get ( $qso -> getDXCCId ());
2026-06-06 14:00:57 +02:00
$singleQso [ 'flag' ] = $this -> flag_html ( $flag );
2025-06-23 19:22:38 +00:00
$q [] = $singleQso ;
2023-06-28 08:27:44 +02:00
}
header ( " Content-Type: application/json " );
print json_encode ( $q );
}
2023-08-01 10:30:05 +02:00
public function startAtLabel () {
$this -> load -> view ( 'logbookadvanced/startatform' );
}
2023-08-11 19:13:13 +02:00
2026-06-15 18:21:20 +02:00
public function printQslForm () {
$this -> load -> model ( 'Qslpostcard_model' );
$data [ 'templates' ] = $this -> Qslpostcard_model -> list_templates ();
$this -> load -> view ( 'logbookadvanced/printQsl' , $data );
}
2023-08-11 19:13:13 +02:00
public function qslSlideshow () {
2025-06-19 10:01:45 +00:00
$cleanids = json_decode ( $this -> security -> xss_clean ( $this -> input -> post ( 'ids' )));
$this -> load -> model ( 'logbookadvanced_model' );
$data [ 'qslimages' ] = $this -> logbookadvanced_model -> getQslsForQsoIds ( $cleanids );
$this -> load -> view ( 'logbookadvanced/qslcarousel' , $data );
2023-08-11 19:13:13 +02:00
}
2023-08-18 20:02:47 +02:00
2023-08-21 14:18:05 +02:00
public function mapSelectedQsos () {
$this -> load -> model ( 'logbookadvanced_model' );
$searchCriteria = array (
'user_id' => ( int ) $this -> session -> userdata ( 'user_id' ),
'dateFrom' => '' ,
'dateTo' => '' ,
2024-07-11 16:51:53 +02:00
'de' => $this -> input -> post ( 'de' ),
2024-11-24 18:24:43 +01:00
'dx' => '*' ,
2023-08-21 14:18:05 +02:00
'mode' => '' ,
'band' => '' ,
'qslSent' => '' ,
'qslReceived' => '' ,
2023-10-04 10:27:40 +02:00
'qslSentMethod' => '' ,
'qslReceivedMethod' => '' ,
2023-08-21 14:18:05 +02:00
'iota' => '' ,
'dxcc' => '' ,
'propmode' => '' ,
2024-11-24 18:24:43 +01:00
'gridsquare' => '*' ,
'state' => '*' ,
2025-06-07 07:36:09 +02:00
'county' => '*' ,
2025-06-19 09:47:21 +02:00
'cqzone' => 'All' ,
'ituzone' => 'All' ,
2025-06-19 08:55:49 +00:00
'qsoresults' => count ( json_decode ( $this -> input -> post ( 'ids' , true ))),
2023-08-21 14:18:05 +02:00
'sats' => '' ,
2024-04-10 01:06:47 +02:00
'orbits' => '' ,
2023-08-21 14:18:05 +02:00
'lotwSent' => '' ,
'lotwReceived' => '' ,
'eqslSent' => '' ,
'eqslReceived' => '' ,
2025-09-08 09:24:04 +02:00
'dclSent' => '' ,
'dclReceived' => '' ,
2024-07-02 17:46:06 +00:00
'clublogSent' => '' ,
'clublogReceived' => '' ,
2024-11-24 18:24:43 +01:00
'qslvia' => '*' ,
'sota' => '*' ,
'pota' => '*' ,
'wwff' => '*' ,
2023-08-21 14:18:05 +02:00
'qslimages' => '' ,
2024-11-24 18:24:43 +01:00
'operator' => '*' ,
'contest' => '*' ,
2024-09-08 19:45:41 +02:00
'continent' => '' ,
2025-01-28 09:08:47 +01:00
'comment' => '*' ,
2025-07-01 15:28:47 +02:00
'dok' => '*' ,
2025-11-17 14:26:32 +01:00
'distance' => '*' ,
'qrzSent' => '' ,
'qrzReceived' => '' ,
2025-06-19 08:55:49 +00:00
'ids' => json_decode ( xss_clean ( $this -> input -> post ( 'ids' ))),
2026-01-03 09:43:40 +01:00
'qsoids' => xss_clean ( $this -> input -> post ( 'qsoids' )),
2026-01-03 11:07:00 +01:00
'sortcolumn' => 'qsotime' ,
2026-02-22 10:18:14 +01:00
'sortdirection' => 'desc' ,
'duration' => '*'
2023-08-21 14:18:05 +02:00
);
2024-05-07 18:22:52 +02:00
$result = $this -> logbookadvanced_model -> getSearchResultArray ( $searchCriteria );
2026-08-11 17:54:08 +02:00
$this -> prepareMappedQsos ( $result );
2023-08-21 14:18:05 +02:00
}
2023-08-18 20:02:47 +02:00
public function mapQsos () {
2026-08-11 17:54:08 +02:00
$this -> load -> model ( 'logbookadvanced_model' );
2023-08-18 20:02:47 +02:00
2025-06-10 16:22:56 +02:00
$searchCriteria = $this -> mapParameters ();
2023-08-18 20:02:47 +02:00
2024-05-07 18:22:52 +02:00
$result = $this -> logbookadvanced_model -> getSearchResultArray ( $searchCriteria );
2026-08-11 17:54:08 +02:00
$this -> prepareMappedQsos ( $result );
2023-08-21 14:18:05 +02:00
}
2026-08-11 17:54:08 +02:00
public function prepareMappedQsos ( $qsos ) {
2023-08-18 20:02:47 +02:00
if ( $this -> session -> userdata ( 'user_measurement_base' ) == NULL ) {
$measurement_base = $this -> config -> item ( 'measurement_base' );
}
else {
$measurement_base = $this -> session -> userdata ( 'user_measurement_base' );
}
// Get Date format
2024-02-07 10:55:35 +01:00
if ( $this -> session -> userdata ( 'user_date_format' )) {
2023-08-18 20:02:47 +02:00
// If Logged in and session exists
2024-02-07 10:55:35 +01:00
$custom_date_format = $this -> session -> userdata ( 'user_date_format' );
2023-08-18 20:02:47 +02:00
} else {
2024-01-17 14:13:23 +00:00
// Get Default date format from /config/wavelog.php
2024-02-07 10:55:35 +01:00
$custom_date_format = $this -> config -> item ( 'qso_date_format' );
2023-08-18 20:02:47 +02:00
}
switch ( $measurement_base ) {
case 'M' :
$var_dist = " miles " ;
break ;
case 'N' :
$var_dist = " nautic miles " ;
break ;
case 'K' :
$var_dist = " kilometers " ;
break ;
2026-07-11 17:39:50 +02:00
default :
log_message ( 'error' , 'Invalid measurement base: ' . $measurement_base );
return ;
2023-08-18 20:02:47 +02:00
}
$mappedcoordinates = array ();
2023-08-21 14:18:05 +02:00
foreach ( $qsos as $qso ) {
2026-07-15 21:24:09 +02:00
if ( $this -> isValidMaidenheadGrid ( $qso [ 'station_gridsquare' ]) || empty ( $qso [ 'station_gridsquare' ])) {
2023-08-18 20:02:47 +02:00
if ( ! empty ( $qso [ 'COL_GRIDSQUARE' ]) || ! empty ( $qso [ 'COL_VUCC_GRIDS' ])) {
2024-04-25 20:16:36 +02:00
$mappedcoordinates [] = $this -> calculate ( $qso , ( $qso [ 'station_gridsquare' ] ? ? '' ), ( $qso [ 'COL_GRIDSQUARE' ] ? ? '' ) == '' ? $qso [ 'COL_VUCC_GRIDS' ] : $qso [ 'COL_GRIDSQUARE' ], $measurement_base , $var_dist , $custom_date_format );
2026-08-13 10:55:10 +02:00
} else {
if ( ! empty ( $qso [ 'lat' ]) && ! empty ( $qso [ 'long' ])) {
$mappedcoordinates [] = $this -> calculateCoordinates ( $qso , $qso [ 'lat' ], $qso [ 'long' ], ( $qso [ 'station_gridsquare' ] ? ? '' ), $measurement_base , $var_dist , $custom_date_format );
}
2023-08-18 20:02:47 +02:00
}
}
}
header ( " Content-Type: application/json " );
print json_encode ( $mappedcoordinates );
}
2024-10-10 19:24:59 +02:00
function isValidMaidenheadGrid ( $grid ) {
2024-10-27 22:19:11 +01:00
if ( strlen ( $grid ) == 4 ) $grid .= " LL " ; // Only 4 Chars? Fill with center "LL" as only A-R allowed
if ( strlen ( $grid ) == 6 ) $grid .= " 55 " ; // Only 6 Chars? Fill with center "55"
if ( strlen ( $grid ) == 8 ) $grid .= " LL " ; // Only 8 Chars? Fill with center "LL" as only A-R allowed
2024-10-10 19:24:59 +02:00
// Regex pattern to match a single valid Maidenhead grid square (with optional extensions)
2024-11-06 21:20:30 +01:00
$singleGridPattern = '[A-R]{2}[0-9]{2}([A-X]{2})?([0-9]{2})?([A-X]{2})?' ;
2024-10-10 19:24:59 +02:00
// Regex to match VUCC grids, allowing multiple grids separated by commas
$compoundPattern = '/^(' . $singleGridPattern . ')(,' . $singleGridPattern . ')*$/i' ;
// Check if the overall format is valid
if ( preg_match ( $compoundPattern , $grid ) !== 1 ) {
return false ;
}
// Split the string by commas to count the number of grid squares
$gridArray = explode ( ',' , $grid );
$gridCount = count ( $gridArray );
// Validate if the count is 1, 2, or 4
if ( $gridCount === 1 || $gridCount === 2 || $gridCount === 4 ) {
return true ;
}
// Return false if it's not exactly 1, 2, or 4 grids
return false ;
}
2023-08-18 20:02:47 +02:00
public function calculate ( $qso , $locator1 , $locator2 , $measurement_base , $var_dist , $custom_date_format ) {
2024-07-15 05:59:47 +02:00
if ( ! $this -> load -> is_loaded ( 'Qra' )) {
$this -> load -> library ( 'Qra' );
}
2025-01-12 15:27:07 +01:00
2024-02-23 12:17:08 +01:00
$this -> load -> model ( 'logbook_model' );
2023-08-18 20:02:47 +02:00
$data [ 'callsign' ] = $qso [ 'COL_CALL' ];
$data [ 'band' ] = $qso [ 'COL_BAND' ];
$data [ 'mode' ] = $qso [ 'COL_MODE' ];
$data [ 'gridsquare' ] = $locator2 ;
$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' ];
2026-02-07 04:29:26 +00:00
$data [ 'orbit' ] = $qso [ 'orbit' ] ? ? null ;
2024-02-23 12:17:08 +01:00
$data [ 'confirmed' ] = ( $this -> logbook_model -> qso_is_confirmed ( $qso ) == true ) ? true : false ;
2025-01-12 15:27:07 +01:00
$data [ 'dxccFlag' ] = $this -> dxccflag -> get ( $qso [ 'COL_DXCC' ]);
$data [ 'id' ] = $qso [ 'COL_PRIMARY_KEY' ];
2024-03-04 09:42:13 +01:00
2026-07-15 21:24:09 +02:00
$latlng2 = $this -> qra -> qra2latlong ( $locator2 );
$latlng2 [ 0 ] = number_format (( float ) $latlng2 [ 0 ], 3 , '.' , '' );;
$latlng2 [ 1 ] = number_format (( float ) $latlng2 [ 1 ], 3 , '.' , '' );;
$data [ 'latlng2' ] = $latlng2 ;
if ( ! empty ( $locator1 )) {
$data [ 'distance' ] = $this -> qra -> distance ( $locator1 , $locator2 , $measurement_base , $qso [ 'COL_ANT_PATH' ]) . $var_dist ;
$data [ 'bearing' ] = $this -> qra -> get_bearing ( $locator1 , $locator2 , $qso [ 'COL_ANT_PATH' ]) . " º " ;
$latlng1 = $this -> qra -> qra2latlong ( $locator1 );
$latlng1 [ 0 ] = number_format (( float ) $latlng1 [ 0 ], 3 , '.' , '' );;
$latlng1 [ 1 ] = number_format (( float ) $latlng1 [ 1 ], 3 , '.' , '' );;
$data [ 'latlng1' ] = $latlng1 ;
$data [ 'mygridsquare' ] = $locator1 ;
}
2023-08-18 20:02:47 +02:00
return $data ;
}
public function calculateCoordinates ( $qso , $lat , $long , $mygrid , $measurement_base , $var_dist , $custom_date_format ) {
2024-07-15 05:59:47 +02:00
if ( ! $this -> load -> is_loaded ( 'Qra' )) {
$this -> load -> library ( 'Qra' );
}
2025-01-12 15:27:07 +01:00
2024-02-23 12:17:08 +01:00
$this -> load -> model ( 'logbook_model' );
2024-03-04 09:42:13 +01:00
2026-08-11 17:54:08 +02:00
if ( ! empty ( $mygrid )) {
$latlng1 = $this -> qra -> qra2latlong ( $mygrid );
$latlng1 [ 0 ] = number_format (( float ) $latlng1 [ 0 ], 3 , '.' , '' );;
$latlng1 [ 1 ] = number_format (( float ) $latlng1 [ 1 ], 3 , '.' , '' );;
$data [ 'latlng1' ] = $latlng1 ;
}
2023-08-18 20:02:47 +02:00
$latlng2 [ 0 ] = $lat ;
$latlng2 [ 1 ] = $long ;
$latlng2 [ 0 ] = number_format (( float ) $latlng2 [ 0 ], 3 , '.' , '' );;
$latlng2 [ 1 ] = number_format (( float ) $latlng2 [ 1 ], 3 , '.' , '' );;
$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' ];
2026-02-07 04:29:26 +00:00
$data [ 'orbit' ] = $qso [ 'orbit' ] ? ? null ;
2024-02-23 12:17:08 +01:00
$data [ 'confirmed' ] = ( $this -> logbook_model -> qso_is_confirmed ( $qso ) == true ) ? true : false ;
2025-01-12 15:27:07 +01:00
$data [ 'dxccFlag' ] = $this -> dxccflag -> get ( $qso [ 'COL_DXCC' ]);
$data [ 'id' ] = $qso [ 'COL_PRIMARY_KEY' ];
2023-08-18 20:02:47 +02:00
return $data ;
}
2023-08-30 08:54:06 +02:00
public function userOptions () {
2025-01-02 10:22:23 +01:00
if ( ! clubaccess_check ( 9 )) return ;
2023-08-30 08:54:06 +02:00
$this -> load -> model ( 'user_options_model' );
$userOptions = $this -> user_options_model -> get_options ( 'LogbookAdvanced' ) -> result ();
2023-08-30 12:53:49 +02:00
if ( isset ( $userOptions [ 0 ])) {
$data [ 'options' ] = $options = json_decode ( $userOptions [ 0 ] -> option_value );
} else {
$data [ 'options' ] = null ;
}
2024-02-15 12:08:56 +01:00
$mapoptions [ 'gridsquare_layer' ] = $this -> user_options_model -> get_options ( 'LogbookAdvancedMap' , array ( 'option_name' => 'gridsquare_layer' , 'option_key' => 'boolean' )) -> row ();
$mapoptions [ 'path_lines' ] = $this -> user_options_model -> get_options ( 'LogbookAdvancedMap' , array ( 'option_name' => 'path_lines' , 'option_key' => 'boolean' )) -> row ();
$mapoptions [ 'cqzones_layer' ] = $this -> user_options_model -> get_options ( 'LogbookAdvancedMap' , array ( 'option_name' => 'cqzones_layer' , 'option_key' => 'boolean' )) -> row ();
$mapoptions [ 'ituzones_layer' ] = $this -> user_options_model -> get_options ( 'LogbookAdvancedMap' , array ( 'option_name' => 'ituzones_layer' , 'option_key' => 'boolean' )) -> row ();
$mapoptions [ 'nightshadow_layer' ] = $this -> user_options_model -> get_options ( 'LogbookAdvancedMap' , array ( 'option_name' => 'nightshadow_layer' , 'option_key' => 'boolean' )) -> row ();
$data [ 'mapoptions' ] = $mapoptions ;
2023-08-30 12:53:49 +02:00
$this -> load -> view ( 'logbookadvanced/useroptions' , $data );
2023-08-30 08:54:06 +02:00
}
public function setUserOptions () {
2025-01-02 10:22:23 +01:00
if ( ! clubaccess_check ( 9 )) return ;
2025-05-23 07:32:50 +00:00
$json_string [ 'datetime' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'datetime' ), 'true' );
$json_string [ 'de' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'de' ), 'true' );
$json_string [ 'dx' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'dx' ), 'true' );
$json_string [ 'mode' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'mode' ), 'true' );
$json_string [ 'rstr' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'rstr' ));
$json_string [ 'rsts' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'rsts' ));
$json_string [ 'band' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'band' ));
$json_string [ 'myrefs' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'myrefs' ));
$json_string [ 'name' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'name' ));
$json_string [ 'qslvia' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'qslvia' ));
$json_string [ 'qsl' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'qsl' ));
$json_string [ 'lotw' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'lotw' ));
$json_string [ 'eqsl' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'eqsl' ));
$json_string [ 'clublog' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'clublog' ));
$json_string [ 'qslmsgs' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'qslmsgs' ));
$json_string [ 'qslmsgr' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'qslmsgr' ));
$json_string [ 'dxcc' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'dxcc' ));
$json_string [ 'state' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'state' ));
2025-06-07 07:20:53 +02:00
$json_string [ 'county' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'county' ));
2025-05-23 07:32:50 +00:00
$json_string [ 'cqzone' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'cqzone' ));
$json_string [ 'ituzone' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'ituzone' ));
$json_string [ 'iota' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'iota' ));
$json_string [ 'pota' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'pota' ));
$json_string [ 'operator' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'operator' ));
$json_string [ 'comment' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'comment' ));
$json_string [ 'propagation' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'propagation' ));
$json_string [ 'contest' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'contest' ));
$json_string [ 'gridsquare' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'gridsquare' ));
$json_string [ 'sota' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'sota' ));
$json_string [ 'dok' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'dok' ));
$json_string [ 'sig' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'sig' ));
2026-04-20 03:50:27 +00:00
$json_string [ 'sig_info' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'sig_info' ));
2025-05-23 07:32:50 +00:00
$json_string [ 'wwff' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'wwff' ));
$json_string [ 'continent' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'continent' ));
$json_string [ 'qrz' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'qrz' ));
$json_string [ 'profilename' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'profilename' ));
$json_string [ 'stationpower' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'stationpower' ));
$json_string [ 'distance' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'distance' ));
$json_string [ 'antennaazimuth' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'antennaazimuth' ));
$json_string [ 'antennaelevation' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'antennaelevation' ));
$json_string [ 'region' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'region' ));
2025-06-14 08:07:27 +02:00
$json_string [ 'qth' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'qth' ));
2025-07-01 18:36:11 +02:00
$json_string [ 'frequency' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'frequency' ));
2025-08-21 14:02:10 +02:00
$json_string [ 'dcl' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'dcl' ));
2026-01-02 12:19:41 +01:00
$json_string [ 'last_modification' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'last_modification' ));
2026-02-21 22:29:08 +01:00
$json_string [ 'duration' ][ 'show' ] = $this -> def_boolean ( $this -> input -> post ( 'duration' ));
2023-08-30 08:54:06 +02:00
$obj [ 'column_settings' ] = json_encode ( $json_string );
$this -> load -> model ( 'user_options_model' );
$this -> user_options_model -> set_option ( 'LogbookAdvanced' , 'LogbookAdvanced' , $obj );
2024-02-15 12:08:56 +01:00
2025-05-23 06:45:00 +00:00
$this -> user_options_model -> set_option ( 'LogbookAdvancedMap' , 'gridsquare_layer' , array ( 'boolean' => $this -> def_boolean ( xss_clean ( $this -> input -> post ( 'gridsquare_layer' )))));
$this -> user_options_model -> set_option ( 'LogbookAdvancedMap' , 'path_lines' , array ( 'boolean' => $this -> def_boolean ( xss_clean ( $this -> input -> post ( 'path_lines' )))));
$this -> user_options_model -> set_option ( 'LogbookAdvancedMap' , 'cqzones_layer' , array ( 'boolean' => $this -> def_boolean ( xss_clean ( $this -> input -> post ( 'cqzone_layer' )))));
$this -> user_options_model -> set_option ( 'LogbookAdvancedMap' , 'ituzones_layer' , array ( 'boolean' => $this -> def_boolean ( xss_clean ( $this -> input -> post ( 'ituzone_layer' )))));
$this -> user_options_model -> set_option ( 'LogbookAdvancedMap' , 'nightshadow_layer' , array ( 'boolean' => $this -> def_boolean ( xss_clean ( $this -> input -> post ( 'nightshadow_layer' )))));
}
private function def_boolean ( $value , $default_value = 'false' ) {
if ((( $value ? ? '' ) == '' ) || (( $value != 'false' ) && ( $value != 'true' ))) {
$value = $default_value ;
}
return $value ;
2023-08-30 08:54:06 +02:00
}
2024-02-16 13:52:20 +01:00
public function editDialog () {
2026-06-23 04:38:58 +00:00
if ( ! clubaccess_check ( 3 )) return ;
2025-01-02 10:22:23 +01:00
2024-02-19 19:05:09 +01:00
$this -> load -> model ( 'bands' );
$this -> load -> model ( 'modes' );
2024-02-20 15:24:49 +01:00
$this -> load -> model ( 'logbookadvanced_model' );
New Wavelog Contesting and Basics for Wavelog Worker (#3063)
* initial commit for new contesting in Wavelog
* implemented cache buster to match logic from upstream dev branch
* refactore data-store to idb since this will be much faster with a lot of QSOs (scale for the future)
* implementation of other exchange types (wip)
* updated migration version
* renamed mig
* renamed mig
* updated mig
* ESC Handler to reset form
* Add Websocket
* stretch maxDuration warning
We can stretch the maxDuration warning to 2 seconds to allow for more network latency and processing time. The heartbeat is protected against multiple parallel requests, so we can afford to be more lenient with the duration before showing a warning. This should help reduce false positives in environments with higher latency or slower processing.
* worked before warning in qso form
While input the logic checks in the qso list if the callisgn already exists on the same band and mode.
* translations
* fix band buttons
* updated migration after release 2.4.2
* Fixing create new contest, add clubstation permission check, add time check to contests
* Adding attach QSO to Contest
* Remove redundant clubstation checks
* Fix function tip
* Remove time check when launch contest
* Fixing contest attach main logbook, adding detach contest qso
* Enable clubstation contest QSO detach attach
* add space handler for callsign input
* set rst default to 599 for cw, 59 for others
* add grid and refactor some ui to make a better fitting here and there
* adjust tabindex
* add "copy exchange to" feature
* fix css for all themes
* adif and cbr export
* fix bug with wrong operator callsign
* add exchange type "exchange+grid"
* introduce new logic for exchangetypes and more flexible order selection
* fix broken qso list scroll
* legacy import feature
* more precise wording
* feat: inline editing of QSOs by double click in the QSO list
* redirect cabrillo to contesting manager
* Fix QSO permission check
* remove unused cabrillo stuff
* remove duplicate function
* fix check if worked before on band change
tnx to @int2001
* fix flash message for legacy importer
* make dropdown searchable and place "other" at the top
* add hint about "Other" contest
* avoid "flash" of winkeyer settings in qso logging, it shows up if cw is set as mode
* winkeyer for the new contesting
need proper testing by @AndreasK79 and @phl0 since I don't have a winkeyer myself. I tested with a python simulator...
* english comments
* proper singular/plural
* fix dropdown
* preselect active station location
* allow editing time aswell
* fix fontsize in radio buttons
* remove redundant qso count query
* cache last updated value for contest qsos to reduce db load
* index on user id
* cache also qso count
* you can now resize windows also on the edges
requested by @xyz667 in https://github.com/wavelog/wavelog/pull/3063#issuecomment-4557850867
* fix oversized clock
* click to prepare logging for contesting
Logic:
- if qso windows is open, call is sent to qso form
- if contest log is open, call is sent to contest log
- if both are open, call is sent to contest log
- if none is open, click opens qso form and call is sent to qso form
* handle exchange s prefill with data from the last qso and make exchange always uppercase
* add dropdown to qso list with option to delete qsos
* language fixes
* english comments
* center text
* fix missing dropdown on new qsos
* add date presets for contest session creator/editor
* basic worker implementation
* support multiple workers for clustering
* remove unnecessary node column
* simple availability check
* websocket for contesting
* bonus: add vip for visibilty in debug view
* use vip if available
* worker disabled in debug view if disabled in config
* racecondition for winkeyer breaks edit/delete dropdown
* racecondition for winkeyer breaks edit/delete dropdown
* qso handling for worker in contesting, no high interval heartbeat anymore
* clear heartbeat intervall
* fix some timing bugs
* remove dedicated worker controller as it's not needed
* handle whitespace
* trigger sync engine after processing QSO sync response and adjust last sync time to avoid spurious resyncs
* fix set and setLocal
* fix change detection and sync logic
* fix the lost of seconds due to edit
* fix table rendering
* watermark handling for true delta
* remove caching as it brings more problems here as benefits
* make serial as default exchangetype
* Add clarification on cluster setup requirements for worker URLs
* add operator to qso list if this is a clubstation
* fix bug for editing qsos in clubmode
* remove redundant code
* integers must be null in database
* fix bug in tabindex if 3 exchangefields are configured (serial, exchange, grid)
* nice contesting map (draft)
* map autofit
* add grid overlay
* calculate distanz and azimuth
* include rotor control via waveloggate (ws only)
* implement simple dedicated callbook lookup
* simpler and faster lookup
* option in contest session to disabled callbook lookup and only calculate dxcc
* syntax issue
* fix bug in CBR export
* catch empty result on contest
* remove some leftovers
* removed some comments
* remove unused stuff
* removed old todos/comments
* add 4s timeout for ajax transport
* you need to be admin for this
* translations
* add option to delete qso's aswell when deleting a session (opt in)
* add quickstart button in manager
* removed old todo
* fix "grows to bottom"
* disable "copy exchange to" if no exchange is set
* clear map on qso clear aswell
* same for scp
* updated documentation link
* calculate distanze and azimut also on grid only
* better space usage in qso input
* callbook db first approach, online lookup can be disabled while being cached for all users when enabled
* some input validation
* use only one sot for qrgtoband
* basic stats component
* fix html encoding
* render all aswell
* ascii
* store locally which time frame the user wants
* sync settings and warn user if something happend on the backend
* dev leftover
* show errors if callbook fails or callsign is invalid
* easier syntax
* Revert "easier syntax" - that was a mistake
This reverts commit 80c75dbf1e6c832f8d0616ea56b8b55d96c36418.
* fix for callbook lookup
* make pathline more visible
* better visibility of qsos
* add classic coordinates bar to the map
* fix bug in stats
* stretch max duration to 4s.. just in case
* simple sanity check in js to prevent unnecessary callbook lookups
* simulate tab after filling the call from scp
* fix poll radios with enabled worker
* reset po/mo files back to upstream/dev
* split contest exports, add back reg1test edi format
* keep the menu item but redirect to contesting
* better syntax and bugfix
* break it down further and fix typo ("constraint")
* use monospace font for input fields
* fix: in worker driven mode we need to do the heartbeat also on not focused windows otherwise we loose this contact
* fix: error handling on invalid times
* wavelog Ø
* more styling
* band lowercase fix
* Other is not a very descriptive title for a contest logger window, so we rename it to "Contest"
* custom contest name
* compare the whole array instead just a few settings
---------
Co-authored-by: int2001 <joerg@dj7nt.de>
Co-authored-by: HadleySo <71105018+HadleySo@users.noreply.github.com>
Co-authored-by: DB4SCW <dev@db4scw.de>
2026-06-14 14:23:00 +02:00
$this -> load -> model ( 'contest_admin_model' );
2024-02-20 15:24:49 +01:00
$data [ 'stateDxcc' ] = $this -> logbookadvanced_model -> getPrimarySubdivisonsDxccs ();
2024-02-19 19:05:09 +01:00
2026-02-15 11:01:03 +01:00
$data [ 'modes' ] = $this -> modes -> all ();
2024-02-19 19:05:09 +01:00
$data [ 'bands' ] = $this -> bands -> get_user_bands_for_qso_entry ();
New Wavelog Contesting and Basics for Wavelog Worker (#3063)
* initial commit for new contesting in Wavelog
* implemented cache buster to match logic from upstream dev branch
* refactore data-store to idb since this will be much faster with a lot of QSOs (scale for the future)
* implementation of other exchange types (wip)
* updated migration version
* renamed mig
* renamed mig
* updated mig
* ESC Handler to reset form
* Add Websocket
* stretch maxDuration warning
We can stretch the maxDuration warning to 2 seconds to allow for more network latency and processing time. The heartbeat is protected against multiple parallel requests, so we can afford to be more lenient with the duration before showing a warning. This should help reduce false positives in environments with higher latency or slower processing.
* worked before warning in qso form
While input the logic checks in the qso list if the callisgn already exists on the same band and mode.
* translations
* fix band buttons
* updated migration after release 2.4.2
* Fixing create new contest, add clubstation permission check, add time check to contests
* Adding attach QSO to Contest
* Remove redundant clubstation checks
* Fix function tip
* Remove time check when launch contest
* Fixing contest attach main logbook, adding detach contest qso
* Enable clubstation contest QSO detach attach
* add space handler for callsign input
* set rst default to 599 for cw, 59 for others
* add grid and refactor some ui to make a better fitting here and there
* adjust tabindex
* add "copy exchange to" feature
* fix css for all themes
* adif and cbr export
* fix bug with wrong operator callsign
* add exchange type "exchange+grid"
* introduce new logic for exchangetypes and more flexible order selection
* fix broken qso list scroll
* legacy import feature
* more precise wording
* feat: inline editing of QSOs by double click in the QSO list
* redirect cabrillo to contesting manager
* Fix QSO permission check
* remove unused cabrillo stuff
* remove duplicate function
* fix check if worked before on band change
tnx to @int2001
* fix flash message for legacy importer
* make dropdown searchable and place "other" at the top
* add hint about "Other" contest
* avoid "flash" of winkeyer settings in qso logging, it shows up if cw is set as mode
* winkeyer for the new contesting
need proper testing by @AndreasK79 and @phl0 since I don't have a winkeyer myself. I tested with a python simulator...
* english comments
* proper singular/plural
* fix dropdown
* preselect active station location
* allow editing time aswell
* fix fontsize in radio buttons
* remove redundant qso count query
* cache last updated value for contest qsos to reduce db load
* index on user id
* cache also qso count
* you can now resize windows also on the edges
requested by @xyz667 in https://github.com/wavelog/wavelog/pull/3063#issuecomment-4557850867
* fix oversized clock
* click to prepare logging for contesting
Logic:
- if qso windows is open, call is sent to qso form
- if contest log is open, call is sent to contest log
- if both are open, call is sent to contest log
- if none is open, click opens qso form and call is sent to qso form
* handle exchange s prefill with data from the last qso and make exchange always uppercase
* add dropdown to qso list with option to delete qsos
* language fixes
* english comments
* center text
* fix missing dropdown on new qsos
* add date presets for contest session creator/editor
* basic worker implementation
* support multiple workers for clustering
* remove unnecessary node column
* simple availability check
* websocket for contesting
* bonus: add vip for visibilty in debug view
* use vip if available
* worker disabled in debug view if disabled in config
* racecondition for winkeyer breaks edit/delete dropdown
* racecondition for winkeyer breaks edit/delete dropdown
* qso handling for worker in contesting, no high interval heartbeat anymore
* clear heartbeat intervall
* fix some timing bugs
* remove dedicated worker controller as it's not needed
* handle whitespace
* trigger sync engine after processing QSO sync response and adjust last sync time to avoid spurious resyncs
* fix set and setLocal
* fix change detection and sync logic
* fix the lost of seconds due to edit
* fix table rendering
* watermark handling for true delta
* remove caching as it brings more problems here as benefits
* make serial as default exchangetype
* Add clarification on cluster setup requirements for worker URLs
* add operator to qso list if this is a clubstation
* fix bug for editing qsos in clubmode
* remove redundant code
* integers must be null in database
* fix bug in tabindex if 3 exchangefields are configured (serial, exchange, grid)
* nice contesting map (draft)
* map autofit
* add grid overlay
* calculate distanz and azimuth
* include rotor control via waveloggate (ws only)
* implement simple dedicated callbook lookup
* simpler and faster lookup
* option in contest session to disabled callbook lookup and only calculate dxcc
* syntax issue
* fix bug in CBR export
* catch empty result on contest
* remove some leftovers
* removed some comments
* remove unused stuff
* removed old todos/comments
* add 4s timeout for ajax transport
* you need to be admin for this
* translations
* add option to delete qso's aswell when deleting a session (opt in)
* add quickstart button in manager
* removed old todo
* fix "grows to bottom"
* disable "copy exchange to" if no exchange is set
* clear map on qso clear aswell
* same for scp
* updated documentation link
* calculate distanze and azimut also on grid only
* better space usage in qso input
* callbook db first approach, online lookup can be disabled while being cached for all users when enabled
* some input validation
* use only one sot for qrgtoband
* basic stats component
* fix html encoding
* render all aswell
* ascii
* store locally which time frame the user wants
* sync settings and warn user if something happend on the backend
* dev leftover
* show errors if callbook fails or callsign is invalid
* easier syntax
* Revert "easier syntax" - that was a mistake
This reverts commit 80c75dbf1e6c832f8d0616ea56b8b55d96c36418.
* fix for callbook lookup
* make pathline more visible
* better visibility of qsos
* add classic coordinates bar to the map
* fix bug in stats
* stretch max duration to 4s.. just in case
* simple sanity check in js to prevent unnecessary callbook lookups
* simulate tab after filling the call from scp
* fix poll radios with enabled worker
* reset po/mo files back to upstream/dev
* split contest exports, add back reg1test edi format
* keep the menu item but redirect to contesting
* better syntax and bugfix
* break it down further and fix typo ("constraint")
* use monospace font for input fields
* fix: in worker driven mode we need to do the heartbeat also on not focused windows otherwise we loose this contact
* fix: error handling on invalid times
* wavelog Ø
* more styling
* band lowercase fix
* Other is not a very descriptive title for a contest logger window, so we rename it to "Contest"
* custom contest name
* compare the whole array instead just a few settings
---------
Co-authored-by: int2001 <joerg@dj7nt.de>
Co-authored-by: HadleySo <71105018+HadleySo@users.noreply.github.com>
Co-authored-by: DB4SCW <dev@db4scw.de>
2026-06-14 14:23:00 +02:00
$data [ 'contests' ] = $this -> contest_admin_model -> getActiveContests ();
2024-02-19 19:05:09 +01:00
$this -> load -> view ( 'logbookadvanced/edit' , $data );
2024-02-16 13:52:20 +01:00
}
public function saveBatchEditQsos () {
2026-06-23 04:38:58 +00:00
if ( ! clubaccess_check ( 3 )) return ;
2025-01-02 10:22:23 +01:00
2024-02-16 13:52:20 +01:00
$ids = xss_clean ( $this -> input -> post ( 'ids' ));
$column = xss_clean ( $this -> input -> post ( 'column' ));
$value = xss_clean ( $this -> input -> post ( 'value' ));
2024-02-19 19:05:09 +01:00
$value2 = xss_clean ( $this -> input -> post ( 'value2' ));
2025-01-14 09:22:08 +01:00
$value3 = xss_clean ( $this -> input -> post ( 'value3' ));
$value4 = xss_clean ( $this -> input -> post ( 'value4' ));
2024-02-16 13:52:20 +01:00
2026-06-23 04:38:58 +00:00
// Club Member may only edit QSOs he made himself; officers and normal users are unaffected
$ids_array = clubaccess_filter_qso_ids ( json_decode ( $ids , true ) ? ? []);
if ( empty ( $ids_array )) {
header ( " Content-Type: application/json " );
print json_encode ([]);
return ;
}
$ids = json_encode ( $ids_array );
2024-02-16 13:52:20 +01:00
$this -> load -> model ( 'logbookadvanced_model' );
2025-01-14 09:22:08 +01:00
$this -> logbookadvanced_model -> saveEditedQsos ( $ids , $column , $value , $value2 , $value3 , $value4 );
2024-02-18 14:55:34 +01:00
$data = $this -> logbookadvanced_model -> getQsosForAdif ( $ids , $this -> session -> userdata ( 'user_id' ));
$results = $data -> result ( 'array' );
2025-06-23 19:22:38 +00:00
$qsos = [];
foreach ( $results as $data ) {
$qsos [] = new QSO ( $data );
}
2024-02-18 14:55:34 +01:00
$q = [];
2024-11-04 12:42:09 +01:00
// Get Date format
if ( $this -> session -> userdata ( 'user_date_format' )) {
// If Logged in and session exists
$custom_date_format = $this -> session -> userdata ( 'user_date_format' );
} else {
// Get Default date format from /config/wavelog.php
$custom_date_format = $this -> config -> item ( 'qso_date_format' );
}
2024-02-18 14:55:34 +01:00
foreach ( $qsos as $qso ) {
2025-06-23 19:22:38 +00:00
$singleQso = $qso -> toArray ();
$flag = $this -> dxccflag -> get ( $qso -> getDXCCId ());
if ( $flag != null ) {
$singleQso [ 'flag' ] = ' ' . $flag ;
} else {
$singleQso [ 'flag' ] = '' ;
}
$q [] = $singleQso ;
2024-02-18 14:55:34 +01:00
}
header ( " Content-Type: application/json " );
print json_encode ( $q );
2024-02-16 13:52:20 +01:00
}
2024-02-18 20:19:45 +01:00
public function batchDeleteQsos () {
2026-06-23 04:38:58 +00:00
if ( ! clubaccess_check ( 3 )) return ;
2025-01-02 10:22:23 +01:00
2024-02-18 20:19:45 +01:00
$ids = xss_clean ( $this -> input -> post ( 'ids' ));
2026-06-23 04:38:58 +00:00
$requested_ids = json_decode ( $ids , true ) ? ? [];
// Club Member (3/6) may only delete QSOs he made himself; officers and normal users are unaffected
$ids_array = clubaccess_filter_qso_ids ( $requested_ids );
if ( ! empty ( $ids_array )) {
$this -> load -> model ( 'logbookadvanced_model' );
$this -> logbookadvanced_model -> deleteQsos ( json_encode ( $ids_array ));
}
header ( " Content-Type: application/json " );
print json_encode ([
'deleted' => array_values ( $ids_array ),
'requested' => count ( $requested_ids ),
]);
2024-02-18 20:19:45 +01:00
}
2024-02-20 15:24:49 +01:00
public function getSubdivisionsForDxcc () {
$dxcc = xss_clean ( $this -> input -> post ( 'dxcc' ));
$this -> load -> model ( 'logbookadvanced_model' );
$result = $this -> logbookadvanced_model -> getSubdivisons ( $dxcc );
header ( " Content-Type: application/json " );
print json_encode ( $result );
}
2025-04-26 11:00:09 +02:00
public function helpDialog () {
$this -> load -> view ( 'logbookadvanced/help' );
}
2025-06-16 11:58:43 +02:00
2025-11-16 19:33:45 +01:00
public function stateDialog () {
2025-11-21 15:20:22 +01:00
$this -> load -> library ( 'Geojson' );
// Get supported countries from Geojson library
$supported_states = $this -> geojson :: SUPPORTED_STATES ;
$country_names = array ();
foreach ( $supported_states as $dxcc => $info ) {
if ( $info [ 'enabled' ]) {
$country_names [] = $info [ 'name' ];
}
}
sort ( $country_names );
$data [ 'supported_countries' ] = implode ( ', ' , $country_names );
$this -> load -> view ( 'logbookadvanced/statedialog' , $data );
2025-11-16 19:33:45 +01:00
}
2025-11-08 08:59:45 +01:00
public function distanceDialog () {
$this -> load -> view ( 'logbookadvanced/distancedialog' );
}
2026-03-21 08:17:35 +01:00
public function mergeDialog () {
if ( ! clubaccess_check ( 9 )) return ;
2026-03-22 18:06:29 +01:00
$qsoIds = $this -> input -> post ( 'qsoIds' , true );
2026-03-21 08:17:35 +01:00
if ( ! is_array ( $qsoIds ) || count ( $qsoIds ) !== 2 ) {
show_error ( 'Invalid QSO IDs' );
}
$this -> load -> model ( 'logbookadvanced_model' );
// Get both QSOs
$qso1 = $this -> logbookadvanced_model -> getQsoForMerge ( $qsoIds [ 0 ]);
$qso2 = $this -> logbookadvanced_model -> getQsoForMerge ( $qsoIds [ 1 ]);
if ( ! $qso1 || ! $qso2 ) {
show_error ( 'QSO not found' );
}
$data [ 'qso1' ] = $qso1 ;
$data [ 'qso2' ] = $qso2 ;
$data [ 'qsoIds' ] = $qsoIds ;
$this -> load -> view ( 'logbookadvanced/mergedialog' , $data );
}
public function mergeQsos () {
if ( ! clubaccess_check ( 9 )) return ;
2026-03-22 18:14:08 +01:00
$qsoIds = $this -> input -> post ( 'qsoIds' , true );
$mergeData = $this -> input -> post ( 'mergeData' , true );
2026-03-21 08:17:35 +01:00
if ( ! is_array ( $qsoIds ) || count ( $qsoIds ) !== 2 ) {
header ( " Content-Type: application/json " );
echo json_encode ([ 'success' => false , 'message' => 'Invalid QSO IDs' ]);
return ;
}
$this -> load -> model ( 'logbookadvanced_model' );
$result = $this -> logbookadvanced_model -> mergeQsos ( $qsoIds [ 0 ], $qsoIds [ 1 ], $mergeData );
header ( " Content-Type: application/json " );
echo json_encode ( $result );
}
2025-06-16 11:58:43 +02:00
public function fixCqZones () {
if ( ! clubaccess_check ( 9 )) return ;
$ids = xss_clean ( $this -> input -> post ( 'ids' ));
$this -> load -> model ( 'logbookadvanced_model' );
2025-12-31 16:29:43 +01:00
$result = $this -> logbookadvanced_model -> fixCqZones ( $ids );
2025-06-16 11:58:43 +02:00
header ( " Content-Type: application/json " );
2025-12-31 16:29:43 +01:00
print json_encode ( $result );
2025-06-16 11:58:43 +02:00
}
public function fixItuZones () {
if ( ! clubaccess_check ( 9 )) return ;
$ids = xss_clean ( $this -> input -> post ( 'ids' ));
$this -> load -> model ( 'logbookadvanced_model' );
2025-12-31 16:29:43 +01:00
$result = $this -> logbookadvanced_model -> fixItuZones ( $ids );
2025-06-16 11:58:43 +02:00
header ( " Content-Type: application/json " );
2025-12-31 16:29:43 +01:00
print json_encode ( $result );
2025-06-16 11:58:43 +02:00
}
2025-11-07 09:28:57 +01:00
public function fixContinent () {
$this -> load -> model ( 'logbookadvanced_model' );
2026-02-08 18:32:38 +01:00
$stationid = $this -> input -> post ( 'stationid' , true );
$result = $this -> logbookadvanced_model -> check_missing_continent ( $stationid );
2025-11-08 08:59:45 +01:00
2025-12-15 19:36:56 +01:00
$data [ 'result' ] = $result ;
$data [ 'type' ] = 'continent' ;
$this -> load -> view ( 'logbookadvanced/showUpdateResult' , $data );
2025-11-08 08:59:45 +01:00
}
2025-11-16 19:33:45 +01:00
public function fixStateProgress () {
if ( ! clubaccess_check ( 9 )) return ;
$this -> load -> model ( 'logbook_model' );
$this -> load -> model ( 'logbookadvanced_model' );
$qsoID = xss_clean ( $this -> input -> post ( 'qsoID' ));
// Process single QSO state fix
$result = $this -> logbookadvanced_model -> fixStateSingle ( $qsoID );
// Get updated QSO data if successful
if ( $result [ 'success' ]) {
$qsoID_array = [ $qsoID ];
$qso = $this -> logbookadvanced_model -> getQsosForAdif ( json_encode ( $qsoID_array ), $this -> session -> userdata ( 'user_id' )) -> row_array ();
if ( $qso !== null ) {
$qsoObj = new QSO ( $qso );
$cleaned_qso = $qsoObj -> toArray ();
$flag = $this -> dxccflag -> get ( $qsoObj -> getDXCCId ());
if ( $flag != null ) {
$cleaned_qso [ 'flag' ] = ' ' . $flag ;
} else {
$cleaned_qso [ 'flag' ] = '' ;
}
$result [ 'qso' ] = $cleaned_qso ;
}
}
header ( " Content-Type: application/json " );
echo json_encode ( $result );
}
2025-11-08 08:59:45 +01:00
public function updateDistances () {
2025-12-17 16:31:32 +01:00
if ( ! clubaccess_check ( 9 )) return ;
2026-02-08 18:32:38 +01:00
$stationid = $this -> input -> post ( 'stationid' , true );
2025-11-08 08:59:45 +01:00
$this -> load -> model ( 'logbookadvanced_model' );
2026-02-08 18:32:38 +01:00
$result = $this -> logbookadvanced_model -> update_distances_batch ( $stationid );
2025-11-08 08:59:45 +01:00
2025-12-15 23:36:46 +01:00
$data [ 'result' ] = $result ;
$data [ 'type' ] = 'distance' ;
$this -> load -> view ( 'logbookadvanced/showUpdateResult' , $data );
2025-11-07 09:28:57 +01:00
}
2025-11-28 19:22:30 +01:00
public function callbookDialog () {
$this -> load -> view ( 'logbookadvanced/callbookdialog' );
}
2025-12-02 07:59:17 +01:00
public function dbtoolsDialog () {
2026-02-08 18:32:38 +01:00
$this -> load -> model ( 'stations' );
$data [ 'station_profile' ] = $this -> stations -> all_of_user ();
$this -> load -> view ( 'logbookadvanced/dbtoolsdialog' , $data );
2025-12-02 07:59:17 +01:00
}
public function checkDb () {
if ( ! clubaccess_check ( 9 )) return ;
$type = $this -> input -> post ( 'type' , true );
2026-02-08 18:32:38 +01:00
$stationid = $this -> input -> post ( 'stationid' , true );
2025-12-02 07:59:17 +01:00
$this -> load -> model ( 'logbookadvanced_model' );
2025-12-07 15:55:52 +01:00
2026-02-08 18:32:38 +01:00
$data [ 'result' ] = $this -> logbookadvanced_model -> runCheckDb ( $type , $stationid );
2025-12-07 15:55:52 +01:00
if ( $type == 'checkstate' ) {
2025-12-08 16:23:53 +01:00
$this -> load -> view ( 'logbookadvanced/statecheckresult' , $data );
2025-12-07 15:55:52 +01:00
} else {
2025-12-08 16:23:53 +01:00
$data [ 'type' ] = $type ;
$this -> load -> view ( 'logbookadvanced/checkresult' , $data );
2025-12-07 15:55:52 +01:00
}
2025-12-02 07:59:17 +01:00
}
2025-12-07 19:52:26 +01:00
public function fixStateBatch () {
if ( ! clubaccess_check ( 9 )) return ;
$this -> load -> model ( 'logbook_model' );
$this -> load -> model ( 'logbookadvanced_model' );
$dxcc = $this -> input -> post ( 'dxcc' , true );
2026-02-08 18:32:38 +01:00
$stationid = $this -> input -> post ( 'stationid' , true );
2025-12-15 16:51:11 +01:00
$data [ 'country' ] = $this -> input -> post ( 'country' , true );
2025-12-07 19:52:26 +01:00
// Process for batch QSO state fix
2026-02-08 18:32:38 +01:00
$result = $this -> logbookadvanced_model -> fixStateBatch ( $dxcc , $stationid );
2025-12-07 19:52:26 +01:00
2025-12-15 16:51:11 +01:00
$data [ 'result' ] = $result ;
2025-12-15 08:31:04 +01:00
2025-12-15 16:51:11 +01:00
$data [ 'type' ] = 'state' ;
2025-12-14 18:43:03 +01:00
2025-12-15 16:51:11 +01:00
$this -> load -> view ( 'logbookadvanced/showUpdateResult' , $data );
2025-12-07 19:52:26 +01:00
}
2025-12-07 22:38:51 +01:00
public function openStateList () {
if ( ! clubaccess_check ( 9 )) return ;
$this -> load -> model ( 'logbookadvanced_model' );
$data [ 'dxcc' ] = $this -> input -> post ( 'dxcc' , true );
2025-12-16 13:05:23 +01:00
$data [ 'country' ] = $this -> input -> post ( 'country' , true );
2026-02-08 18:32:38 +01:00
$data [ 'stationid' ] = $this -> input -> post ( 'stationid' , true );
2025-12-07 22:38:51 +01:00
// Process for batch QSO state fix
2026-02-08 18:32:38 +01:00
$data [ 'qsos' ] = $this -> logbookadvanced_model -> getStateListQsos ( $data [ 'dxcc' ], $data [ 'stationid' ]);
2025-12-07 22:38:51 +01:00
$this -> load -> view ( 'logbookadvanced/showStateQsos' , $data );
}
2025-12-08 14:59:43 +01:00
2026-02-08 18:32:38 +01:00
public function fixMissingGrids () {
2025-12-17 16:31:32 +01:00
if ( ! clubaccess_check ( 9 )) return ;
2025-12-14 09:33:01 +01:00
$type = $this -> input -> post ( 'type' , true );
2026-02-08 18:32:38 +01:00
$stationid = $this -> input -> post ( 'stationid' , true );
2025-12-14 09:33:01 +01:00
$this -> load -> model ( 'logbookadvanced_model' );
2026-02-08 18:32:38 +01:00
$result = $this -> logbookadvanced_model -> check_missing_grid ( $stationid );
2025-12-14 09:33:01 +01:00
2025-12-16 09:16:32 +01:00
$data [ 'result' ] = $result ;
$data [ 'type' ] = $type ;
$this -> load -> view ( 'logbookadvanced/showUpdateResult' , $data );
2025-12-14 09:33:01 +01:00
}
2025-12-22 08:25:26 +01:00
function dupeSearchDialog () {
if ( ! clubaccess_check ( 9 )) return ;
$this -> load -> view ( 'logbookadvanced/dupesearchdialog' );
}
2025-12-25 18:20:05 +01:00
function fixDxccSelected () {
if ( ! clubaccess_check ( 9 )) return ;
$ids = xss_clean ( $this -> input -> post ( 'ids' ));
$this -> load -> model ( 'logbookadvanced_model' );
$result = $this -> logbookadvanced_model -> fixDxccSelected ( $ids );
$result [ 'message' ] = '<div class="alert alert-' . ( $result [ 'count' ] == 0 ? 'danger' : 'success' ) . '" role="alert">' . sprintf ( __ ( " DXCC updated for %d QSO(s). " ), $result [ 'count' ]) . '</div>' ;
header ( " Content-Type: application/json " );
print json_encode ( $result );
}
2026-01-17 20:26:14 +01:00
function showMapForIncorrectGrid () {
if ( ! clubaccess_check ( 9 )) return ;
$this -> load -> model ( 'logbookadvanced_model' );
$dxcc = $this -> input -> post ( 'dxcc' , true );
$data [ 'grids' ] = $this -> logbookadvanced_model -> getGridsForDxcc ( $dxcc );
$data [ 'dxcc' ] = $dxcc ;
$data [ 'gridsquare' ] = $this -> input -> post ( 'gridsquare' , true );
2026-01-18 10:01:37 +01:00
$dxccname = $this -> input -> post ( 'dxccname' , true );
$data [ 'title' ] = sprintf ( __ ( " Map for DXCC %s and gridsquare %s. " ), $dxccname , $data [ 'gridsquare' ]);
2026-01-17 20:26:14 +01:00
header ( " Content-Type: application/json " );
print json_encode ( $data );
}
2026-03-20 16:22:17 +01:00
function getQsos () {
if ( ! clubaccess_check ( 9 )) return ;
$qsoID [] = $this -> input -> post ( 'id' , true );
$this -> load -> model ( 'logbookadvanced_model' );
$qso = $this -> logbookadvanced_model -> getQsosForAdif ( json_encode ( $qsoID ), $this -> session -> userdata ( 'user_id' )) -> row_array ();
$qsoObj = new QSO ( $qso ); // Redirection via Object to clean/convert QSO (get rid of cols)
$cleaned_qso = $qsoObj -> toArray (); // And back to Array for the JSON
$flag = $this -> dxccflag -> get ( $qsoObj -> getDXCCId ());
if ( $flag != null ) {
$cleaned_qso [ 'flag' ] = ' ' . $flag ;
} else {
$cleaned_qso [ 'flag' ] = '' ;
}
header ( " Content-Type: application/json " );
echo json_encode ( $cleaned_qso );
}
2026-06-06 14:00:57 +02:00
private function flag_html ( $flag ) {
if ( $flag != null ) {
return ' <span class="flag-emoji">' . $flag . '</span>' ;
} else {
return '' ;
}
}
New Wavelog Contesting and Basics for Wavelog Worker (#3063)
* initial commit for new contesting in Wavelog
* implemented cache buster to match logic from upstream dev branch
* refactore data-store to idb since this will be much faster with a lot of QSOs (scale for the future)
* implementation of other exchange types (wip)
* updated migration version
* renamed mig
* renamed mig
* updated mig
* ESC Handler to reset form
* Add Websocket
* stretch maxDuration warning
We can stretch the maxDuration warning to 2 seconds to allow for more network latency and processing time. The heartbeat is protected against multiple parallel requests, so we can afford to be more lenient with the duration before showing a warning. This should help reduce false positives in environments with higher latency or slower processing.
* worked before warning in qso form
While input the logic checks in the qso list if the callisgn already exists on the same band and mode.
* translations
* fix band buttons
* updated migration after release 2.4.2
* Fixing create new contest, add clubstation permission check, add time check to contests
* Adding attach QSO to Contest
* Remove redundant clubstation checks
* Fix function tip
* Remove time check when launch contest
* Fixing contest attach main logbook, adding detach contest qso
* Enable clubstation contest QSO detach attach
* add space handler for callsign input
* set rst default to 599 for cw, 59 for others
* add grid and refactor some ui to make a better fitting here and there
* adjust tabindex
* add "copy exchange to" feature
* fix css for all themes
* adif and cbr export
* fix bug with wrong operator callsign
* add exchange type "exchange+grid"
* introduce new logic for exchangetypes and more flexible order selection
* fix broken qso list scroll
* legacy import feature
* more precise wording
* feat: inline editing of QSOs by double click in the QSO list
* redirect cabrillo to contesting manager
* Fix QSO permission check
* remove unused cabrillo stuff
* remove duplicate function
* fix check if worked before on band change
tnx to @int2001
* fix flash message for legacy importer
* make dropdown searchable and place "other" at the top
* add hint about "Other" contest
* avoid "flash" of winkeyer settings in qso logging, it shows up if cw is set as mode
* winkeyer for the new contesting
need proper testing by @AndreasK79 and @phl0 since I don't have a winkeyer myself. I tested with a python simulator...
* english comments
* proper singular/plural
* fix dropdown
* preselect active station location
* allow editing time aswell
* fix fontsize in radio buttons
* remove redundant qso count query
* cache last updated value for contest qsos to reduce db load
* index on user id
* cache also qso count
* you can now resize windows also on the edges
requested by @xyz667 in https://github.com/wavelog/wavelog/pull/3063#issuecomment-4557850867
* fix oversized clock
* click to prepare logging for contesting
Logic:
- if qso windows is open, call is sent to qso form
- if contest log is open, call is sent to contest log
- if both are open, call is sent to contest log
- if none is open, click opens qso form and call is sent to qso form
* handle exchange s prefill with data from the last qso and make exchange always uppercase
* add dropdown to qso list with option to delete qsos
* language fixes
* english comments
* center text
* fix missing dropdown on new qsos
* add date presets for contest session creator/editor
* basic worker implementation
* support multiple workers for clustering
* remove unnecessary node column
* simple availability check
* websocket for contesting
* bonus: add vip for visibilty in debug view
* use vip if available
* worker disabled in debug view if disabled in config
* racecondition for winkeyer breaks edit/delete dropdown
* racecondition for winkeyer breaks edit/delete dropdown
* qso handling for worker in contesting, no high interval heartbeat anymore
* clear heartbeat intervall
* fix some timing bugs
* remove dedicated worker controller as it's not needed
* handle whitespace
* trigger sync engine after processing QSO sync response and adjust last sync time to avoid spurious resyncs
* fix set and setLocal
* fix change detection and sync logic
* fix the lost of seconds due to edit
* fix table rendering
* watermark handling for true delta
* remove caching as it brings more problems here as benefits
* make serial as default exchangetype
* Add clarification on cluster setup requirements for worker URLs
* add operator to qso list if this is a clubstation
* fix bug for editing qsos in clubmode
* remove redundant code
* integers must be null in database
* fix bug in tabindex if 3 exchangefields are configured (serial, exchange, grid)
* nice contesting map (draft)
* map autofit
* add grid overlay
* calculate distanz and azimuth
* include rotor control via waveloggate (ws only)
* implement simple dedicated callbook lookup
* simpler and faster lookup
* option in contest session to disabled callbook lookup and only calculate dxcc
* syntax issue
* fix bug in CBR export
* catch empty result on contest
* remove some leftovers
* removed some comments
* remove unused stuff
* removed old todos/comments
* add 4s timeout for ajax transport
* you need to be admin for this
* translations
* add option to delete qso's aswell when deleting a session (opt in)
* add quickstart button in manager
* removed old todo
* fix "grows to bottom"
* disable "copy exchange to" if no exchange is set
* clear map on qso clear aswell
* same for scp
* updated documentation link
* calculate distanze and azimut also on grid only
* better space usage in qso input
* callbook db first approach, online lookup can be disabled while being cached for all users when enabled
* some input validation
* use only one sot for qrgtoband
* basic stats component
* fix html encoding
* render all aswell
* ascii
* store locally which time frame the user wants
* sync settings and warn user if something happend on the backend
* dev leftover
* show errors if callbook fails or callsign is invalid
* easier syntax
* Revert "easier syntax" - that was a mistake
This reverts commit 80c75dbf1e6c832f8d0616ea56b8b55d96c36418.
* fix for callbook lookup
* make pathline more visible
* better visibility of qsos
* add classic coordinates bar to the map
* fix bug in stats
* stretch max duration to 4s.. just in case
* simple sanity check in js to prevent unnecessary callbook lookups
* simulate tab after filling the call from scp
* fix poll radios with enabled worker
* reset po/mo files back to upstream/dev
* split contest exports, add back reg1test edi format
* keep the menu item but redirect to contesting
* better syntax and bugfix
* break it down further and fix typo ("constraint")
* use monospace font for input fields
* fix: in worker driven mode we need to do the heartbeat also on not focused windows otherwise we loose this contact
* fix: error handling on invalid times
* wavelog Ø
* more styling
* band lowercase fix
* Other is not a very descriptive title for a contest logger window, so we rename it to "Contest"
* custom contest name
* compare the whole array instead just a few settings
---------
Co-authored-by: int2001 <joerg@dj7nt.de>
Co-authored-by: HadleySo <71105018+HadleySo@users.noreply.github.com>
Co-authored-by: DB4SCW <dev@db4scw.de>
2026-06-14 14:23:00 +02:00
public function attachContestDialog () {
$qsoIds = $this -> input -> post ( 'qsoIds' , true );
$data [ 'qsoIds' ] = $qsoIds ;
$this -> load -> model ( 'contesting_model' );
$data [ 'contests' ] = $this -> contesting_model -> get_user_contests ();
$data [ 'custom_date_format' ] = $this -> session -> userdata ( 'user_date_format' );
$this -> load -> view ( 'logbookadvanced/attachContest' , $data );
}
public function attachContestQsos () {
$this -> load -> model ( 'contesting_model' );
2026-06-15 18:21:20 +02:00
$this -> load -> model ( 'logbook_model' );
New Wavelog Contesting and Basics for Wavelog Worker (#3063)
* initial commit for new contesting in Wavelog
* implemented cache buster to match logic from upstream dev branch
* refactore data-store to idb since this will be much faster with a lot of QSOs (scale for the future)
* implementation of other exchange types (wip)
* updated migration version
* renamed mig
* renamed mig
* updated mig
* ESC Handler to reset form
* Add Websocket
* stretch maxDuration warning
We can stretch the maxDuration warning to 2 seconds to allow for more network latency and processing time. The heartbeat is protected against multiple parallel requests, so we can afford to be more lenient with the duration before showing a warning. This should help reduce false positives in environments with higher latency or slower processing.
* worked before warning in qso form
While input the logic checks in the qso list if the callisgn already exists on the same band and mode.
* translations
* fix band buttons
* updated migration after release 2.4.2
* Fixing create new contest, add clubstation permission check, add time check to contests
* Adding attach QSO to Contest
* Remove redundant clubstation checks
* Fix function tip
* Remove time check when launch contest
* Fixing contest attach main logbook, adding detach contest qso
* Enable clubstation contest QSO detach attach
* add space handler for callsign input
* set rst default to 599 for cw, 59 for others
* add grid and refactor some ui to make a better fitting here and there
* adjust tabindex
* add "copy exchange to" feature
* fix css for all themes
* adif and cbr export
* fix bug with wrong operator callsign
* add exchange type "exchange+grid"
* introduce new logic for exchangetypes and more flexible order selection
* fix broken qso list scroll
* legacy import feature
* more precise wording
* feat: inline editing of QSOs by double click in the QSO list
* redirect cabrillo to contesting manager
* Fix QSO permission check
* remove unused cabrillo stuff
* remove duplicate function
* fix check if worked before on band change
tnx to @int2001
* fix flash message for legacy importer
* make dropdown searchable and place "other" at the top
* add hint about "Other" contest
* avoid "flash" of winkeyer settings in qso logging, it shows up if cw is set as mode
* winkeyer for the new contesting
need proper testing by @AndreasK79 and @phl0 since I don't have a winkeyer myself. I tested with a python simulator...
* english comments
* proper singular/plural
* fix dropdown
* preselect active station location
* allow editing time aswell
* fix fontsize in radio buttons
* remove redundant qso count query
* cache last updated value for contest qsos to reduce db load
* index on user id
* cache also qso count
* you can now resize windows also on the edges
requested by @xyz667 in https://github.com/wavelog/wavelog/pull/3063#issuecomment-4557850867
* fix oversized clock
* click to prepare logging for contesting
Logic:
- if qso windows is open, call is sent to qso form
- if contest log is open, call is sent to contest log
- if both are open, call is sent to contest log
- if none is open, click opens qso form and call is sent to qso form
* handle exchange s prefill with data from the last qso and make exchange always uppercase
* add dropdown to qso list with option to delete qsos
* language fixes
* english comments
* center text
* fix missing dropdown on new qsos
* add date presets for contest session creator/editor
* basic worker implementation
* support multiple workers for clustering
* remove unnecessary node column
* simple availability check
* websocket for contesting
* bonus: add vip for visibilty in debug view
* use vip if available
* worker disabled in debug view if disabled in config
* racecondition for winkeyer breaks edit/delete dropdown
* racecondition for winkeyer breaks edit/delete dropdown
* qso handling for worker in contesting, no high interval heartbeat anymore
* clear heartbeat intervall
* fix some timing bugs
* remove dedicated worker controller as it's not needed
* handle whitespace
* trigger sync engine after processing QSO sync response and adjust last sync time to avoid spurious resyncs
* fix set and setLocal
* fix change detection and sync logic
* fix the lost of seconds due to edit
* fix table rendering
* watermark handling for true delta
* remove caching as it brings more problems here as benefits
* make serial as default exchangetype
* Add clarification on cluster setup requirements for worker URLs
* add operator to qso list if this is a clubstation
* fix bug for editing qsos in clubmode
* remove redundant code
* integers must be null in database
* fix bug in tabindex if 3 exchangefields are configured (serial, exchange, grid)
* nice contesting map (draft)
* map autofit
* add grid overlay
* calculate distanz and azimuth
* include rotor control via waveloggate (ws only)
* implement simple dedicated callbook lookup
* simpler and faster lookup
* option in contest session to disabled callbook lookup and only calculate dxcc
* syntax issue
* fix bug in CBR export
* catch empty result on contest
* remove some leftovers
* removed some comments
* remove unused stuff
* removed old todos/comments
* add 4s timeout for ajax transport
* you need to be admin for this
* translations
* add option to delete qso's aswell when deleting a session (opt in)
* add quickstart button in manager
* removed old todo
* fix "grows to bottom"
* disable "copy exchange to" if no exchange is set
* clear map on qso clear aswell
* same for scp
* updated documentation link
* calculate distanze and azimut also on grid only
* better space usage in qso input
* callbook db first approach, online lookup can be disabled while being cached for all users when enabled
* some input validation
* use only one sot for qrgtoband
* basic stats component
* fix html encoding
* render all aswell
* ascii
* store locally which time frame the user wants
* sync settings and warn user if something happend on the backend
* dev leftover
* show errors if callbook fails or callsign is invalid
* easier syntax
* Revert "easier syntax" - that was a mistake
This reverts commit 80c75dbf1e6c832f8d0616ea56b8b55d96c36418.
* fix for callbook lookup
* make pathline more visible
* better visibility of qsos
* add classic coordinates bar to the map
* fix bug in stats
* stretch max duration to 4s.. just in case
* simple sanity check in js to prevent unnecessary callbook lookups
* simulate tab after filling the call from scp
* fix poll radios with enabled worker
* reset po/mo files back to upstream/dev
* split contest exports, add back reg1test edi format
* keep the menu item but redirect to contesting
* better syntax and bugfix
* break it down further and fix typo ("constraint")
* use monospace font for input fields
* fix: in worker driven mode we need to do the heartbeat also on not focused windows otherwise we loose this contact
* fix: error handling on invalid times
* wavelog Ø
* more styling
* band lowercase fix
* Other is not a very descriptive title for a contest logger window, so we rename it to "Contest"
* custom contest name
* compare the whole array instead just a few settings
---------
Co-authored-by: int2001 <joerg@dj7nt.de>
Co-authored-by: HadleySo <71105018+HadleySo@users.noreply.github.com>
Co-authored-by: DB4SCW <dev@db4scw.de>
2026-06-14 14:23:00 +02:00
$qsoIds = $this -> input -> post ( 'qsoIds' , true );
$contestId = $this -> input -> post ( 'selected_contest' , true );
if ( ! is_array ( $qsoIds ) || count ( $qsoIds ) < 1 ) {
header ( " Content-Type: application/json " );
echo json_encode ([ 'success' => false , 'message' => 'Invalid QSO IDs' ]);
return ;
}
// Check if permission on contest
if ( ! $this -> contesting_model -> check_user_contest ( $contestId )) {
header ( " Content-Type: application/json " );
echo json_encode ([ 'success' => false , 'message' => 'Invalid contest' ]);
2026-06-15 18:21:20 +02:00
return ;
New Wavelog Contesting and Basics for Wavelog Worker (#3063)
* initial commit for new contesting in Wavelog
* implemented cache buster to match logic from upstream dev branch
* refactore data-store to idb since this will be much faster with a lot of QSOs (scale for the future)
* implementation of other exchange types (wip)
* updated migration version
* renamed mig
* renamed mig
* updated mig
* ESC Handler to reset form
* Add Websocket
* stretch maxDuration warning
We can stretch the maxDuration warning to 2 seconds to allow for more network latency and processing time. The heartbeat is protected against multiple parallel requests, so we can afford to be more lenient with the duration before showing a warning. This should help reduce false positives in environments with higher latency or slower processing.
* worked before warning in qso form
While input the logic checks in the qso list if the callisgn already exists on the same band and mode.
* translations
* fix band buttons
* updated migration after release 2.4.2
* Fixing create new contest, add clubstation permission check, add time check to contests
* Adding attach QSO to Contest
* Remove redundant clubstation checks
* Fix function tip
* Remove time check when launch contest
* Fixing contest attach main logbook, adding detach contest qso
* Enable clubstation contest QSO detach attach
* add space handler for callsign input
* set rst default to 599 for cw, 59 for others
* add grid and refactor some ui to make a better fitting here and there
* adjust tabindex
* add "copy exchange to" feature
* fix css for all themes
* adif and cbr export
* fix bug with wrong operator callsign
* add exchange type "exchange+grid"
* introduce new logic for exchangetypes and more flexible order selection
* fix broken qso list scroll
* legacy import feature
* more precise wording
* feat: inline editing of QSOs by double click in the QSO list
* redirect cabrillo to contesting manager
* Fix QSO permission check
* remove unused cabrillo stuff
* remove duplicate function
* fix check if worked before on band change
tnx to @int2001
* fix flash message for legacy importer
* make dropdown searchable and place "other" at the top
* add hint about "Other" contest
* avoid "flash" of winkeyer settings in qso logging, it shows up if cw is set as mode
* winkeyer for the new contesting
need proper testing by @AndreasK79 and @phl0 since I don't have a winkeyer myself. I tested with a python simulator...
* english comments
* proper singular/plural
* fix dropdown
* preselect active station location
* allow editing time aswell
* fix fontsize in radio buttons
* remove redundant qso count query
* cache last updated value for contest qsos to reduce db load
* index on user id
* cache also qso count
* you can now resize windows also on the edges
requested by @xyz667 in https://github.com/wavelog/wavelog/pull/3063#issuecomment-4557850867
* fix oversized clock
* click to prepare logging for contesting
Logic:
- if qso windows is open, call is sent to qso form
- if contest log is open, call is sent to contest log
- if both are open, call is sent to contest log
- if none is open, click opens qso form and call is sent to qso form
* handle exchange s prefill with data from the last qso and make exchange always uppercase
* add dropdown to qso list with option to delete qsos
* language fixes
* english comments
* center text
* fix missing dropdown on new qsos
* add date presets for contest session creator/editor
* basic worker implementation
* support multiple workers for clustering
* remove unnecessary node column
* simple availability check
* websocket for contesting
* bonus: add vip for visibilty in debug view
* use vip if available
* worker disabled in debug view if disabled in config
* racecondition for winkeyer breaks edit/delete dropdown
* racecondition for winkeyer breaks edit/delete dropdown
* qso handling for worker in contesting, no high interval heartbeat anymore
* clear heartbeat intervall
* fix some timing bugs
* remove dedicated worker controller as it's not needed
* handle whitespace
* trigger sync engine after processing QSO sync response and adjust last sync time to avoid spurious resyncs
* fix set and setLocal
* fix change detection and sync logic
* fix the lost of seconds due to edit
* fix table rendering
* watermark handling for true delta
* remove caching as it brings more problems here as benefits
* make serial as default exchangetype
* Add clarification on cluster setup requirements for worker URLs
* add operator to qso list if this is a clubstation
* fix bug for editing qsos in clubmode
* remove redundant code
* integers must be null in database
* fix bug in tabindex if 3 exchangefields are configured (serial, exchange, grid)
* nice contesting map (draft)
* map autofit
* add grid overlay
* calculate distanz and azimuth
* include rotor control via waveloggate (ws only)
* implement simple dedicated callbook lookup
* simpler and faster lookup
* option in contest session to disabled callbook lookup and only calculate dxcc
* syntax issue
* fix bug in CBR export
* catch empty result on contest
* remove some leftovers
* removed some comments
* remove unused stuff
* removed old todos/comments
* add 4s timeout for ajax transport
* you need to be admin for this
* translations
* add option to delete qso's aswell when deleting a session (opt in)
* add quickstart button in manager
* removed old todo
* fix "grows to bottom"
* disable "copy exchange to" if no exchange is set
* clear map on qso clear aswell
* same for scp
* updated documentation link
* calculate distanze and azimut also on grid only
* better space usage in qso input
* callbook db first approach, online lookup can be disabled while being cached for all users when enabled
* some input validation
* use only one sot for qrgtoband
* basic stats component
* fix html encoding
* render all aswell
* ascii
* store locally which time frame the user wants
* sync settings and warn user if something happend on the backend
* dev leftover
* show errors if callbook fails or callsign is invalid
* easier syntax
* Revert "easier syntax" - that was a mistake
This reverts commit 80c75dbf1e6c832f8d0616ea56b8b55d96c36418.
* fix for callbook lookup
* make pathline more visible
* better visibility of qsos
* add classic coordinates bar to the map
* fix bug in stats
* stretch max duration to 4s.. just in case
* simple sanity check in js to prevent unnecessary callbook lookups
* simulate tab after filling the call from scp
* fix poll radios with enabled worker
* reset po/mo files back to upstream/dev
* split contest exports, add back reg1test edi format
* keep the menu item but redirect to contesting
* better syntax and bugfix
* break it down further and fix typo ("constraint")
* use monospace font for input fields
* fix: in worker driven mode we need to do the heartbeat also on not focused windows otherwise we loose this contact
* fix: error handling on invalid times
* wavelog Ø
* more styling
* band lowercase fix
* Other is not a very descriptive title for a contest logger window, so we rename it to "Contest"
* custom contest name
* compare the whole array instead just a few settings
---------
Co-authored-by: int2001 <joerg@dj7nt.de>
Co-authored-by: HadleySo <71105018+HadleySo@users.noreply.github.com>
Co-authored-by: DB4SCW <dev@db4scw.de>
2026-06-14 14:23:00 +02:00
}
$error_count = 0 ;
foreach ( $qsoIds as $qsoID ) {
// Check if user has permission on QSO
if ( ! clubaccess_check ( 3 , $qsoID )) {
$error_count += 1 ;
continue ;
}
2026-06-15 18:21:20 +02:00
New Wavelog Contesting and Basics for Wavelog Worker (#3063)
* initial commit for new contesting in Wavelog
* implemented cache buster to match logic from upstream dev branch
* refactore data-store to idb since this will be much faster with a lot of QSOs (scale for the future)
* implementation of other exchange types (wip)
* updated migration version
* renamed mig
* renamed mig
* updated mig
* ESC Handler to reset form
* Add Websocket
* stretch maxDuration warning
We can stretch the maxDuration warning to 2 seconds to allow for more network latency and processing time. The heartbeat is protected against multiple parallel requests, so we can afford to be more lenient with the duration before showing a warning. This should help reduce false positives in environments with higher latency or slower processing.
* worked before warning in qso form
While input the logic checks in the qso list if the callisgn already exists on the same band and mode.
* translations
* fix band buttons
* updated migration after release 2.4.2
* Fixing create new contest, add clubstation permission check, add time check to contests
* Adding attach QSO to Contest
* Remove redundant clubstation checks
* Fix function tip
* Remove time check when launch contest
* Fixing contest attach main logbook, adding detach contest qso
* Enable clubstation contest QSO detach attach
* add space handler for callsign input
* set rst default to 599 for cw, 59 for others
* add grid and refactor some ui to make a better fitting here and there
* adjust tabindex
* add "copy exchange to" feature
* fix css for all themes
* adif and cbr export
* fix bug with wrong operator callsign
* add exchange type "exchange+grid"
* introduce new logic for exchangetypes and more flexible order selection
* fix broken qso list scroll
* legacy import feature
* more precise wording
* feat: inline editing of QSOs by double click in the QSO list
* redirect cabrillo to contesting manager
* Fix QSO permission check
* remove unused cabrillo stuff
* remove duplicate function
* fix check if worked before on band change
tnx to @int2001
* fix flash message for legacy importer
* make dropdown searchable and place "other" at the top
* add hint about "Other" contest
* avoid "flash" of winkeyer settings in qso logging, it shows up if cw is set as mode
* winkeyer for the new contesting
need proper testing by @AndreasK79 and @phl0 since I don't have a winkeyer myself. I tested with a python simulator...
* english comments
* proper singular/plural
* fix dropdown
* preselect active station location
* allow editing time aswell
* fix fontsize in radio buttons
* remove redundant qso count query
* cache last updated value for contest qsos to reduce db load
* index on user id
* cache also qso count
* you can now resize windows also on the edges
requested by @xyz667 in https://github.com/wavelog/wavelog/pull/3063#issuecomment-4557850867
* fix oversized clock
* click to prepare logging for contesting
Logic:
- if qso windows is open, call is sent to qso form
- if contest log is open, call is sent to contest log
- if both are open, call is sent to contest log
- if none is open, click opens qso form and call is sent to qso form
* handle exchange s prefill with data from the last qso and make exchange always uppercase
* add dropdown to qso list with option to delete qsos
* language fixes
* english comments
* center text
* fix missing dropdown on new qsos
* add date presets for contest session creator/editor
* basic worker implementation
* support multiple workers for clustering
* remove unnecessary node column
* simple availability check
* websocket for contesting
* bonus: add vip for visibilty in debug view
* use vip if available
* worker disabled in debug view if disabled in config
* racecondition for winkeyer breaks edit/delete dropdown
* racecondition for winkeyer breaks edit/delete dropdown
* qso handling for worker in contesting, no high interval heartbeat anymore
* clear heartbeat intervall
* fix some timing bugs
* remove dedicated worker controller as it's not needed
* handle whitespace
* trigger sync engine after processing QSO sync response and adjust last sync time to avoid spurious resyncs
* fix set and setLocal
* fix change detection and sync logic
* fix the lost of seconds due to edit
* fix table rendering
* watermark handling for true delta
* remove caching as it brings more problems here as benefits
* make serial as default exchangetype
* Add clarification on cluster setup requirements for worker URLs
* add operator to qso list if this is a clubstation
* fix bug for editing qsos in clubmode
* remove redundant code
* integers must be null in database
* fix bug in tabindex if 3 exchangefields are configured (serial, exchange, grid)
* nice contesting map (draft)
* map autofit
* add grid overlay
* calculate distanz and azimuth
* include rotor control via waveloggate (ws only)
* implement simple dedicated callbook lookup
* simpler and faster lookup
* option in contest session to disabled callbook lookup and only calculate dxcc
* syntax issue
* fix bug in CBR export
* catch empty result on contest
* remove some leftovers
* removed some comments
* remove unused stuff
* removed old todos/comments
* add 4s timeout for ajax transport
* you need to be admin for this
* translations
* add option to delete qso's aswell when deleting a session (opt in)
* add quickstart button in manager
* removed old todo
* fix "grows to bottom"
* disable "copy exchange to" if no exchange is set
* clear map on qso clear aswell
* same for scp
* updated documentation link
* calculate distanze and azimut also on grid only
* better space usage in qso input
* callbook db first approach, online lookup can be disabled while being cached for all users when enabled
* some input validation
* use only one sot for qrgtoband
* basic stats component
* fix html encoding
* render all aswell
* ascii
* store locally which time frame the user wants
* sync settings and warn user if something happend on the backend
* dev leftover
* show errors if callbook fails or callsign is invalid
* easier syntax
* Revert "easier syntax" - that was a mistake
This reverts commit 80c75dbf1e6c832f8d0616ea56b8b55d96c36418.
* fix for callbook lookup
* make pathline more visible
* better visibility of qsos
* add classic coordinates bar to the map
* fix bug in stats
* stretch max duration to 4s.. just in case
* simple sanity check in js to prevent unnecessary callbook lookups
* simulate tab after filling the call from scp
* fix poll radios with enabled worker
* reset po/mo files back to upstream/dev
* split contest exports, add back reg1test edi format
* keep the menu item but redirect to contesting
* better syntax and bugfix
* break it down further and fix typo ("constraint")
* use monospace font for input fields
* fix: in worker driven mode we need to do the heartbeat also on not focused windows otherwise we loose this contact
* fix: error handling on invalid times
* wavelog Ø
* more styling
* band lowercase fix
* Other is not a very descriptive title for a contest logger window, so we rename it to "Contest"
* custom contest name
* compare the whole array instead just a few settings
---------
Co-authored-by: int2001 <joerg@dj7nt.de>
Co-authored-by: HadleySo <71105018+HadleySo@users.noreply.github.com>
Co-authored-by: DB4SCW <dev@db4scw.de>
2026-06-14 14:23:00 +02:00
// Update Contest
$this -> contesting_model -> link_qso ( $qsoID , $contestId );
// Update QSO
$contest_adif_id = $this -> contesting_model -> get_session_info ( $contestId )[ 'contest_id' ];
$this -> logbook_model -> set_contest ( $qsoID , $contest_adif_id );
}
if ( $error_count > 0 ) {
$error_message = " Error on " . ( string ) $error_count . " records, success on " . ( string ) ( count ( $qsoIds ) - $error_count );
header ( " Content-Type: application/json " );
echo json_encode ([ 'success' => false , 'message' => $error_message ]);
return ;
}
header ( " Content-Type: application/json " );
echo json_encode ([ 'success' => true ]);
return ;
}
public function detachContestDialog () {
$qsoIds = $this -> input -> post ( 'qsoIds' , true );
$data [ 'qsoIds' ] = $qsoIds ;
$this -> load -> view ( 'logbookadvanced/detachContest' , $data );
}
public function detachContestQsos () {
$this -> load -> model ( 'contesting_model' );
2026-06-15 18:21:20 +02:00
$this -> load -> model ( 'logbook_model' );
New Wavelog Contesting and Basics for Wavelog Worker (#3063)
* initial commit for new contesting in Wavelog
* implemented cache buster to match logic from upstream dev branch
* refactore data-store to idb since this will be much faster with a lot of QSOs (scale for the future)
* implementation of other exchange types (wip)
* updated migration version
* renamed mig
* renamed mig
* updated mig
* ESC Handler to reset form
* Add Websocket
* stretch maxDuration warning
We can stretch the maxDuration warning to 2 seconds to allow for more network latency and processing time. The heartbeat is protected against multiple parallel requests, so we can afford to be more lenient with the duration before showing a warning. This should help reduce false positives in environments with higher latency or slower processing.
* worked before warning in qso form
While input the logic checks in the qso list if the callisgn already exists on the same band and mode.
* translations
* fix band buttons
* updated migration after release 2.4.2
* Fixing create new contest, add clubstation permission check, add time check to contests
* Adding attach QSO to Contest
* Remove redundant clubstation checks
* Fix function tip
* Remove time check when launch contest
* Fixing contest attach main logbook, adding detach contest qso
* Enable clubstation contest QSO detach attach
* add space handler for callsign input
* set rst default to 599 for cw, 59 for others
* add grid and refactor some ui to make a better fitting here and there
* adjust tabindex
* add "copy exchange to" feature
* fix css for all themes
* adif and cbr export
* fix bug with wrong operator callsign
* add exchange type "exchange+grid"
* introduce new logic for exchangetypes and more flexible order selection
* fix broken qso list scroll
* legacy import feature
* more precise wording
* feat: inline editing of QSOs by double click in the QSO list
* redirect cabrillo to contesting manager
* Fix QSO permission check
* remove unused cabrillo stuff
* remove duplicate function
* fix check if worked before on band change
tnx to @int2001
* fix flash message for legacy importer
* make dropdown searchable and place "other" at the top
* add hint about "Other" contest
* avoid "flash" of winkeyer settings in qso logging, it shows up if cw is set as mode
* winkeyer for the new contesting
need proper testing by @AndreasK79 and @phl0 since I don't have a winkeyer myself. I tested with a python simulator...
* english comments
* proper singular/plural
* fix dropdown
* preselect active station location
* allow editing time aswell
* fix fontsize in radio buttons
* remove redundant qso count query
* cache last updated value for contest qsos to reduce db load
* index on user id
* cache also qso count
* you can now resize windows also on the edges
requested by @xyz667 in https://github.com/wavelog/wavelog/pull/3063#issuecomment-4557850867
* fix oversized clock
* click to prepare logging for contesting
Logic:
- if qso windows is open, call is sent to qso form
- if contest log is open, call is sent to contest log
- if both are open, call is sent to contest log
- if none is open, click opens qso form and call is sent to qso form
* handle exchange s prefill with data from the last qso and make exchange always uppercase
* add dropdown to qso list with option to delete qsos
* language fixes
* english comments
* center text
* fix missing dropdown on new qsos
* add date presets for contest session creator/editor
* basic worker implementation
* support multiple workers for clustering
* remove unnecessary node column
* simple availability check
* websocket for contesting
* bonus: add vip for visibilty in debug view
* use vip if available
* worker disabled in debug view if disabled in config
* racecondition for winkeyer breaks edit/delete dropdown
* racecondition for winkeyer breaks edit/delete dropdown
* qso handling for worker in contesting, no high interval heartbeat anymore
* clear heartbeat intervall
* fix some timing bugs
* remove dedicated worker controller as it's not needed
* handle whitespace
* trigger sync engine after processing QSO sync response and adjust last sync time to avoid spurious resyncs
* fix set and setLocal
* fix change detection and sync logic
* fix the lost of seconds due to edit
* fix table rendering
* watermark handling for true delta
* remove caching as it brings more problems here as benefits
* make serial as default exchangetype
* Add clarification on cluster setup requirements for worker URLs
* add operator to qso list if this is a clubstation
* fix bug for editing qsos in clubmode
* remove redundant code
* integers must be null in database
* fix bug in tabindex if 3 exchangefields are configured (serial, exchange, grid)
* nice contesting map (draft)
* map autofit
* add grid overlay
* calculate distanz and azimuth
* include rotor control via waveloggate (ws only)
* implement simple dedicated callbook lookup
* simpler and faster lookup
* option in contest session to disabled callbook lookup and only calculate dxcc
* syntax issue
* fix bug in CBR export
* catch empty result on contest
* remove some leftovers
* removed some comments
* remove unused stuff
* removed old todos/comments
* add 4s timeout for ajax transport
* you need to be admin for this
* translations
* add option to delete qso's aswell when deleting a session (opt in)
* add quickstart button in manager
* removed old todo
* fix "grows to bottom"
* disable "copy exchange to" if no exchange is set
* clear map on qso clear aswell
* same for scp
* updated documentation link
* calculate distanze and azimut also on grid only
* better space usage in qso input
* callbook db first approach, online lookup can be disabled while being cached for all users when enabled
* some input validation
* use only one sot for qrgtoband
* basic stats component
* fix html encoding
* render all aswell
* ascii
* store locally which time frame the user wants
* sync settings and warn user if something happend on the backend
* dev leftover
* show errors if callbook fails or callsign is invalid
* easier syntax
* Revert "easier syntax" - that was a mistake
This reverts commit 80c75dbf1e6c832f8d0616ea56b8b55d96c36418.
* fix for callbook lookup
* make pathline more visible
* better visibility of qsos
* add classic coordinates bar to the map
* fix bug in stats
* stretch max duration to 4s.. just in case
* simple sanity check in js to prevent unnecessary callbook lookups
* simulate tab after filling the call from scp
* fix poll radios with enabled worker
* reset po/mo files back to upstream/dev
* split contest exports, add back reg1test edi format
* keep the menu item but redirect to contesting
* better syntax and bugfix
* break it down further and fix typo ("constraint")
* use monospace font for input fields
* fix: in worker driven mode we need to do the heartbeat also on not focused windows otherwise we loose this contact
* fix: error handling on invalid times
* wavelog Ø
* more styling
* band lowercase fix
* Other is not a very descriptive title for a contest logger window, so we rename it to "Contest"
* custom contest name
* compare the whole array instead just a few settings
---------
Co-authored-by: int2001 <joerg@dj7nt.de>
Co-authored-by: HadleySo <71105018+HadleySo@users.noreply.github.com>
Co-authored-by: DB4SCW <dev@db4scw.de>
2026-06-14 14:23:00 +02:00
$qsoIds = $this -> input -> post ( 'qsoIds' , true );
if ( ! is_array ( $qsoIds ) || count ( $qsoIds ) < 1 ) {
header ( " Content-Type: application/json " );
echo json_encode ([ 'success' => false , 'message' => 'Invalid QSO IDs' ]);
return ;
}
$error_count = 0 ;
foreach ( $qsoIds as $qsoID ) {
// Check if user has permission on QSO
if ( ! clubaccess_check ( 3 , $qsoID )) {
$error_count += 1 ;
continue ;
}
// Check if permission on contest
$contestId = $this -> contesting_model -> get_linked_contest ( $qsoID );
if ( $contestId != 0 && ! $this -> contesting_model -> check_user_contest ( $contestId )) {
$error_count += 1 ;
continue ;
}
// Update Contest
$this -> contesting_model -> unlink_qso ( $qsoID , $contestId );
// Update QSO
$this -> logbook_model -> set_contest ( $qsoID , 0 );
2026-06-15 18:21:20 +02:00
New Wavelog Contesting and Basics for Wavelog Worker (#3063)
* initial commit for new contesting in Wavelog
* implemented cache buster to match logic from upstream dev branch
* refactore data-store to idb since this will be much faster with a lot of QSOs (scale for the future)
* implementation of other exchange types (wip)
* updated migration version
* renamed mig
* renamed mig
* updated mig
* ESC Handler to reset form
* Add Websocket
* stretch maxDuration warning
We can stretch the maxDuration warning to 2 seconds to allow for more network latency and processing time. The heartbeat is protected against multiple parallel requests, so we can afford to be more lenient with the duration before showing a warning. This should help reduce false positives in environments with higher latency or slower processing.
* worked before warning in qso form
While input the logic checks in the qso list if the callisgn already exists on the same band and mode.
* translations
* fix band buttons
* updated migration after release 2.4.2
* Fixing create new contest, add clubstation permission check, add time check to contests
* Adding attach QSO to Contest
* Remove redundant clubstation checks
* Fix function tip
* Remove time check when launch contest
* Fixing contest attach main logbook, adding detach contest qso
* Enable clubstation contest QSO detach attach
* add space handler for callsign input
* set rst default to 599 for cw, 59 for others
* add grid and refactor some ui to make a better fitting here and there
* adjust tabindex
* add "copy exchange to" feature
* fix css for all themes
* adif and cbr export
* fix bug with wrong operator callsign
* add exchange type "exchange+grid"
* introduce new logic for exchangetypes and more flexible order selection
* fix broken qso list scroll
* legacy import feature
* more precise wording
* feat: inline editing of QSOs by double click in the QSO list
* redirect cabrillo to contesting manager
* Fix QSO permission check
* remove unused cabrillo stuff
* remove duplicate function
* fix check if worked before on band change
tnx to @int2001
* fix flash message for legacy importer
* make dropdown searchable and place "other" at the top
* add hint about "Other" contest
* avoid "flash" of winkeyer settings in qso logging, it shows up if cw is set as mode
* winkeyer for the new contesting
need proper testing by @AndreasK79 and @phl0 since I don't have a winkeyer myself. I tested with a python simulator...
* english comments
* proper singular/plural
* fix dropdown
* preselect active station location
* allow editing time aswell
* fix fontsize in radio buttons
* remove redundant qso count query
* cache last updated value for contest qsos to reduce db load
* index on user id
* cache also qso count
* you can now resize windows also on the edges
requested by @xyz667 in https://github.com/wavelog/wavelog/pull/3063#issuecomment-4557850867
* fix oversized clock
* click to prepare logging for contesting
Logic:
- if qso windows is open, call is sent to qso form
- if contest log is open, call is sent to contest log
- if both are open, call is sent to contest log
- if none is open, click opens qso form and call is sent to qso form
* handle exchange s prefill with data from the last qso and make exchange always uppercase
* add dropdown to qso list with option to delete qsos
* language fixes
* english comments
* center text
* fix missing dropdown on new qsos
* add date presets for contest session creator/editor
* basic worker implementation
* support multiple workers for clustering
* remove unnecessary node column
* simple availability check
* websocket for contesting
* bonus: add vip for visibilty in debug view
* use vip if available
* worker disabled in debug view if disabled in config
* racecondition for winkeyer breaks edit/delete dropdown
* racecondition for winkeyer breaks edit/delete dropdown
* qso handling for worker in contesting, no high interval heartbeat anymore
* clear heartbeat intervall
* fix some timing bugs
* remove dedicated worker controller as it's not needed
* handle whitespace
* trigger sync engine after processing QSO sync response and adjust last sync time to avoid spurious resyncs
* fix set and setLocal
* fix change detection and sync logic
* fix the lost of seconds due to edit
* fix table rendering
* watermark handling for true delta
* remove caching as it brings more problems here as benefits
* make serial as default exchangetype
* Add clarification on cluster setup requirements for worker URLs
* add operator to qso list if this is a clubstation
* fix bug for editing qsos in clubmode
* remove redundant code
* integers must be null in database
* fix bug in tabindex if 3 exchangefields are configured (serial, exchange, grid)
* nice contesting map (draft)
* map autofit
* add grid overlay
* calculate distanz and azimuth
* include rotor control via waveloggate (ws only)
* implement simple dedicated callbook lookup
* simpler and faster lookup
* option in contest session to disabled callbook lookup and only calculate dxcc
* syntax issue
* fix bug in CBR export
* catch empty result on contest
* remove some leftovers
* removed some comments
* remove unused stuff
* removed old todos/comments
* add 4s timeout for ajax transport
* you need to be admin for this
* translations
* add option to delete qso's aswell when deleting a session (opt in)
* add quickstart button in manager
* removed old todo
* fix "grows to bottom"
* disable "copy exchange to" if no exchange is set
* clear map on qso clear aswell
* same for scp
* updated documentation link
* calculate distanze and azimut also on grid only
* better space usage in qso input
* callbook db first approach, online lookup can be disabled while being cached for all users when enabled
* some input validation
* use only one sot for qrgtoband
* basic stats component
* fix html encoding
* render all aswell
* ascii
* store locally which time frame the user wants
* sync settings and warn user if something happend on the backend
* dev leftover
* show errors if callbook fails or callsign is invalid
* easier syntax
* Revert "easier syntax" - that was a mistake
This reverts commit 80c75dbf1e6c832f8d0616ea56b8b55d96c36418.
* fix for callbook lookup
* make pathline more visible
* better visibility of qsos
* add classic coordinates bar to the map
* fix bug in stats
* stretch max duration to 4s.. just in case
* simple sanity check in js to prevent unnecessary callbook lookups
* simulate tab after filling the call from scp
* fix poll radios with enabled worker
* reset po/mo files back to upstream/dev
* split contest exports, add back reg1test edi format
* keep the menu item but redirect to contesting
* better syntax and bugfix
* break it down further and fix typo ("constraint")
* use monospace font for input fields
* fix: in worker driven mode we need to do the heartbeat also on not focused windows otherwise we loose this contact
* fix: error handling on invalid times
* wavelog Ø
* more styling
* band lowercase fix
* Other is not a very descriptive title for a contest logger window, so we rename it to "Contest"
* custom contest name
* compare the whole array instead just a few settings
---------
Co-authored-by: int2001 <joerg@dj7nt.de>
Co-authored-by: HadleySo <71105018+HadleySo@users.noreply.github.com>
Co-authored-by: DB4SCW <dev@db4scw.de>
2026-06-14 14:23:00 +02:00
}
if ( $error_count > 0 ) {
$error_message = " Error on " . ( string ) $error_count . " records, success on " . ( string ) ( count ( $qsoIds ) - $error_count );
header ( " Content-Type: application/json " );
echo json_encode ([ 'success' => false , 'message' => $error_message ]);
return ;
}
header ( " Content-Type: application/json " );
echo json_encode ([ 'success' => true ]);
2026-06-15 18:21:20 +02:00
return ;
New Wavelog Contesting and Basics for Wavelog Worker (#3063)
* initial commit for new contesting in Wavelog
* implemented cache buster to match logic from upstream dev branch
* refactore data-store to idb since this will be much faster with a lot of QSOs (scale for the future)
* implementation of other exchange types (wip)
* updated migration version
* renamed mig
* renamed mig
* updated mig
* ESC Handler to reset form
* Add Websocket
* stretch maxDuration warning
We can stretch the maxDuration warning to 2 seconds to allow for more network latency and processing time. The heartbeat is protected against multiple parallel requests, so we can afford to be more lenient with the duration before showing a warning. This should help reduce false positives in environments with higher latency or slower processing.
* worked before warning in qso form
While input the logic checks in the qso list if the callisgn already exists on the same band and mode.
* translations
* fix band buttons
* updated migration after release 2.4.2
* Fixing create new contest, add clubstation permission check, add time check to contests
* Adding attach QSO to Contest
* Remove redundant clubstation checks
* Fix function tip
* Remove time check when launch contest
* Fixing contest attach main logbook, adding detach contest qso
* Enable clubstation contest QSO detach attach
* add space handler for callsign input
* set rst default to 599 for cw, 59 for others
* add grid and refactor some ui to make a better fitting here and there
* adjust tabindex
* add "copy exchange to" feature
* fix css for all themes
* adif and cbr export
* fix bug with wrong operator callsign
* add exchange type "exchange+grid"
* introduce new logic for exchangetypes and more flexible order selection
* fix broken qso list scroll
* legacy import feature
* more precise wording
* feat: inline editing of QSOs by double click in the QSO list
* redirect cabrillo to contesting manager
* Fix QSO permission check
* remove unused cabrillo stuff
* remove duplicate function
* fix check if worked before on band change
tnx to @int2001
* fix flash message for legacy importer
* make dropdown searchable and place "other" at the top
* add hint about "Other" contest
* avoid "flash" of winkeyer settings in qso logging, it shows up if cw is set as mode
* winkeyer for the new contesting
need proper testing by @AndreasK79 and @phl0 since I don't have a winkeyer myself. I tested with a python simulator...
* english comments
* proper singular/plural
* fix dropdown
* preselect active station location
* allow editing time aswell
* fix fontsize in radio buttons
* remove redundant qso count query
* cache last updated value for contest qsos to reduce db load
* index on user id
* cache also qso count
* you can now resize windows also on the edges
requested by @xyz667 in https://github.com/wavelog/wavelog/pull/3063#issuecomment-4557850867
* fix oversized clock
* click to prepare logging for contesting
Logic:
- if qso windows is open, call is sent to qso form
- if contest log is open, call is sent to contest log
- if both are open, call is sent to contest log
- if none is open, click opens qso form and call is sent to qso form
* handle exchange s prefill with data from the last qso and make exchange always uppercase
* add dropdown to qso list with option to delete qsos
* language fixes
* english comments
* center text
* fix missing dropdown on new qsos
* add date presets for contest session creator/editor
* basic worker implementation
* support multiple workers for clustering
* remove unnecessary node column
* simple availability check
* websocket for contesting
* bonus: add vip for visibilty in debug view
* use vip if available
* worker disabled in debug view if disabled in config
* racecondition for winkeyer breaks edit/delete dropdown
* racecondition for winkeyer breaks edit/delete dropdown
* qso handling for worker in contesting, no high interval heartbeat anymore
* clear heartbeat intervall
* fix some timing bugs
* remove dedicated worker controller as it's not needed
* handle whitespace
* trigger sync engine after processing QSO sync response and adjust last sync time to avoid spurious resyncs
* fix set and setLocal
* fix change detection and sync logic
* fix the lost of seconds due to edit
* fix table rendering
* watermark handling for true delta
* remove caching as it brings more problems here as benefits
* make serial as default exchangetype
* Add clarification on cluster setup requirements for worker URLs
* add operator to qso list if this is a clubstation
* fix bug for editing qsos in clubmode
* remove redundant code
* integers must be null in database
* fix bug in tabindex if 3 exchangefields are configured (serial, exchange, grid)
* nice contesting map (draft)
* map autofit
* add grid overlay
* calculate distanz and azimuth
* include rotor control via waveloggate (ws only)
* implement simple dedicated callbook lookup
* simpler and faster lookup
* option in contest session to disabled callbook lookup and only calculate dxcc
* syntax issue
* fix bug in CBR export
* catch empty result on contest
* remove some leftovers
* removed some comments
* remove unused stuff
* removed old todos/comments
* add 4s timeout for ajax transport
* you need to be admin for this
* translations
* add option to delete qso's aswell when deleting a session (opt in)
* add quickstart button in manager
* removed old todo
* fix "grows to bottom"
* disable "copy exchange to" if no exchange is set
* clear map on qso clear aswell
* same for scp
* updated documentation link
* calculate distanze and azimut also on grid only
* better space usage in qso input
* callbook db first approach, online lookup can be disabled while being cached for all users when enabled
* some input validation
* use only one sot for qrgtoband
* basic stats component
* fix html encoding
* render all aswell
* ascii
* store locally which time frame the user wants
* sync settings and warn user if something happend on the backend
* dev leftover
* show errors if callbook fails or callsign is invalid
* easier syntax
* Revert "easier syntax" - that was a mistake
This reverts commit 80c75dbf1e6c832f8d0616ea56b8b55d96c36418.
* fix for callbook lookup
* make pathline more visible
* better visibility of qsos
* add classic coordinates bar to the map
* fix bug in stats
* stretch max duration to 4s.. just in case
* simple sanity check in js to prevent unnecessary callbook lookups
* simulate tab after filling the call from scp
* fix poll radios with enabled worker
* reset po/mo files back to upstream/dev
* split contest exports, add back reg1test edi format
* keep the menu item but redirect to contesting
* better syntax and bugfix
* break it down further and fix typo ("constraint")
* use monospace font for input fields
* fix: in worker driven mode we need to do the heartbeat also on not focused windows otherwise we loose this contact
* fix: error handling on invalid times
* wavelog Ø
* more styling
* band lowercase fix
* Other is not a very descriptive title for a contest logger window, so we rename it to "Contest"
* custom contest name
* compare the whole array instead just a few settings
---------
Co-authored-by: int2001 <joerg@dj7nt.de>
Co-authored-by: HadleySo <71105018+HadleySo@users.noreply.github.com>
Co-authored-by: DB4SCW <dev@db4scw.de>
2026-06-14 14:23:00 +02:00
}
2023-10-04 14:46:18 +02:00
}