Bump migration version to 250 and add Migration_tag_2_8_8. The new migration sets the stored app version to 2.8.8 and resets the user's version_dialog confirmation (option_value = 'false') to trigger the version info dialog. The down() method rolls the version back to 2.8.7.
Enable HTMX-driven certificate uploads and partial UI updates for LoTW. Updated Lotw controller to detect HTMX requests in do_cert_upload, return inline success/error alerts for modal uploads, and added cert_table_refresh endpoint to return the cert table partial. Extracted the certificate table into a new view (lotw_views/cert_table.php) and replaced the inline table in index.php with a container that loads that partial. Added a Bootstrap modal view (upload_cert_modal.php) with an HTMX multipart form, drag-and-drop file UI, JS handlers to manage upload state and refresh the certificate list, and modal reset behavior. Minor refactors to flash/success handling to support both full-page and HTMX flows.
Mark certain dropdowns (Gridmaster, Other Export Options, Third Party Logbooks) with a new dropdown-submenu-left class in header.php so submenus can open to the left. Update general.css to style .dropdown-submenu and .dropdown-submenu-left positioning, refine .navbar .dropdown-menu appearance, and improve dropdown item spacing, hover effects and submenu chevron styling for better alignment and visual consistency (prevents overflow and improves UX).
Initialize and increment a $found_count while parsing ADIF records when import_check returns 'Found', then after batch update compute already-confirmed QSOs and expand the LoTW status message to include: Found, Updated, Already confirmed, and Gridsquares updated. Uses max(0, ...) to avoid negative already-confirmed values and updates the log output accordingly.
Append the LoTW status div to the $table variable before assigning it to $data['lotw_table'], rather than concatenating it afterward. This ensures the status is part of the table HTML output and avoids the separate post-assignment append.
Remove the per-row "LoTW Status" header and cells from the Lotw table output to avoid repeating the same status for each QSO. Instead, append a single "LoTW Status" summary div after the table using $lotw_status. This simplifies the table layout and centralizes the LoTW status display.
Allow LoTW batch updates to reference QSOs by COL_PRIMARY_KEY for reliable matching. Controller: include 'primary_key' in batch update payloads. Model: collect numeric primary keys, expand WHERE to include COL_PRIMARY_KEY IN (...) alongside the existing datetime/call/band/station match, add early exit/log when no usable keys provided, and build an id-based lookup (qso_map_by_id) to prefer primary-key matches while remaining backward-compatible with the composite key lookup. This reduces ambiguous matches and improves update accuracy.
Add mappings for QMR-KWT-2 -> QMR-KWT-2_(RS95S) and Lobachevsky -> Lobachevsky_(RS83S), and introduce conditional APRS name mapping for BOTAN (when COL_MODE == 'PKT') and SONATE-2 (when COL_MODE == 'PKT'). These changes extend satellite name normalization in application/models/Logbook_model.php to handle these satellites and modes.
Normalize indentation, spacing and PHP/HTML formatting in application/views/notes/main.php and application/views/notes/station_diary_print.php. Changes are purely cosmetic (whitespace, indentation, minor spacing around concatenation and tags, and newline adjustments) to improve readability and consistency; no functional logic was modified.
Add a Station Diary print feature: controller Notes.php now sets a has_diary_entries flag for the main notes view and adds a station_diary() action that loads Station Diary entries and renders a print-friendly view. The notes main view conditionally shows a "Station Diary" button that opens the print page in a new tab. A new view notes/station_diary_print.php provides a print-optimized layout, entry listing with date/time handling, total entries summary, a print button, and a friendly fallback when no entries are found.
Display the saved creation timestamp (including time) across notes list, note view, and edit form. Adds a human-readable "Saved" line in application/views/notes/edit.php and application/views/notes/view.php, and updates application/views/notes/main.php to include the time using the format "M d, Y \a\t g:i A". The date input in the edit form still uses a YYYY-MM-DD value for the date picker, and entries with empty or zero dates show "N/A".
Introduce a Station Diary UI and backend endpoint to allow quick note creation via HTMX. Added Notes::quick_add in the controller with form validation, note creation, success/error responses and a small JS form reset. Updated view_log/index to show a Station Diary button (when user_show_notes=1) and include the modal form that posts to notes/quick_add and renders messages into the modal.
Add checks around the unsaved-changes logic to bypass the confirmation when the #callsign field is present but empty. The patch inserts a guard in the page unload catcher and before showing the confirmation so users creating new/blank callsign entries won't receive an unnecessary unsaved-change warning (checks element existence and uses trim()).
Update .gitignore to exclude all files under /application/cache while whitelisting /application/cache/index.html and /application/cache/.htaccess. This prevents committing transient cache files but preserves placeholder and access-control files needed to keep the directory and settings in the repo.
In Logbook_model.php, replace select('DISTINCT user_id') with $this->db->distinct(); $this->db->select('user_id') to use CI's distinct API and produce correct SQL. Also correct the where clause to use station_logbooks_relationship.station_location_id instead of station_id so shared-access users are filtered by the proper station location.
Add per-user/logbook file caching for dashboard statistics (15min TTL) and update Dashboard controller to use cached qso, countries, VUCC and QSL queries. Introduce clear_dashboard_cache() in Logbook_model and call it on QSO create/update/delete to invalidate affected users' cache entries. Add migration (249) to create composite indexes (idx_dxcc_stats, idx_vucc_gridsquare, idx_vucc_grids) to improve dashboard query performance, and bump migration_version to 249. Also include generated cache files under application/cache for current stats.
Replace malformed code with a proper existence check for the 'idx_confirmation_match' index, drop the index with ALTER TABLE if present, and re-enable db_debug. This fixes a syntax/logic error in the migration so the LOTW/QRZ/eQSL confirmation match index is removed safely during migration.
Delete the conditional block that dropped the `idx_gridsquare_prefix` index from the table. Add `$this->db->db_debug = true;` and close out the migration method/class. This prevents the migration from removing the gridsquare prefix index and ensures DB debug mode is restored after the migration.
Add batch processing for eQSL imports/exports and introduce performance indexes. Bump migration_version to 248 and add Migration_add_eqsl_performance_indexes to create idx_eqsl_qslrdate and idx_eqsl_confirmation_match indexes to speed up eQSL queries and batch matching. Modify Eqsl controller to collect successful uploads and perform a single batch mark-as-sent update. Update EqslImporter to queue confirmations and run a single batch update at the end. Implement eqsl_update_batch() and eqsl_mark_sent_batch() in Eqslmethods_model to perform efficient batch DB operations and logging, reducing per-record queries for large eQSL operations.
Replace the specific idx_lotw_confirmation_match index with a generic idx_confirmation_match and update related comments and local variable names. Comments now note the index benefits both LOTW and QRZ processing (import_check, lotw_update_batch, process_qrz_batch). The composite index columns remain (COL_TIME_ON, COL_CALL, COL_BAND, COL_STATION_CALLSIGN); existence checks and add/drop statements were adjusted to use the new name.
Bump migration version to 247 and add a migration that creates performance indexes for LoTW workflows (idx_lotw_qslrdate, idx_lotw_qsos_to_upload, idx_lotw_confirmation_match) to speed common queries. Refactor Lotw controller to collect records in memory, build rows for rendering, and perform a single batch confirmation update via a new Logbook_model::lotw_update_batch() method instead of many individual updates. Implement lotw_update_batch() to look up matching QSOs, perform update_batch() calls, and separately update gridsquares/distances using the Qra library. Simplify LotwCert::toggle_archive_certificate() to toggle archived state with a single UPDATE and return the resulting status.
Bump migration version and add a new migration (246) to create/drop a 4-char prefix index on COL_GRIDSQUARE to speed LIKE queries; migration 245 now also drops the prefix index if present. Add Stations::user_owns_station and use it in Logbookadvanced_model to avoid N+1 station lookups. Add caching to Logbooks_model::list_logbook_relationships to prevent redundant queries. Optimize Oqrs_model queries to select only needed columns for several methods. Add Stats::getUniqueCallsignsConsolidated to combine multiple unique-callsign groupings into a single set of queries for better performance. Database debug toggles added where appropriate.
Improve query performance and memory usage by adding a migration to create several indexes and converting various upload/reporting flows to batched processing. Changes include:
- Add migration 245 to create indexes: idx_mode, idx_sat_name, idx_continent, idx_qsl_stats (composite), idx_hrdlog_upload, idx_qrz_upload to speed common queries.
- Bump migration version to 245 in config.
- Hrdlog and Qrz controllers: switch to fetching QSOs in LIMIT/OFFSET batches, process updates in chunks, add logging for batch progress, and use break 2 to stop outer loops on invalid API keys to avoid continuing work.
- Logbook_model:
- get_hrdlog_qsos and get_qrz_qsos now accept limit/offset and use ORDER BY/LIMIT/OFFSET for batching.
- Replaced a subquery with a JOIN for grid-based filtering to improve performance.
- get_modes rewritten to use query builder (distinct/select/order_by).
- Bulk DXCC updates use update_batch instead of per-row queries.
- calls_without_station_id limited to 500 results to avoid UI hangs.
Overall goal: prevent memory exhaustion with large datasets and improve database query performance.
Replace repeated LEFT OUTER JOIN (SELECT callsign, MAX(lastupload) ...) derived-table joins with simpler LEFT JOIN lotw_users lotw across Distances_model, Logbook_model, Logbookadvanced_model, and Worked_all_britain_model. Also remove an unnecessary DISTINCT/inner station_profile join from an optimized Logbook_model subquery. These changes simplify SQL emitted by the CI query builder, improve compatibility and readability, and may improve performance; note that using direct joins can change which lastupload row is returned if multiple lotw_users rows exist for a callsign.
Bump migration version to 244 and add migration 244_tag_2_8_7. The new migration updates options.version to 2.8.7 and resets user_options.version_dialog.confirmed to false to trigger the version info dialog; the down() method reverts options.version to 2.8.6.
Enhanced the WWFF awards page with band, mode, and QSL type filters, quick preset buttons, and a summary section showing worked/confirmed parks and milestone progress. Updated the controller to handle filter input and summary data, and extended the model with methods for filtered queries and statistics.
Added collapsible filter panel with quick preset buttons, improved form layout, and a new statistics summary section showing WAJA progress and milestones. Prefecture names in the table are now clickable to view QSOs. Updated SQL queries in the Waja model to use the correct band key and improved SAT handling.
Introduced a new controller method sigexportcsv() to export SIG QSO data as a CSV file. Added a corresponding button in the SIG QSO list view to allow users to download the CSV export.
Updated the SIG awards table to redirect WAB entries to a dedicated WAB awards page instead of the generic SIG details page. This improves navigation and user experience for WAB award users.
Introduces filtering by band, mode, and confirmation status to the SIG awards section in Awards.php, including a filter summary helper. Updates all supported language files to add translations for the new SIG award filters, table headers, and related UI elements.
Introduces band, mode, and confirmed-only filters to the Worked All Britain (WAB) award view and details AJAX endpoint. Updates the controller, model, and view logic to support filtering, and adds new localized strings for WAB award UI elements in multiple languages. Also ensures the correct script is loaded for the WAB section and improves the Bands model to check for field existence before filtering by award.
Introduces logic in the Debug controller to detect if the application is running inside a Docker container and displays the result on the debug view. This helps developers quickly identify the runtime environment for troubleshooting and configuration purposes.
Added display of installation path, server API, HTTPS status, available disk space, database info, PHP settings, session information, and checks for gd and json PHP modules to the debug/main.php view for improved diagnostics.
Displays a 'Managed' row in the debug table if the managed.php config file exists, providing clearer visibility into the application's configuration state.
The backup controller now checks if the PHP ZIP extension is installed and passes this information to the view. The backup page displays a warning if the extension is missing, guiding users to install it for backup and restore functionality.
Refactored the backup export process to stream JSON data directly to a file handle, significantly reducing memory usage for large datasets. QSOs and logbooks are now written in chunks, and memory is freed periodically. Increased max execution time and adjusted memory limit to optimize for streaming. This improves reliability and scalability for users with large logbooks.
Modified the mode selection dropdown to display submode if it exists, otherwise fallback to mode. Also updated the iteration to use the result() method for consistency with the data structure.
Adds JSON_INVALID_UTF8_SUBSTITUTE to json_encode for $qsos_by_ref and $confirmed to handle invalid UTF-8 data, preventing JavaScript errors when rendering the SOTA map.
Moved the comment reset to the beginning of each line iteration in handleInput(), ensuring comments are cleared before processing each row. This prevents comments from persisting across lines and fixes potential data carryover issues.
Added migration 243 to tag Cloudlog as version 2.8.6 and updated the migration version in config. Improved SOTA awards table to display a message outside the table when no results are found. Modified the SOTA index page to trigger filter refresh on 'Apply' and adjusted DataTables language options for empty states.
Introduces a new section in the maintenance page allowing manual updates of reference data files (Clublog SCP, LoTW Users, DOK, SOTA, WWFF, POTA) via AJAX buttons with loading indicators. Adds corresponding UI-friendly controller methods with authorization checks and improves the WWFF update logic to process CSV files line by line for better memory efficiency.