[Feature] Add filtering options to public gridsquare maps

copilot/fix-c1623248-9691-46e2-a4cc-7f8c39b3738b
Peter Goodhall 2025-08-19 17:28:24 +01:00 zatwierdzone przez GitHub
commit 6af65e6dbb
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
4 zmienionych plików z 306 dodań i 73 usunięć

Wyświetl plik

@ -20,6 +20,9 @@ class Visitor extends CI_Controller {
elseif($method == "satellites") {
$this->satellites($method);
}
elseif($method == "getGridsjs") {
$this->getGridsjs();
}
elseif($method == "search") {
$this->search($method);
}
@ -226,36 +229,88 @@ class Visitor extends CI_Controller {
$this->load->model('gridmap_model');
$data['page_title'] = "Satellite Gridsquare Map";
$data['page_title'] = "Public Gridsquare Map";
// Get available bands for this logbook
$location_list = "'".implode("','",$logbooks_locations_array)."'";
// Get bands (excluding satellites)
$bands_query = $this->db->query(
"SELECT distinct LOWER(`COL_BAND`) as `COL_BAND` FROM `".$this->config->item('table_name')."` WHERE station_id in (" . $location_list . ") AND COL_PROP_MODE != \"SAT\" ORDER BY COL_BAND"
);
$bands = array();
foreach($bands_query->result() as $row){
array_push($bands, strtoupper($row->COL_BAND));
}
// Check if satellites exist and add SAT band
$sat_query = $this->db->query(
"SELECT distinct LOWER(`COL_PROP_MODE`) as `COL_PROP_MODE` FROM `".$this->config->item('table_name')."` WHERE station_id in (" . $location_list . ") AND COL_PROP_MODE = \"SAT\""
);
if ($sat_query->num_rows() > 0) {
array_push($bands, 'SAT');
}
// Get available satellites
$sats_query = $this->db->query(
"SELECT distinct col_sat_name FROM ".$this->config->item('table_name')." WHERE station_id in (" . $location_list . ") and coalesce(col_sat_name, '') <> '' ORDER BY col_sat_name"
);
$sats_available = array();
foreach($sats_query->result() as $row){
array_push($sats_available, $row->col_sat_name);
}
// Get available modes
$modes_query = $this->db->query(
"SELECT distinct col_mode FROM ".$this->config->item('table_name')." WHERE station_id in (" . $location_list . ") and coalesce(col_mode, '') <> '' ORDER BY col_mode"
);
$modes = array();
foreach($modes_query->result() as $row){
if (!in_array($row->col_mode, $modes)) {
array_push($modes, $row->col_mode);
}
}
// Get submodes as well
$submodes_query = $this->db->query(
"SELECT distinct col_submode FROM ".$this->config->item('table_name')." WHERE station_id in (" . $location_list . ") and coalesce(col_submode, '') <> '' ORDER BY col_submode"
);
foreach($submodes_query->result() as $row){
if (!in_array($row->col_submode, $modes)) {
array_push($modes, $row->col_submode);
}
}
asort($modes);
$data['bands'] = $bands;
$data['sats_available'] = $sats_available;
$data['modes'] = $modes;
// Set default values for visitor (no user preferences)
$data['user_default_band'] = 'All';
$data['user_default_confirmation'] = '';
// Generate initial grid data (default to showing all bands)
$default_band = 'All';
$default_mode = 'All';
$default_sat = 'All';
$array_grid_2char = array();
$array_grid_4char = array();
$array_grid_6char = array();
$array_confirmed_grid_2char = array();
$array_confirmed_grid_4char = array();
$array_confirmed_grid_6char = array();
$grid_2char = "";
$grid_4char = "";
$grid_6char = "";
$grid_2char_confirmed = "";
$grid_4char_confirmed = "";
$grid_6char_confirmed = "";
// Get Confirmed LoTW & Paper Squares (non VUCC)
$query = $this->gridmap_model->get_band_confirmed('SAT', 'All', 'true', 'true', 'false', 'false', 'All', $logbooks_locations_array);
// Get initial data for "All" bands
$query = $this->gridmap_model->get_band_confirmed($default_band, $default_mode, 'false', 'false', 'false', 'false', $default_sat, $logbooks_locations_array);
if ($query && $query->num_rows() > 0)
{
foreach ($query->result() as $row)
{
$grid_2char_confirmed = strtoupper(substr($row->GRID_SQUARES,0,2));
$grid_4char_confirmed = strtoupper(substr($row->GRID_SQUARES,0,4));
if ($this->config->item('map_6digit_grids')) {
@ -267,30 +322,25 @@ class Visitor extends CI_Controller {
array_push($array_confirmed_grid_2char, $grid_2char_confirmed);
}
if(!in_array($grid_4char_confirmed, $array_confirmed_grid_4char)){
array_push($array_confirmed_grid_4char, $grid_4char_confirmed);
}
if ($this->config->item('map_6digit_grids')) {
if(!in_array($grid_6char_confirmed, $array_confirmed_grid_6char)){
array_push($array_confirmed_grid_6char, $grid_6char_confirmed);
}
}
}
}
// Get worked squares
$query = $this->gridmap_model->get_band('SAT', 'All', 'false', 'true', 'false', 'false', 'All', $logbooks_locations_array);
// Get worked squares (all bands by default)
$query = $this->gridmap_model->get_band($default_band, $default_mode, 'false', 'false', 'false', 'false', $default_sat, $logbooks_locations_array);
if ($query && $query->num_rows() > 0)
{
foreach ($query->result() as $row)
{
$grid_two = strtoupper(substr($row->GRID_SQUARES,0,2));
$grid_four = strtoupper(substr($row->GRID_SQUARES,0,4));
if ($this->config->item('map_6digit_grids')) {
@ -302,29 +352,25 @@ class Visitor extends CI_Controller {
array_push($array_grid_2char, $grid_two);
}
if(!in_array($grid_four, $array_grid_4char)){
array_push($array_grid_4char, $grid_four);
}
if ($this->config->item('map_6digit_grids')) {
if(!in_array($grid_six, $array_grid_6char)){
array_push($array_grid_6char, $grid_six);
}
}
}
}
$query_vucc = $this->gridmap_model->get_band_worked_vucc_squares('SAT', 'All', 'false', 'true', 'false', 'false', 'All', $logbooks_locations_array);
// Get VUCC squares (worked)
$query_vucc = $this->gridmap_model->get_band_worked_vucc_squares($default_band, $default_mode, 'false', 'false', 'false', 'false', $default_sat, $logbooks_locations_array);
if ($query && $query_vucc->num_rows() > 0)
if ($query_vucc && $query_vucc->num_rows() > 0)
{
foreach ($query_vucc->result() as $row)
{
$grids = explode(",", $row->COL_VUCC_GRIDS);
foreach($grids as $key) {
@ -336,7 +382,6 @@ class Visitor extends CI_Controller {
array_push($array_grid_2char, $grid_two);
}
if(!in_array($grid_four, $array_grid_4char)){
array_push($array_grid_4char, $grid_four);
}
@ -344,14 +389,13 @@ class Visitor extends CI_Controller {
}
}
// Confirmed Squares
$query_vucc = $this->gridmap_model->get_band_confirmed_vucc_squares('SAT', 'All', 'true', 'true', 'false', 'false', 'All', $logbooks_locations_array);
// Confirmed VUCC Squares
$query_vucc = $this->gridmap_model->get_band_confirmed_vucc_squares($default_band, $default_mode, 'false', 'false', 'false', 'false', $default_sat, $logbooks_locations_array);
if ($query && $query_vucc->num_rows() > 0)
if ($query_vucc && $query_vucc->num_rows() > 0)
{
foreach ($query_vucc->result() as $row)
{
$grids = explode(",", $row->COL_VUCC_GRIDS);
foreach($grids as $key) {
@ -363,7 +407,6 @@ class Visitor extends CI_Controller {
array_push($array_confirmed_grid_2char, $grid_2char_confirmed);
}
if(!in_array($grid_4char_confirmed, $array_confirmed_grid_4char)){
array_push($array_confirmed_grid_4char, $grid_4char_confirmed);
}
@ -450,4 +493,159 @@ class Visitor extends CI_Controller {
}
}
public function getGridsjs()
{
$slug = $this->security->xss_clean($this->input->post('slug'));
$band = $this->security->xss_clean($this->input->post('band'));
$mode = $this->security->xss_clean($this->input->post('mode'));
$sat = $this->security->xss_clean($this->input->post('sat'));
if (!$slug) {
header('Content-Type: application/json');
echo json_encode(array('error' => 'No slug provided'));
return;
}
$this->load->model('logbooks_model');
if(!$this->logbooks_model->public_slug_exists($slug)) {
header('Content-Type: application/json');
echo json_encode(array('error' => 'Invalid slug'));
return;
}
$logbook_id = $this->logbooks_model->public_slug_exists_logbook_id($slug);
if($logbook_id == false) {
header('Content-Type: application/json');
echo json_encode(array('error' => 'Invalid logbook'));
return;
}
// Get associated station locations for mysql queries
$logbooks_locations_array = $this->logbooks_model->list_logbook_relationships($logbook_id);
if (!$logbooks_locations_array) {
header('Content-Type: application/json');
echo json_encode(array('error' => 'No station locations'));
return;
}
$this->load->model('gridmap_model');
$array_grid_2char = array();
$array_grid_4char = array();
$array_grid_6char = array();
$array_grid_2char_confirmed = array();
$array_grid_4char_confirmed = array();
$array_grid_6char_confirmed = array();
// For public visitor, we don't show QSL confirmations, so set all to false
$query = $this->gridmap_model->get_band_confirmed($band, $mode, 'false', 'false', 'false', 'false', $sat, $logbooks_locations_array);
if ($query && $query->num_rows() > 0) {
foreach ($query->result() as $row) {
$grid_2char_confirmed = strtoupper(substr($row->GRID_SQUARES,0,2));
$grid_4char_confirmed = strtoupper(substr($row->GRID_SQUARES,0,4));
$grid_6char_confirmed = strtoupper(substr($row->GRID_SQUARES,0,6));
// Check if 2 Char is in array
if(!in_array($grid_2char_confirmed, $array_grid_2char_confirmed)){
array_push($array_grid_2char_confirmed, $grid_2char_confirmed);
}
if(!in_array($grid_4char_confirmed, $array_grid_4char_confirmed)){
array_push($array_grid_4char_confirmed, $grid_4char_confirmed);
}
if(!in_array($grid_6char_confirmed, $array_grid_6char_confirmed)){
array_push($array_grid_6char_confirmed, $grid_6char_confirmed);
}
}
}
$query = $this->gridmap_model->get_band($band, $mode, 'false', 'false', 'false', 'false', $sat, $logbooks_locations_array);
if ($query && $query->num_rows() > 0) {
foreach ($query->result() as $row) {
$grid_two = strtoupper(substr($row->GRID_SQUARES,0,2));
$grid_four = strtoupper(substr($row->GRID_SQUARES,0,4));
$grid_six = strtoupper(substr($row->GRID_SQUARES,0,6));
// Check if 2 Char is in array
if(!in_array($grid_two, $array_grid_2char)){
array_push($array_grid_2char, $grid_two);
}
if(!in_array($grid_four, $array_grid_4char)){
array_push($array_grid_4char, $grid_four);
}
if(!in_array($grid_six, $array_grid_6char)){
array_push($array_grid_6char, $grid_six);
}
}
}
$query_vucc = $this->gridmap_model->get_band_worked_vucc_squares($band, $mode, 'false', 'false', 'false', 'false', $sat, $logbooks_locations_array);
if ($query_vucc && $query_vucc->num_rows() > 0) {
foreach ($query_vucc->result() as $row) {
$grids = explode(",", $row->COL_VUCC_GRIDS);
foreach($grids as $key) {
$grid_two = strtoupper(substr($key,0,2));
$grid_four = strtoupper(substr($key,0,4));
// Check if 2 Char is in array
if(!in_array($grid_two, $array_grid_2char)){
array_push($array_grid_2char, $grid_two);
}
if(!in_array($grid_four, $array_grid_4char)){
array_push($array_grid_4char, $grid_four);
}
}
}
}
// // Confirmed Squares
$query_vucc = $this->gridmap_model->get_band_confirmed_vucc_squares($band, $mode, 'false', 'false', 'false', 'false', $sat, $logbooks_locations_array);
if ($query_vucc && $query_vucc->num_rows() > 0) {
foreach ($query_vucc->result() as $row) {
$grids = explode(",", $row->COL_VUCC_GRIDS);
foreach($grids as $key) {
$grid_2char_confirmed = strtoupper(substr($key,0,2));
$grid_4char_confirmed = strtoupper(substr($key,0,4));
// Check if 2 Char is in array
if(!in_array($grid_2char_confirmed, $array_grid_2char_confirmed)){
array_push($array_grid_2char_confirmed, $grid_2char_confirmed);
}
if(!in_array($grid_4char_confirmed, $array_grid_4char_confirmed)){
array_push($array_grid_4char_confirmed, $grid_4char_confirmed);
}
}
}
}
$data['grid_2char_confirmed'] = ($array_grid_2char_confirmed);
$data['grid_4char_confirmed'] = ($array_grid_4char_confirmed);
$data['grid_6char_confirmed'] = ($array_grid_6char_confirmed);
$data['grid_2char'] = ($array_grid_2char);
$data['grid_4char'] = ($array_grid_4char);
$data['grid_6char'] = ($array_grid_6char);
header('Content-Type: application/json');
echo json_encode($data);
}
}

Wyświetl plik

@ -46,7 +46,6 @@
<h2><?php echo $page_title; ?></h2>
<?php if ($visitor == false) { ?>
<form class="d-flex align-items-center">
<label class="my-1 me-2" for="band"><?php echo lang('gridsquares_band'); ?></label>
<select class="form-select my-1 me-sm-2 w-auto" id="band">
@ -75,12 +74,19 @@
<option value="All"><?php echo lang('general_word_all')?></option>
<?php
foreach($modes as $mode){
if ($mode->submode ?? '' == '') {
if (is_object($mode)) {
// Handle object format (from gridmap_model->get_worked_modes())
if ($mode->submode ?? '' == '') {
echo '<option value="' . $mode->mode . '">' . strtoupper($mode->mode) . '</option>'."\n";
}
} else {
// Handle simple string format (from visitor implementation)
echo '<option value="' . $mode . '">' . strtoupper($mode) . '</option>'."\n";
}
}
?>
</select>
<?php if ($visitor == false) { ?>
<label class="my-1 me-2"><?php echo lang('gridsquares_confirmation'); ?></label>
<div>
<div class="form-check-inline">
@ -116,11 +122,11 @@
<label class="form-check-label" for="qrz">QRZ.com</label>
</div>
</div>
<?php } ?>
<button id="plot" type="button" name="plot" class="btn btn-primary me-1 ld-ext-right ld-ext-right-plot" onclick="gridPlot(this.form,<?php echo $visitor == true ? "true" : "false"; ?>)"><?php echo lang('gridsquares_button_plot'); ?><div class="ld ld-ring ld-spin"></div></button>
<button id="clear" type="button" name="clear" class="btn btn-primary me-1 ld-ext-right ld-ext-right-clear" onclick="clearMarkers()"><?php echo lang('gridsquares_button_clear_markers'); ?><div class="ld ld-ring ld-spin"></div></button>
</form>
<?php } ?>
<?php if($this->session->flashdata('message')) { ?>
<!-- Display Message -->

Wyświetl plik

@ -57,53 +57,37 @@
<?php if ($this->uri->segment(2) == "satellites") { ?>
<script type="text/javascript" src="<?php echo base_url();?>assets/js/leaflet/L.MaidenheadColoured.js"></script>
<script type="text/javascript" src="<?php echo base_url();?>assets/js/leaflet/geocoding.js"></script>
<script type="text/javascript" src="<?php echo base_url();?>assets/js/leaflet/L.MaidenheadColouredGridMap.js"></script>
<script type="text/javascript" src="<?php echo base_url();?>assets/js/sections/gridmap.js?"></script>
<script>
var layer = L.tileLayer('<?php echo $this->optionslib->get_option('option_map_tile_server');?>', {
maxZoom: 18,
attribution: '<?php echo $this->optionslib->get_option('option_map_tile_server_copyright');?>',
id: 'mapbox.streets'
});
var map = L.map('gridsquare_map', {
layers: [layer],
center: [19, 0],
zoom: 2,
fullscreenControl: true,
fullscreenControlOptions: {
position: 'topleft'
},
});
var printer = L.easyPrint({
tileLayer: layer,
sizeModes: ['Current'],
filename: 'myMap',
exportOnly: true,
hideControlContainer: true
}).addTo(map);
// Set up global variables for gridmap functionality
var grid_two = <?php echo $grid_2char; ?>;
var grid_four = <?php echo $grid_4char; ?>;
var grid_six = <?php echo $grid_6char; ?>;
var grid_two_count = grid_two.length;
var grid_four_count = grid_four.length;
var grid_six_count = grid_six.length;
var grid_two_confirmed = <?php echo $grid_2char_confirmed; ?>;
var grid_four_confirmed = <?php echo $grid_4char_confirmed; ?>;
var grid_six_confirmed = <?php echo $grid_6char_confirmed; ?>;
var grid_two_confirmed_count = grid_two_confirmed.length;
var grid_four_confirmed_count = grid_four_confirmed.length;
var grid_six_confirmed_count = grid_six_confirmed.length;
// Set up other required global variables
var jslayer = '<?php echo $this->optionslib->get_option('option_map_tile_server');?>';
var jsattribution = '<?php echo $this->optionslib->get_option('option_map_tile_server_copyright');?>';
var gridsquares_gridsquares = "<?php echo lang('gridsquares_gridsquares'); ?>";
var gridsquares_gridsquares_confirmed = "<?php echo lang('gridsquares_gridsquares_confirmed'); ?>";
var gridsquares_gridsquares_not_confirmed = "<?php echo lang('gridsquares_gridsquares_not_confirmed'); ?>";
var gridsquares_gridsquares_total_worked = "<?php echo lang('gridsquares_gridsquares_total_worked'); ?>";
var visitor = true;
var type = "worked";
var maidenhead = L.maidenhead().addTo(map);
// Initialize the map when document is ready
$(document).ready(function() {
// Use the plot function from gridmap.js to render the initial map
plot(visitor, grid_two, grid_four, grid_six, grid_two_confirmed, grid_four_confirmed, grid_six_confirmed);
});
<?php if ($this->uri->segment(1) == "gridsquares" && $this->uri->segment(2) == "band") { ?>

Wyświetl plik

@ -41,6 +41,16 @@ function gridPlot(form, visitor=true) {
ajax_url = site_url + '/gridmap/getGridsjs';
}
// If visitor context, get the slug from the URL and use visitor endpoint
if (visitor === true) {
var pathParts = window.location.pathname.split('/');
var slugIndex = pathParts.indexOf('satellites');
if (slugIndex !== -1 && pathParts[slugIndex + 1]) {
var slug = pathParts[slugIndex + 1];
ajax_url = site_url + '/visitor/getGridsjs';
}
}
if (visitor != true) {
$.ajax({
url: ajax_url,
@ -73,7 +83,42 @@ function gridPlot(form, visitor=true) {
},
});
} else {
plot(visitor, grid_two, grid_four, grid_six, grid_two_confirmed, grid_four_confirmed, grid_six_confirmed);
// Visitor context - use AJAX to get filtered data
var pathParts = window.location.pathname.split('/');
var slugIndex = pathParts.indexOf('satellites');
if (slugIndex !== -1 && pathParts[slugIndex + 1]) {
var slug = pathParts[slugIndex + 1];
$.ajax({
url: ajax_url,
type: 'post',
data: {
slug: slug,
band: $("#band").val(),
mode: $("#mode").val(),
sat: $("#sats").val(),
},
success: function (data) {
console.log(data);
$('.cohidden').show();
$(".ld-ext-right-plot").removeClass('running');
$(".ld-ext-right-plot").prop('disabled', false);
$('#plot').prop("disabled", false);
grid_two = data.grid_2char;
grid_four = data.grid_4char;
grid_six = data.grid_6char;
grid_two_confirmed = data.grid_2char_confirmed;
grid_four_confirmed = data.grid_4char_confirmed;
grid_six_confirmed = data.grid_6char_confirmed;
plot(visitor, grid_two, grid_four, grid_six, grid_two_confirmed, grid_four_confirmed, grid_six_confirmed);
},
error: function (data) {
console.error('Error loading visitor grid data:', data);
},
});
} else {
// Fallback: use predefined grid data if available
plot(visitor, grid_two, grid_four, grid_six, grid_two_confirmed, grid_four_confirmed, grid_six_confirmed);
}
};
}