Commit graph

5890 commits

Author SHA1 Message Date
Peter Goodhall
e5cd953d2d Add migration 264 tagging v2.8.11
Bump migration_version to 264 and add Migration_tag_2_8_11. The new migration updates the 'options' table to set version = '2.8.11' and resets users' 'version_dialog' confirmed flag to 'false' to trigger the version info dialog. The down() method reverts the stored version back to '2.8.10'.
2026-04-01 12:44:53 +01:00
Peter Goodhall
8fcbfafbc8 Allow overriding displayed callsign in widgets
Add an optional $display_callsign parameter to on_air and on_air_image so embedders can show a different callsign than the one used to look up the user (e.g., /widgets/on_air/M0ABC/GB2XXX). Update embed examples and use the display_callsign when provided (sanitised with xss_clean and strtoupper) while preserving the original lookup behavior.
2026-03-30 10:45:51 +01:00
Peter Goodhall
3be655e64d Add migration to convert notes to utf8mb4
Bump migration_version to 263 and add Migration_notes_utf8mb4_columns. The new migration converts the notes table to use utf8mb4 with utf8mb4_unicode_ci to support emoji and other 4-byte characters; down() reverts the table back to utf8 with utf8_general_ci.
2026-03-29 23:07:32 +01:00
Peter Goodhall
7d442c8116 Add on_air_image SVG badge endpoint
Introduce Widgets::on_air_image(callsign) — an embeddable SVG "on air" status badge (usage: /widgets/on_air_image/YOURCALL). The method validates the callsign, looks up the user and their recent radio status via user_model and cat, builds a status string (including SAT, frequency+mode, or "qrt" if offline), and chooses a badge color. It computes dynamic badge widths using an approximate Verdana character width, sanitizes text for XML output, includes accessible title/aria-label, and returns the SVG with Content-Type image/svg+xml and Cache-Control: no-cache, max-age=60. Errors are shown for missing callsign or unknown user.
2026-03-29 14:25:41 +01:00
Peter Goodhall
b6a1eb830c Add embeddable on-air widget
Introduce an embeddable "on air" status widget. Adds Widgets::on_air controller action to lookup a user by callsign, sanitize input, and render a new widgets/on_air view (iframe-friendly). Adds Cat::recent_status_by_user_id to fetch recent CAT entries (last 15 minutes) for public display. View shows ON AIR/ QRT badges, radio/satellite details, and includes auto-refresh and minimal styling; usage: /widgets/on_air/YOURCALL.
2026-03-29 14:24:26 +01:00
Peter Goodhall
9bbc58d805 Use COL_VUCC_GRIDS as fallback for grids
Prefer COL_GRIDSQUARE when present and fall back to COL_VUCC_GRIDS when building grid information. Added COL_VUCC_GRIDS to select lists in Note model queries and updated Logbook_model to set plot HTML to VUCC grids if gridsquare is missing. Also updated the public station diary view to display VUCC grids in the table when COL_GRIDSQUARE is empty. Files changed: Logbook_model.php, Note.php, public_index.php.
2026-03-29 14:12:25 +01:00
Peter Goodhall
0b272dc1c8 Improve highlight DX selection using gridsquares
Expand highlight DX query to include QSOs with gridsquares/VUCC when stored distance is missing. Join station_profile to access station_gridsquare, select up to 50 candidate QSOs, prefer stored COL_DISTANCE but compute distances via the Qra library when needed, and pick the farthest candidate (rounded to int). Apply the same logic for daily and date-range queries and preserve the satellite-only filter. Replaces the previous strict COL_DISTANCE>0 single-row lookup to avoid excluding valid DXs derivable from grids.
2026-03-29 14:09:31 +01:00
Peter Goodhall
950f5a37b0 Improve DX Cluster status badge and JS state handling
Replace plain text status with a badge containing an icon and tooltip in the DX Cluster tab (increase font-size to 0.85rem and set cursor to default). Update setStatus() to drive the icon class and tooltip text via a stateMap for common states (Connected, Connecting..., Reconnecting..., Error, Disconnected), set the badge class, and update both title and data-bs-original-title for Bootstrap tooltip compatibility. Adds a fallback for unknown states.
2026-03-29 14:02:23 +01:00
Peter Goodhall
0f62a7178a Add client-side QRA utils and use in QSO
Introduce a frontend QRA utilities module and switch QSO locator/bearing/distance logic to run client-side. Added assets/js/qra-utils.js (ported from the PHP Qra library), injected measurement_base and station_gridsquares into the QSO view, and updated application/controllers/Qso.php to provide the measurement_base for the frontend. Footer now loads qra-utils.js before qso.js. Modified assets/js/sections/qso.js to debounce locator input, place map markers from local grid→lat/lng math, and compute bearing/distance via QraUtils (removes several AJAX calls to server endpoints). This reduces server round-trips and keeps frontend behavior consistent with the PHP implementation.
2026-03-29 13:57:36 +01:00
Peter Goodhall
107bbb3572 Use sanitized $manual variable instead of $_GET
Read and cast the manual mode once into $manual using $this->input->get(...) with a default of 0, and replace all direct $_GET['manual'] usages with $manual. Updates include the JavaScript qso_manual value, form action and resetTimers call, and multiple conditional checks and disabled attributes to improve input handling and consistency. Also ensures EOF newline is present.
2026-03-29 13:47:54 +01:00
Peter Goodhall
cee6cd2def Refactor DXCC checks; add CW RBN lock UI
Replace inline DB queries in Dxcluster with a new Logbook_model::check_if_dxcc_worked_in_logbook method to centralize DXCC existence checks (per-band and overall). Remove several debug log statements from Dxcluster. Add client-side logic in dxcluster and qso views to enforce a CW↔RBN rule: when mode is 'cw' the "hide RBN" option is forced off and the checkbox is disabled (and restored when leaving CW), and apply that lock on load and mode changes. Also disable track-band when the user manually changes band in the QSO cluster UI.
2026-03-29 13:37:16 +01:00
Peter Goodhall
3d9e466b76 Add mode and new DXCC filters; extract DX utils
Add UI controls for mode and "New DXCC" filtering to the DX Cluster and QSO views, persist selections in localStorage, and wire them into existing spot filtering and rendering logic (including auto-unhide of RBN when CW is selected). Extract shared helper functions into a new assets/js/dxcluster-utils.js (DXCluster) providing isRbnSpot, getBandFromFrequency, detectModeFromFrequency, and detectMode, and update views to use these helpers. Also adjust badge logic to prioritize truly new DXCC, include the new script, and ensure spots are held until worked status is known for new/DXCC-band filtering.
2026-03-29 11:31:31 +01:00
Peter Goodhall
fab643fe5d Preserve pagination when redrawing DataTable
Change DataTables draw() call to draw(false) so the table is redrawn without resetting the current page. This keeps the user's pagination position after updates in application/views/qso/index.php.
2026-03-28 14:11:58 +00:00
Peter Goodhall
60fdf5a57b Send QSY command to selected radio
When a spot is selected on the QSO page, if a radio is chosen (radio != '0') the code now posts a QSY request to the dxcluster/qsy endpoint. The frequency is converted to MHz with 3 decimals and included as radio_id and frequency in a JSON body; if the spot is from RBN and marked CW the mode='CW' is also sent. The fetch is non-blocking and errors are silently ignored. This brings the QSO page behavior in line with the main DX Cluster page by automatically tuning a selected radio to the spotted frequency.
2026-03-28 10:39:14 +00:00
Peter Goodhall
a47e691db7 Fix RBN spot detection regex
Restrict RBN spot detection to skimmers that end with a literal '#' after the callsign. Previously the code matched hyphen followed by '#' or digits (/\-[#\d]+$/), which could misclassify numeric SSIDs like '-1' as RBN spots. The check now matches hyphen + one or more literal '#' characters (/\-#+$/) and simplifies trimming by removing the temporary uppercase variable.
2026-03-27 22:38:52 +00:00
Peter Goodhall
6a9a63297c Tighten RBN detection and optimize table render
Refine RBN skimmer detection and avoid unnecessary DOM redraws when the DX Cluster tab is hidden. isRbn now requires a literal '#' suffix rather than any trailing digits to prevent false positives. renderTable skips re-rendering if the cluster pane is not active, and the tab-visibility handler now calls renderTable before syncing the band filter and adjusting column widths so spots received while hidden are shown when the tab becomes visible.
2026-03-27 22:37:59 +00:00
Peter Goodhall
5fc7db65eb Add 'Track Band' option to cluster view
Add a 'Track Band' checkbox to the cluster controls and wire up state and persistence. Introduces a trackBand flag (default false), stores the setting in localStorage ('cloudlog_clusterTrackBand'), restores the state on init, and listens for changes to enable/disable band tracking. When disabled the band filter is reset to 'all'; when enabled it syncs the cluster band from the selected radio. Also prevents syncBandFromRadio from running when tracking is off.
2026-03-27 22:32:11 +00:00
Peter Goodhall
ac23397727 Add DX Cluster tab to QSO interface
Introduce a DX Cluster tab to the QSO view and user settings. This change:

- Enables a new qso_form option 'dxcluster_tab' in controllers (Qso.php, User.php) so the tab can be toggled per-user.
- Adds a user preference toggle in the user edit view to show/hide the DX Cluster tab.
- Implements the DX Cluster UI in the QSO index view: tab button, controls (band select, hide RBN), spot table and click-to-fill behavior.
- Adds client-side JS to manage a WebSocket to wss://dxc.cloudlog.org, maintain and render recent spots in a DataTable, persist filter preferences, sync band selection with the QSO form/radio, and batch-check worked status via the dxcluster/check_worked endpoint.

Files changed: application/controllers/Qso.php, application/controllers/User.php, application/views/qso/index.php, application/views/user/edit.php.
2026-03-27 22:29:25 +00:00
Peter Goodhall
3ca2478553 Use DOMContentLoaded and guard selectize
Replace jQuery $(function() {}) with document.addEventListener('DOMContentLoaded') in the QSO view and harden selectize usage in assets/js/sections/qso.js. Add existence checks (for elements and selectize instances) before accessing .selectize to avoid null/undefined dereferences, and consolidate selectize clearing logic. These changes improve robustness when selectize or jQuery readiness assumptions aren't met and prevent runtime errors.
2026-03-27 21:40:23 +00:00
Peter Goodhall
70f5c81b29 Respect hidden DOK field and guard Selectize
Always render the DOK field wrapper but mark it with data-user-hidden when the field is disabled for the user, and make toggleDokField skip showing the field in that case. Add defensive checks around Selectize accesses in assets/js/sections/qso.js (ensure $select[0] exists and dok_selectize is non-null before calling methods) to avoid JS errors when the DOK input is absent or not initialized. Changes touch application/views/qso/index.php and assets/js/sections/qso.js to prevent runtime errors and correctly honor user-hidden DOK configuration.
2026-03-27 19:34:24 +00:00
Peter Goodhall
0e631c2de1 Trigger DXCC change handlers on programmatic updates
Call toggleDokField()/toggleUsaFields() on jQuery ready and ensure programmatic updates to #dxcc_id fire change handlers. Replaced the previous DOMContentLoaded init with a jQuery $(function()) call to initialise the toggle state, added .trigger('change') where #dxcc_id is set programmatically, and invoke the toggle functions from the dxcc change handler to keep UI fields in sync.
2026-03-27 18:18:17 +00:00
Peter Goodhall
20570ba343 Add configurable QSO form field visibility
Introduce per-user visibility settings for QSO form fields and tabs. Load qso_form options in QSO and User controllers (with sensible defaults), apply them to the qso view to conditionally render fields/tabs, and save changes from the user edit form. Add a QSO Form accordion in user/edit.php exposing switches for each field/tab, update user save logic to persist each option, and include client-side JS in qso/index.php to toggle USA state/county and DOK fields based on DXCC selection. Files changed: application/controllers/Qso.php, application/controllers/User.php, application/views/qso/index.php, application/views/user/edit.php.
2026-03-27 18:11:22 +00:00
Peter Goodhall
1fe8f10c02 Relocate callsign badges and simplify redraw
Move the small badge elements (callsign_info, locator_info_contest_dxcc, distance_contest_dxcc) out of the callsign input column and into a new row below the distance field (div#callsign-badge-row) with a min-height to preserve layout. In contesting.js, replace table.columns.adjust().draw(false) with table.draw(false) in updateTableColumns to avoid an extra column adjustment and reduce redraw overhead.
2026-03-27 17:39:32 +00:00
Peter Goodhall
dce3127eca Improve contest UI and DataTable behavior
Rework contest QSO form layout and add collapsible panels for session settings and extra fields (name/comment/copy-exchange). Add prominent reset/save buttons, inline chevrons to indicate collapse state, and a logbook search input. In assets/js/sections/contesting.js ensure DataTables are destroyed before DOM updates, initialize DataTable with a compact dom, preserve initial search from the new logbook search field, add a keyup handler to drive table filtering, and fix column render targets/padding. Also remove a redundant search/order call after logging a QSO to avoid duplicate operations.
2026-03-27 16:32:15 +00:00
Peter Goodhall
3267413685 Add contest stats card and dupe checks
Add a contest stats card to the contesting view and implement client-side logic to compute and display session QSOs, per-band counts, and recent rate. Hide the callsign suggestion box by default and show/hide it based on lookup results; add a debounced duplicate-worked check while typing and visual success/error styling on the callsign input. Mark duplicate QSOs in the table (table-warning) by counting identical call|band|mode entries, and add updateTableColumns/updateContestStats helpers to toggle DataTable columns by exchange type and refresh contest stats when the QSO table is rebuilt. Also include small resets to clear suggestion UI and styling when fields are reset.
2026-03-27 16:10:39 +00:00
Peter Goodhall
9d90724eba Add migration 262 and fix terminator tiling
Bump migration version to 262 and add Migration_tag_2_8_10 which updates the stored app version to 2.8.10 and forces the version info dialog by resetting the user option. The migration includes a down() to revert the version to 2.8.9. Also update L.Terminator.js to generate three longitude-shifted polygon copies (offsets -360, 0, +360) so the night/day terminator overlay tiles correctly across world copies when the map is zoomed out.
2026-03-27 11:11:46 +00:00
Peter Goodhall
c0185f7698 Split ARRL VHF band option into two items
Replace a single long combined option for ARRL VHF with two separate select options. The previous option that used the lang() helper was changed to two options with values "VHF-3-BAND" and "VHF-FM-ONLY" and labels "VHF-3-BAND (ARRL VHF)" and "VHF-FM-ONLY (ARRL VHF)" to improve clarity and better match expected Cabrillo category values.
2026-03-27 00:06:12 +00:00
Peter Goodhall
4c1dd7a42d Add Cabrillo export modal & format improvements
Add a full Cabrillo export workflow and harden Cabrillo/QSO formatting. Introduces a modal UI to export contest logs (new button + modal form with fields for location, category time, operators, club, soapbox, date range and other Cabrillo categories). Controller updates pass the new fields to the export action. Cabrilloformat library extended to accept and emit LOCATION and CATEGORY-TIME, improve header field ordering and presence checks, map ADIF modes to the five Cabrillo modes (CW/PH/FM/RY/DG), fix a band label (2.4G -> 2.3G), and emit placeholders for missing received exchanges to preserve column alignment. Contesting_model: more robust date parsing with UTC fallback, ensure session QSO marker only persists when timestamp valid, and build start timestamp when LIVE mode omits start_date/start_time. Frontend JS: setSession() now returns the ajax promise so callers can await it; several callers updated to await setSession and re-fetch session data before refreshing the QSO table; restore full table search on callsign blur and when suggestions are cleared. Misc: small form/input fixes (club field type, default overlay option) and additional server-supplied data loaded into the contesting view (active station id, contest session, station profile). These changes add required Cabrillo fields for certain contests and make exports and session handling more reliable.
2026-03-27 00:04:21 +00:00
Peter Goodhall
f9941cc021 Update terminator styling and defaults
Adjust terminator/greyline visual style and default options. Changed colors to #4a6fa5 (stroke) and #001f3f (fill), increased stroke weight to 1.5, lowered fillOpacity to 0.18, and changed resolution from 2 to 1. These edits were applied both where the greyline is created in the footer view and in the L.Terminator default options to keep behavior and appearance consistent.
2026-03-26 22:45:51 +00:00
Peter Goodhall
bcae0c8782 Add optional map greyline layer (terminator)
Add a day/night greyline (terminator) overlay to the dashboard map.

- New assets/js/leaflet/L.Terminator.js: a Leaflet polygon plugin that computes the solar terminator for a given time and exposes L.terminator().
- Load the terminator script in the footer and register a Greyline overlay layer with start/stop interval updates (refreshes every minute). Updates are managed when the overlay is added/removed or when the map unloads to avoid orphaned timers.
- Expose the greyline as a toggleable overlay in the map layer control and add markers to a dedicated markersLayer overlay (instead of adding them directly to the map).
- Add a user preference checkbox to application/views/user/edit.php (Enable Dashboard Map Greyline Layer) and wire saving/reading of the dashboard_map_greyline option in application/controllers/User.php and application/controllers/Dashboard.php. Default behavior is enabled when not set.

This change lets users enable/disable the visual day/night terminator on the dashboard map and ensures proper lifecycle handling for updates and marker layering.
2026-03-26 22:39:04 +00:00
Peter Goodhall
d847e4819e Add pagination and DXCC tab to previous QSOs
Implement server-side pagination for previous contacts and add a DXCC Summary tab. Controller Qso now uses last_custom_paginated and exposes total_rows/total_pages/current_page/limit. Logbook_model gained last_custom_paginated and last_custom_count to support paged queries. The previous_contacts view was updated with HTMX pagination controls and wrapping for a scrollable table; qso/index was refactored to a tabbed UI (Previous Contacts / DXCC Summary). Lookup result display was improved: responsive table, sticky header, consolidation of LSB/USB into SSB and filtering out empty modes. JS and CSS updates load DXCC HTML into the new tab, hide legacy dxccsummary elements, and add form reset / Escape handling to return focus to the previous contacts tab.
2026-03-26 22:26:47 +00:00
Peter Goodhall
36757e3e34 Add option to count satellite QSOs in DXPeditions
Introduce a user preference to treat satellite QSOs as "worked" for DXPedition status and wire it through the UI, controller, and model. Changes: add dashboard_dxpedition_sat_worked default and POST handling in User controller, add checkbox to user settings view to toggle the option, update Workabledxcc_model to optionally include satellite results when computing workedBefore via a new shouldIncludeSatelliteWorked() helper, and tweak upcoming_dxccs view styling and row classes to visually indicate worked vs needed DXPeditions. This makes DXPedition cards respect users' preference for counting satellite contacts.
2026-03-26 15:00:56 +00:00
Peter Goodhall
10ce6d1b7d Use 'Unknown' for placeholder callsigns
Replace dash placeholder with the string "Unknown" for DXpedition callsign display. The Workabledxcc_model::normalize method now returns "Unknown" for empty or placeholder patterns (e.g. F/H, M/S). The upcoming_dxccs view was updated to default to and check for "Unknown" when rendering callsigns and tooltips so the UI shows a clearer, consistent placeholder.
2026-03-26 14:44:23 +00:00
Peter Goodhall
ec5b90017f Normalize DXped callsigns, add paginated UI
Add normalizeDxpedCallsign() to Workabledxcc_model and use it in the controller and model to standardize/replace placeholder callsigns (e.g. F/H, M/S) with '-'. Improve week filtering and date handling: set explicit times for start/end of week and records, use overlap logic to include DXpeditions that intersect the week, and compute daysLeft with proper past/last-day labeling. Revamp upcoming_dxccs view: implement client-side pagination, page size, prev/next controls, escaped tooltips, and graceful display for placeholder callsigns; add a link to the full list. These changes improve display consistency and UI usability.
2026-03-26 14:36:29 +00:00
Peter Goodhall
6e43503116 Enforce unique callsigns and protect last admin
Add callsign uniqueness checks and prevent demotion of the last admin. Introduces ECALLSIGNEXISTS and ELASTADMIN constants, new model methods (exists_by_callsign, count_admin_users, would_remove_last_admin) and integrates checks into add/update flows to return appropriate error codes. Update User controller to add validation callbacks (check_unique_callsign, check_last_admin_role) and wire errors into multiple user actions. Update signup/edit views to display callsign and usertype validation feedback using Bootstrap invalid-feedback and improve alert layout.
2026-03-26 14:22:02 +00:00
Peter Goodhall
294044ac28 Support compound callsign matching and base extraction
Handle compound callsigns (e.g. F/MM9SQL/P) when looking up call history and database records. Added extract_base_callsign() to normalize and extract the longest segment of a slash-separated callsign, updated controller lookup to fall back to the base callsign and to skip empty rows, and tightened matching logic to accept either the full input or its base call. Updated model WHERE clause to match normalized COL_CALL against exact, first, middle, or last slash-separated segments (with Ø→0 normalization) to ensure compound variants are found.
2026-03-26 13:07:25 +00:00
Peter Goodhall
df8dc163ff Add reverse SIG bulk remove and input validation
Validate and harden SIG handling across controllers and views. Awards: trim and validate requested SIG type, guard against empty types and wrap SIG data loading in try/catch with error logging and user notice. Callhistory: tighten input trimming and validation for proposed SIG info, reject proposals without membership numbers and enforce per-organization SIG-info rules (e.g. numeric for CWOPS). Add scan_remove action to perform reverse/bulk SIG clears for matched QSOs, and filter/validate batch changes before applying. Improve CSV/header parsing by normalizing header keys, aligning rows to headers (handles N1MM !!Order!! cases), extracting exch1 robustly, and adding helpers (looks_like_callsign, is_valid_sig_info_for_organization). View: add Reverse Bulk SIG Update UI, confirmation modal and JS helpers, and convert several forms to use JS-driven confirm dialogs. Misc: various trimming/safety fixes and UX messages.
2026-03-26 10:40:39 +00:00
Peter Goodhall
5c4106f068 Refactor callhistory preview DataTable init
Wrap preview table script in an IIFE and move initialization into initCallhistoryPreviewTable(). Add guards to wait/retry until jQuery and DataTables are available, prevent double-initialization, and defer startup until window load. Preserve selection helpers (select/deselect, check-all) but scope them to the DataTable instance, update selected count handling, and validate on submit (alert + prevent submit when no rows selected). Overall changes reduce race conditions and make the preview table initialization more robust.
2026-03-24 23:48:11 +00:00
Peter Goodhall
7ca3007398 Increase call history page length and paging
Set DataTables default pageLength to 100 for the call history preview table, add a lengthMenu with options [25, 50, 100, 250, All], and enable full_numbers pagingType to improve navigation when viewing larger result sets.
2026-03-24 23:45:45 +00:00
Peter Goodhall
ffa20deddf Submit selected changes as JSON
Switch client/server to send selected row changes as a JSON payload. The view now renders checkboxes with data-* attributes (instead of multiple named hidden inputs) and includes a hidden changes_json field. JS collects checked rows into an array, serializes it to changes_json on submit, and adds helpers (getAllRowChecks, updated select/deselect logic and validation). The controller now accepts changes_json (JSON-decodes it into raw_changes) and falls back to the old POST 'changes' param for backward compatibility.
2026-03-24 23:41:16 +00:00
Peter Goodhall
fbe95feaab Show selected count and correct applied count
Include the number of selected QSOs in the flash notice and update feedback to show both selected and actually updated counts. Also fix the model logic to only increment the applied counter when DB affected_rows() > 0 (previously >= 0), preventing non-updates from being counted.
2026-03-24 23:38:45 +00:00
Peter Goodhall
9f324f3435 Add start date filter to callhistory
Add an optional start_date filter to the callhistory preview workflow. Controller: validate YYYY-MM-DD input, set flash notice and redirect on invalid format, pass the start_date to the model and include it in view data. Model: accept a start_date parameter and apply a COL_TIME_ON >= start_date 00:00:00 WHERE clause when provided. View: add a date input to the form and display the selected start date in the no-matches message to indicate the time scope.
2026-03-24 23:31:56 +00:00
Peter Goodhall
1a14e986e1 Require organization label for call history files
Enforce presence of organization_label for uploaded call history files and bulk SIG updates. Controller changes: on upload, remove the stored temp file and show a notice if organization_label is empty; when applying scans, expect a posted file_id, load the file and reject bulk updates if the file lacks an organization_label; simplified a proposal-empty check to only consider proposed_sig. View changes: update introductory text to remove 'optional', mark the organization label input as required, and include a hidden file_id field in the preview/apply form so the controller can validate the selected file.
2026-03-24 23:28:24 +00:00
Peter Goodhall
ed0578cd18 Add scan preview/apply for call history
Adds a workflow to scan uploaded call history files for matching QSOs and apply SIG/SIG_INFO backfills. Controller Callhistory: loads logbooks, adds scan_preview and scan_apply actions, CSV parsing helpers, and safety checks to ensure files are readable and station ownership matches. Model Callhistory_model: adds get_station_ids_for_logbook, get_qsos_for_callsigns, and apply_sig_backfill to fetch candidate QSOs within a user's station/logbook scope and apply updates in a DB transaction. View callhistory/index.php: introduces a preview UI with selection controls, logbook scope selector, and client-side JS to manage selections and submission. Changes include normalization/heuristics for extracting callsigns/exchanges and only propose updates where existing SIG fields are blank.
2026-03-24 23:22:21 +00:00
Peter Goodhall
9d6a9e84fc Improve CSV parsing heuristics
Enhance Callhistory CSV parsing to handle comment/BOM lines and ambiguous columns. Removed the unused line_number logic and added is_comment_row to skip comment rows (handles leading BOM and '#' markers). Introduced extract_name to better detect operator/name when columns are swapped, and expanded guess_exch1_without_header to check the first few columns for exchange/name patterns. Added helper heuristics looks_like_name_value and looks_like_exchange_value to distinguish names from exchange values for more reliable extraction.
2026-03-24 22:49:50 +00:00
Peter Goodhall
894d9af38f Add Call History upload and lookup feature
Introduce a new Call History feature: adds Callhistory controller, Callhistory_model, migration (create callhistory_files table) and view for uploading/managing call history files. Implements CSV/TXT upload handling, storage per-user, activation/priority controls, checksum, and server-side lookup that scans active files for matching callsigns. Integrates UI: header menu link, contesting and QSO views show call history results inline, and JavaScript to perform lookups and render results with copy-to-SIG functionality. Also updates .gitignore to exclude uploaded callhistory directory and bumps migration_version to 261.
2026-03-24 22:36:54 +00:00
Peter Goodhall
70971d81f1 Fix contesting tab order and initial focus flow
Set deterministic tab sequence for contest logging fields by exchange type, start focus on callsign, and end navigation at Save QSO for faster keyboard entry.
2026-03-24 16:07:44 +00:00
Peter Goodhall
c3a5410805 Normalize county/state fields and use in queries
Normalize COL_CNTY/COL_STATE handling and use normalized expressions in queries to ensure consistent grouping/filtering and avoid mismatches.

- application/models/Counties.php: add normalized SQL expressions (trim/case/substring) and apply them to counting, grouping and ordering queries; filter out empty normalized states and adjust joins to compare normalized values.
- application/models/Logbook_model.php: normalize incoming $county/$state, add dxcc_entities join and selects, and use normalized WHERE clauses (case/trim and substring for 'ST, County' formats); also standardize band filter to COL_BAND != 'SAT'.
- application/views/view_log/partial/log_ajax.php: avoid undefined property notices by checking for name/end on the row object and use those values for Country and Flag display.

These changes address inconsistent imported county/state formats (e.g. "ST, County"), whitespace/case variations, and prevent PHP notices while keeping query semantics intact.
2026-03-24 16:04:23 +00:00
Peter Goodhall
fb362fd699 Refactor station reference selectize init
Replace duplicated selectize configuration in create.php and edit.php with a shared initStationReferenceSelect(selector, endpoint, maxItems) helper. The new function centralizes AJAX loading (min 3 chars), fields, and options, and is used to initialize SOTA, WWFF (single-select) and POTA (multi-select) inputs. No functional changes intended—this reduces duplicated code and simplifies future maintenance.
2026-03-24 14:34:49 +00:00
Peter Goodhall
14af3fda19 Support multiple POTA refs, DB + UI
Add support for comma-separated POTA references across the app: bump migration version to 259 and add migration 260 to expand COL_MY_POTA_REF and station_pota to VARCHAR(255). Introduce Pota::split_refs and collect_refs_from_rows to normalize and aggregate multiple refs; refactor Pota counts to compute unique refs per band/mode. Normalize station_pota when saving in Stations and Logbook_model (uses normalize_pota_refs), and adjust POTA search to match refs inside comma-separated values. Update views to render multiple POTA links and hashtags, and add Selectize-based autocomplete for station POTA input on create/edit forms. Also minor change to user_owns_station query (removed user_id where clause).
2026-03-24 14:32:17 +00:00