mirror of
https://github.com/wavelog/wavelog.git
synced 2026-03-22 10:24:14 +00:00
Merge branch 'dev' into lba_qrz_filter
This commit is contained in:
@@ -22,7 +22,7 @@ $config['migration_enabled'] = TRUE;
|
||||
|
|
||||
*/
|
||||
|
||||
$config['migration_version'] = 263;
|
||||
$config['migration_version'] = 264;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -528,4 +528,93 @@ class Stationsetup extends CI_Controller {
|
||||
$this->load->view('stationsetup/locationlist');
|
||||
$this->load->view('interface_assets/footer');
|
||||
}
|
||||
|
||||
public function export_locations() {
|
||||
$this->load->model('stationsetup_model');
|
||||
|
||||
$locations = $this->stationsetup_model->list_all_locations();
|
||||
|
||||
// Output as JSON
|
||||
$this->output
|
||||
->set_content_type('application/json')
|
||||
->set_output(json_encode($locations));
|
||||
}
|
||||
|
||||
public function import_locations(){
|
||||
if (empty($_FILES['file']['tmp_name'])) {
|
||||
$this->output
|
||||
->set_content_type('application/json')
|
||||
->set_output(json_encode(['status' => 'error', 'message' => 'No file uploaded']));
|
||||
return;
|
||||
}
|
||||
|
||||
$fileContent = file_get_contents($_FILES['file']['tmp_name']);
|
||||
$locations = json_decode($fileContent, true);
|
||||
|
||||
if ($locations === null) {
|
||||
$this->output
|
||||
->set_content_type('application/json')
|
||||
->set_output(json_encode(['status' => 'error', 'message' => 'Invalid JSON file']));
|
||||
return;
|
||||
}
|
||||
|
||||
// Load your model
|
||||
$this->load->model('stationsetup_model');
|
||||
|
||||
$imported = 0;
|
||||
foreach ($locations as $loc) {
|
||||
if ($imported >= 1000){
|
||||
$this->output
|
||||
->set_content_type('application/json')
|
||||
->set_output(json_encode(['status' => 'success', 'message' => "$imported locations imported. Maximum limit of 1000 locations reached."]));
|
||||
return; // Prevent importing more than 1000 locations at once
|
||||
}
|
||||
// Data for station_profile
|
||||
$dbdata = [
|
||||
'station_active' => 0,
|
||||
'station_profile_name' => ((isset($loc['station_profile_name']) && $loc['station_profile_name'] != "") ? xss_clean($loc['station_profile_name']) : ''),
|
||||
'station_gridsquare' => ((isset($loc['station_gridsquare']) && $loc['station_gridsquare'] != "") ? xss_clean($loc['station_gridsquare']) : ''),
|
||||
'station_city' => ((isset($loc['station_city']) && $loc['station_city'] != "") ? xss_clean($loc['station_city']) : ''),
|
||||
'station_iota' => ((isset($loc['station_iota']) && $loc['station_iota'] != "") ? xss_clean($loc['station_iota']) : ''),
|
||||
'station_sota' => ((isset($loc['station_sota']) && $loc['station_sota'] != "") ? xss_clean($loc['station_sota']) : ''),
|
||||
'station_callsign' => ((isset($loc['station_callsign']) && $loc['station_callsign'] != "") ? xss_clean($loc['station_callsign']) : null),
|
||||
'station_power' => ((isset($loc['station_power']) && $loc['station_power'] != "") ? xss_clean($loc['station_power']) : null),
|
||||
'station_dxcc' => ((isset($loc['station_dxcc']) && $loc['station_dxcc'] != "") ? xss_clean($loc['station_dxcc']) : null),
|
||||
'station_cq' => ((isset($loc['station_cq']) && $loc['station_cq'] != "") ? xss_clean($loc['station_cq']) : null),
|
||||
'station_itu' => ((isset($loc['station_itu']) && $loc['station_itu'] != "") ? xss_clean($loc['station_itu']) : null),
|
||||
'station_sig' => ((isset($loc['station_sig']) && $loc['station_sig'] != "") ? xss_clean($loc['station_sig']) : null),
|
||||
'station_sig_info' => ((isset($loc['station_sig_info']) && $loc['station_sig_info'] != "") ? xss_clean($loc['station_sig_info']) : null),
|
||||
'station_wwff' => ((isset($loc['station_wwff']) && $loc['station_wwff'] != "") ? xss_clean($loc['station_wwff']) : null),
|
||||
'station_pota' => ((isset($loc['station_pota']) && $loc['station_pota'] != "") ? xss_clean($loc['station_pota']) : null),
|
||||
'state' => ((isset($loc['state']) && $loc['state'] != "") ? xss_clean($loc['state']) : null),
|
||||
'station_cnty' => ((isset($loc['station_cnty']) && $loc['station_cnty'] != "") ? xss_clean($loc['station_cnty']) : null),
|
||||
'qrzrealtime' => ((isset($loc['qrzrealtime']) && $loc['qrzrealtime'] != "") ? xss_clean($loc['qrzrealtime']) : 0),
|
||||
'oqrs' => ((isset($loc['oqrs']) && $loc['oqrs'] != "") ? xss_clean($loc['oqrs']) : 0),
|
||||
'oqrs_text' => ((isset($loc['oqrs_text']) && $loc['oqrs_text'] != "") ? xss_clean($loc['oqrs_text']) : null),
|
||||
'oqrs_email' => ((isset($loc['oqrs_email']) && $loc['oqrs_email'] != "") ? xss_clean($loc['oqrs_email']) : null),
|
||||
'webadifrealtime' => ((isset($loc['webadifrealtime']) && $loc['webadifrealtime'] != "") ? xss_clean($loc['webadifrealtime']) : null),
|
||||
'clublogignore' => ((isset($loc['clublogignore']) && $loc['clublogignore'] != "") ? xss_clean($loc['clublogignore']) : 1),
|
||||
'clublogrealtime' => ((isset($loc['clublogrealtime']) && $loc['clublogrealtime'] != "") ? xss_clean($loc['clublogrealtime']) : 0),
|
||||
'hrdlogrealtime' => ((isset($loc['hrdlogrealtime']) && $loc['hrdlogrealtime'] != "") ? xss_clean($loc['hrdlogrealtime']) : 0),
|
||||
'hrdlog_username' => ((isset($loc['hrdlog_username']) && $loc['hrdlog_username'] != "") ? xss_clean($loc['hrdlog_username']) : null),
|
||||
'eqslqthnickname' => ((isset($loc['eqslqthnickname']) && $loc['eqslqthnickname'] != "") ? xss_clean($loc['eqslqthnickname']) : null),
|
||||
'webadifapiurl' => 'https://qo100dx.club/api',
|
||||
'station_uuid' => xss_clean($loc['station_uuid'] ?? null),
|
||||
'user_id' => $this->session->userdata('user_id'),
|
||||
];
|
||||
|
||||
// Data for user_options
|
||||
$optiondata = [
|
||||
'eqsl_default_qslmsg' => xss_clean($loc['eqsl_default_qslmsg'] ?? null),
|
||||
];
|
||||
|
||||
// Insert or update location in DB
|
||||
$imported += $this->stationsetup_model->save_location($dbdata, $optiondata);
|
||||
}
|
||||
|
||||
$this->output
|
||||
->set_content_type('application/json')
|
||||
->set_output(json_encode(['status' => 'success', 'message' => "$imported locations imported."]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
24
application/migrations/264_add_station_uuid.php
Normal file
24
application/migrations/264_add_station_uuid.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
defined('BASEPATH') or exit('No direct script access allowed');
|
||||
|
||||
class Migration_add_station_uuid extends CI_Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->dbtry("ALTER TABLE station_profile ADD COLUMN station_uuid varchar(36) DEFAULT NULL AFTER webadifrealtime");
|
||||
$this->dbtry("UPDATE station_profile SET station_uuid = UUID() WHERE station_uuid IS NULL");
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dbtry("ALTER TABLE station_profile DROP COLUMN station_uuid");
|
||||
}
|
||||
|
||||
function dbtry($what) {
|
||||
try {
|
||||
$this->db->query($what);
|
||||
} catch (Exception $e) {
|
||||
log_message("error", "Something gone wrong while altering station_uuid: ".$e." // Executing: ".$this->db->last_query());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,6 +160,7 @@ class Stations extends CI_Model {
|
||||
'webadifapikey' => xss_clean($this->input->post('webadifapikey', true)),
|
||||
'webadifapiurl' => 'https://qo100dx.club/api',
|
||||
'webadifrealtime' => xss_clean($this->input->post('webadifrealtime', true)),
|
||||
'station_uuid' => $this->db->query("SELECT UUID() as uuid")->row()->uuid,
|
||||
);
|
||||
|
||||
// Insert Records & return insert id //
|
||||
|
||||
@@ -234,7 +234,7 @@ class Stationsetup_model extends CI_Model {
|
||||
}
|
||||
|
||||
function list_all_locations() {
|
||||
$sql = "select dxcc_entities.end, station_profile.station_id, station_profile_name, station_gridsquare, station_city, station_iota, station_sota, station_callsign, station_power, station_dxcc, dxcc_entities.name as dxccname, dxcc_entities.prefix as dxccprefix, station_cnty, station_cq, station_itu, station_active, eqslqthnickname, state, county, station_sig, station_sig_info, qrzrealtime, station_wwff, station_pota, oqrs, oqrs_text, oqrs_email, webadifrealtime, clublogrealtime, clublogignore, hrdlogrealtime, creation_date, last_modified
|
||||
$sql = "select dxcc_entities.end, station_profile.station_id, station_profile_name, station_profile.hrdlog_username, station_gridsquare, station_city, station_iota, station_sota, station_callsign, station_power, station_dxcc, dxcc_entities.name as dxccname, dxcc_entities.prefix as dxccprefix, station_cnty, station_cq, station_itu, station_active, eqslqthnickname, state, county, station_sig, station_sig_info, qrzrealtime, station_wwff, station_pota, oqrs, oqrs_text, oqrs_email, webadifrealtime, clublogrealtime, clublogignore, hrdlogrealtime, creation_date, last_modified, station_uuid
|
||||
from station_profile
|
||||
join dxcc_entities on station_profile.station_dxcc = dxcc_entities.adif
|
||||
where user_id = ?";
|
||||
@@ -242,6 +242,7 @@ class Stationsetup_model extends CI_Model {
|
||||
$query = $this->db->query($sql, array($this->session->userdata('user_id')));
|
||||
|
||||
$result = $query->result();
|
||||
$this->load->model('user_options_model');
|
||||
|
||||
foreach($result as $location) {
|
||||
$options_object = $this->user_options_model->get_options('eqsl_default_qslmsg', array('option_name' => 'key_station_id', 'option_key' => $location->station_id))->result();
|
||||
@@ -254,6 +255,72 @@ class Stationsetup_model extends CI_Model {
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function save_location($dbdata, $optiondata) {
|
||||
// Make sure we have the needed fields
|
||||
if (empty($dbdata['station_profile_name']) || empty($dbdata['station_callsign'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if a location exists with same parameters
|
||||
$sql = "
|
||||
SELECT *
|
||||
FROM station_profile
|
||||
WHERE station_profile_name = ?
|
||||
AND station_callsign = ?
|
||||
AND station_gridsquare = ?
|
||||
AND station_city = ?
|
||||
AND station_iota = ?
|
||||
AND station_sota = ?
|
||||
AND state = ?
|
||||
AND station_cnty = ?
|
||||
AND station_dxcc = ?
|
||||
AND station_wwff = ?
|
||||
AND station_pota = ?
|
||||
AND station_sig = ?
|
||||
AND station_sig_info = ?
|
||||
AND user_id = ?;
|
||||
";
|
||||
|
||||
$query = $this->db->query($sql, [
|
||||
$dbdata['station_profile_name'],
|
||||
$dbdata['station_callsign'],
|
||||
$dbdata['station_gridsquare'],
|
||||
$dbdata['station_city'],
|
||||
$dbdata['station_iota'],
|
||||
$dbdata['station_sota'],
|
||||
$dbdata['state'],
|
||||
$dbdata['station_cnty'],
|
||||
$dbdata['station_dxcc'],
|
||||
$dbdata['station_wwff'],
|
||||
$dbdata['station_pota'],
|
||||
$dbdata['station_sig'],
|
||||
$dbdata['station_sig_info'],
|
||||
$this->session->userdata('user_id')
|
||||
]);
|
||||
|
||||
if ($query->num_rows() > 0) {
|
||||
// Location already exists
|
||||
return 0;
|
||||
} else {
|
||||
// Insert new location
|
||||
// Generate UUID if not provided
|
||||
if (empty($dbdata['station_uuid'])) {
|
||||
$dbdata['station_uuid'] = $this->db->query("SELECT UUID() as uuid")->row()->uuid;
|
||||
}
|
||||
|
||||
$this->db->insert('station_profile', $dbdata);
|
||||
$location_id = $this->db->insert_id();
|
||||
|
||||
if (!empty(trim($optiondata['eqsl_default_qslmsg']))) {
|
||||
$this->load->model('user_options_model');
|
||||
$this->user_options_model->set_option('eqsl_default_qslmsg', 'key_station_id', array($location_id => $optiondata['eqsl_default_qslmsg']));
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="container-fluid pt-3 ps-4 pe-4">
|
||||
<h2><?= $page_title ?></h2>
|
||||
|
||||
<?php if (!empty($locations)): ?>
|
||||
<div class="table-responsive mt-3">
|
||||
<table style="width:100%" class="table-sm table table-hover table-striped table-bordered table-condensed" id="qsoList">
|
||||
<thead>
|
||||
@@ -33,6 +33,7 @@
|
||||
<th>ClubLog realtime upload</th>
|
||||
<th>ClubLog Ignore</th>
|
||||
<th>HRDLog realtime upload</th>
|
||||
<th>HRDLog username</th>
|
||||
<th>Created</th>
|
||||
<th>Last Modified</th>
|
||||
</tr>
|
||||
@@ -72,6 +73,7 @@
|
||||
<td><?php echo $loc->clublogrealtime ? 'Yes' : 'No' ?></td>
|
||||
<td><?php echo $loc->clublogignore ? 'Yes' : 'No' ?></td>
|
||||
<td><?php echo $loc->hrdlogrealtime ? 'Yes' : 'No' ?></td>
|
||||
<td><?php echo $loc->hrdlog_username; ?></td>
|
||||
<td><?php echo $loc->creation_date; ?></td>
|
||||
<td><?php echo $loc->last_modified; ?></td>
|
||||
</tr>
|
||||
@@ -79,33 +81,117 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-info mt-3">No station locations found.</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
$('.table').DataTable({
|
||||
"pageLength": 25,
|
||||
responsive: false,
|
||||
ordering: true,
|
||||
"scrollY": window.innerHeight - 250,
|
||||
"scrollCollapse": true,
|
||||
"paging": false,
|
||||
"scrollX": true,
|
||||
"language": {
|
||||
url: getDataTablesLanguageUrl(),
|
||||
},
|
||||
dom: 'Bfrtip',
|
||||
buttons: [
|
||||
{
|
||||
extend: 'csv',
|
||||
className: 'mb-1 btn btn-sm btn-primary', // Bootstrap classes
|
||||
init: function(api, node, config) {
|
||||
$(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
|
||||
},
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
$('.table').DataTable({
|
||||
"pageLength": 25,
|
||||
responsive: false,
|
||||
ordering: true,
|
||||
"scrollY": window.innerHeight - 250,
|
||||
"scrollCollapse": true,
|
||||
"paging": false,
|
||||
"scrollX": true,
|
||||
"language": {
|
||||
url: getDataTablesLanguageUrl(),
|
||||
},
|
||||
dom: 'Bfrtip',
|
||||
buttons: [
|
||||
{
|
||||
extend: 'csv',
|
||||
className: 'mb-1 btn btn-sm btn-primary',
|
||||
init: function(api, node, config) {
|
||||
$(node).removeClass('dt-button').addClass('btn btn-primary');
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Export All Locations',
|
||||
className: 'mb-1 btn btn-sm btn-primary', // same Bootstrap style
|
||||
action: function(e, dt, node, config) {
|
||||
exportAllLocations();
|
||||
},
|
||||
init: function(api, node, config) {
|
||||
$(node).removeClass('dt-button').addClass('btn btn-primary');
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Import Locations',
|
||||
className: 'mb-1 btn btn-sm btn-primary',
|
||||
action: function(e, dt, node, config) {
|
||||
// Create a hidden file input (accept JSON)
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.accept = 'application/json';
|
||||
input.style.display = 'none';
|
||||
|
||||
input.addEventListener('change', function(event) {
|
||||
const file = event.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
const url = base_url + 'index.php/stationsetup/import_locations';
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
console.log("Import result:", result);
|
||||
showToast('Info', result.message || "Import completed successfully!", 'bg-info text-dark', 4000);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Import failed:", error);
|
||||
showToast('Error', 'Import failed. Check console for details.', 'bg-danger text-white', 5000);
|
||||
});
|
||||
});
|
||||
|
||||
document.body.appendChild(input);
|
||||
input.click(); // Trigger file chooser
|
||||
document.body.removeChild(input);
|
||||
},
|
||||
init: function(api, node, config) {
|
||||
$(node).removeClass('dt-button').addClass('btn btn-primary');
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
function exportAllLocations() {
|
||||
const url = base_url + 'index.php/stationsetup/export_locations';
|
||||
|
||||
fetch(url)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
showToast('Error', 'Network response was not ok (${response.status})', 'bg-danger text-white', 5000);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
// Convert JSON to string
|
||||
const jsonStr = JSON.stringify(data, null, 2);
|
||||
|
||||
// Create a downloadable blob
|
||||
const blob = new Blob([jsonStr], { type: "application/json" });
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = "locations.json";
|
||||
|
||||
// Trigger download
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
})
|
||||
.catch(error => {
|
||||
showToast('Error', 'Failed to export locations. Check console for details.', 'bg-danger text-white', 5000);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user