Commit graph

5834 commits

Author SHA1 Message Date
Peter Goodhall
8c98d523fd Add migration for Tag Cloudlog 2.8.9
Bump migration_version to 258 and add Migration_tag_2_8_9. The migration sets the stored app version to 2.8.9, resets users' 'version_dialog' confirmed flag to false to trigger the version info dialog, and includes a down() to revert the stored version to 2.8.8.
2026-03-12 15:38:27 +00:00
Peter Goodhall
5747413a46 AMSAT-Status - Sat name changes
AMSAT has decided to change value names so this fixes it
2026-03-11 11:37:41 +00:00
Peter Goodhall
e430b6a306 Handle date-only created_at inputs
Enhance created_at parsing to accept date-only inputs (YYYY-MM-DD). If only a date is provided, append a time part: reuse the existing note's time if available and valid, otherwise use the current time. For other input formats, attempt to parse with strtotime and normalize to Y-m-d H:i:s. All stored values are xss_clean()-sanitized and invalid/unparsable inputs are ignored.
2026-03-10 13:09:13 +00:00
Peter Goodhall
a4851b8c80 Update edit.php 2026-03-09 18:21:14 +00:00
Peter Goodhall
69dd06c225 Add Quill editor styles to views
Add comprehensive Quill .ql-editor CSS (typography, spacing, headings, lists, blockquotes, pre/code, tables, images, links, hr) to notes/add.php, notes/edit.php and view_log/index.php to improve editor and rendered content readability and ensure consistent styling. Note: the inserted CSS in notes/edit.php appears to have a missing/ mis-nested closing brace which may break the stylesheet and should be corrected.
2026-03-09 14:02:15 +00:00
Peter Goodhall
7ba915e29c Add public QSO map to station diary
Add interactive QSO map support for public station diary entries. Controller: add stationdiary::get_qso_map_data() to return JSON map data for a given entry/date range/logbook with station location. Models: Note::get_public_entry_user_id() to resolve the entry owner; Logbook_model: get_qsos_for_public_map() to query QSOs for the map, set a default stn_loc fallback, and skip markers with invalid 0,0 coordinates. View: public_index.php includes Leaflet CSS/JS, a Show/Hide QSO Map toggle, map container per entry, client-side map initialization and marker/popups loaded via POST to the new endpoint. These changes ensure public diary entries can display QSO locations and the station marker while avoiding bogus markers and limiting results to the correct user/logbook context.
2026-03-09 13:50:34 +00:00
Peter Goodhall
d0c4dcd66a Optimize uploaded images: resize/compress to 1080
Update image processing for uploads to improve optimization: set quality to 70%, change master_dim to auto, and target a max dimension of 1080x1080. Add logic to only resize when an image exceeds 1080px on any side while still reprocessing (calling resize) for compression even when dimensions are within limits. Minor formatting/cleanup of image library initialization.
2026-03-09 13:35:07 +00:00
Peter Goodhall
a4d284a0c0 Add reactions to station diary entries
Introduce a reactions feature for public station diary entries. Adds a migration to create station_diary_reactions with indexes and a unique (diary_id, visitor_hash) constraint; bumps migration version to 257 and registers a new route for /entry/:id/react. Controller: implements visitor token/hash creation, a react() endpoint to accept POSTed reactions (like, love, fire), increments/updates reactions, invalidates cache and returns totals and visitor reaction. Model: new methods to get totals, fetch visitor reaction and save/update reactions. View: UI, styles and client-side JS for reaction buttons, counts, and copy/share enhancements; integrates totals and visitor state into the single-entry view.
2026-03-09 13:29:14 +00:00
Peter Goodhall
bef2981945 Allow 1-based image position in shortcodes
Add a fallback in Note::process_image_shortcodes to treat numeric identifiers as 1-based positions into the $images array when no image was found by earlier lookups. Validates the position is within range and converts it to zero-based indexing, enabling shortcodes like [image:1] to reference the first image.
2026-03-09 13:11:02 +00:00
Peter Goodhall
da4c4201ca Support public QSO datetime format & sharing
Add handling for public QSO datetime formatting and single-entry sharing. Introduce get_public_qso_datetime_format() in Stationdiary controller (defaults and appends time if missing) and pass qso_datetime_format, is_single_entry and current_entry_permalink to the public view. Update Note model to select and return user_date_format from auth table so user preferences flow through. Update public_index view to use the public QSO datetime format for QSO rows and add social share buttons (Facebook, X, Bluesky) when viewing a single entry.
2026-03-09 11:00:21 +00:00
Peter Goodhall
0b07e5ac18 Add public diary entry view and routing
Add support for viewing individual public Station Diary entries. Adds a new route for /station-diary/:callsign/entry/:id, a Stationdiary::entry controller method with caching (per-call sign + entry + cache version, 86400s TTL), and a Note model method get_public_station_diary_entry() that loads images and optional QSO summaries/lists. Update public_index view to link entry titles to their permalink and include entry IDs in article IDs, and update RSS feed to use the entry permalink/guid. Also include small CSS tweaks for entry title links.
2026-03-09 10:57:38 +00:00
Peter Goodhall
6e4575d5c4 Include satellite fields in note queries
Update Note model SELECT lists to include COL_PROP_MODE, COL_SAT_NAME and COL_SAT_MODE so propagation and satellite metadata are returned for single-day and date-range queries in application/models/Note.php.
2026-03-08 17:53:18 +00:00
Peter Goodhall
92df3b0fc2 Show satellite name in band column
When a QSO is a satellite contact (PROP_MODE 'SAT' or COL_SAT_NAME present), display the satellite name (or 'SAT' if no name) in the Band column instead of the RF band. Changes apply to both server-side PHP rendering and the client-side JS template, with existing fallbacks ('-' when no band) and HTML-escaping preserved for safety.
2026-03-08 17:49:43 +00:00
Peter Goodhall
07c3527cb6 Render diary images & improve diary cache
Load and render station diary images inline and separately, and make cache handling more robust. Notes controller: load diary_images for print view and invalidate public diary cache when an image caption is updated. Stationdiary controller: include a render-version token in the public diary cache key to force re-renders when markup changes. Note model: make touch_public_diary_cache_version more resilient (unique value, fallback to file_put_contents and cache clean), add invalidate_public_diary_cache_for_note helper, and enhance process_image_shortcodes to handle encoded brackets, tolerant shortcode spacing, modifiers (alignment and size) with deterministic styling, and return used image ids. Views: update station_diary_print and note view to process shortcodes, remove empty paragraph artifacts, show inline images via shortcodes, and display remaining images with captions and improved print CSS.
2026-03-08 15:11:33 +00:00
Peter Goodhall
a6e3c62fd1 Support multiple image shortcode modifiers
Extend image shortcode parsing to accept multiple colon-separated modifiers (e.g. [image:ID:left:small]). Updated the regex to capture optional modifier strings and renamed the variable to $modifierString. Modifiers are split and processed so alignment (left/right/center) and size (small/medium/large) can be applied together; alignment sets wrapper classes and a default max-width only if not already set, while size modifiers set explicit max-widths. Minor refactor preserves existing behavior and tracks used image IDs.
2026-03-08 14:54:33 +00:00
Peter Goodhall
b364db4234 Clean up empty <p><br> and redundant <br> in notes
Strip empty <p><br></p> tags and remove stray <br> between paragraphs in station diary views. public_index.php: after processing image shortcodes, remove empty paragraph placeholders and collapse <br> placed between </p> and <p>. rss.php: process image shortcodes for each entry (using $entry->images ?? []), clean the note content the same way, and output the cleaned content in the RSS <description>. This prevents extraneous blank lines and redundant breaks in rendered HTML and RSS feeds.
2026-03-08 14:50:55 +00:00
Peter Goodhall
f8dffa8776 Add image shortcodes and caption editing
Support inline diary images via shortcodes and improve notes UI. Introduces a Note::process_image_shortcodes() method (ID/caption lookup and modifiers like left/right/center/small/medium/large), and updates station diary rendering to process shortcodes and avoid duplicate image output. Adds an AJAX endpoint notes/update_image_caption with ownership checks to save image captions, plus client-side JS to edit/save captions from the note edit view. Refactors notes add/edit views: reorganized form into sections/accordion, Quill editor min-height, image upload tips, improved buttons and layout, and QSO summary layout tweaks.
2026-03-08 14:36:56 +00:00
Peter Goodhall
af756c3c88 Update public_index.php 2026-03-08 14:16:37 +00:00
Peter Goodhall
58b6ae86c1 Close article tag and move pagination outside
Add a closing </article> and adjust the surrounding conditionals so the pagination nav is rendered outside the entry loop. This fixes HTML nesting and ensures the HR/summary/images remain part of each entry while pagination appears once below the list in the station diary public index view.
2026-03-08 13:41:41 +00:00
Peter Goodhall
d31b3f9517 Render diary separator conditionally
Only output the diary <hr> divider when the entry has content to separate: either include_qso_summary is enabled and qso_summary.total_qsos > 0, or the entry has images. This avoids showing an unnecessary rule for empty entries and includes a small whitespace cleanup.
2026-03-08 13:40:22 +00:00
Peter Goodhall
a4dd03b24d Show divider only when QSO summary exists
Moved the <hr> divider into the QSO summary conditional so the rule is rendered only when include_qso_summary is true and qso_summary.total_qsos > 0. This prevents an empty divider from appearing when no QSO summary is present.
2026-03-08 13:39:38 +00:00
Peter Goodhall
50c24aede1 Add public station diary & QSO filters
Introduce Public Station Diary feature and QSO filtering support.

- Add migrations: 255 adds public_station_diary_enabled option (default enabled), 256 adds qso_date_start, qso_date_end, qso_satellite_only columns to notes.
- Bump migration version to 256.
- Add controller actions (Options::public_diary, public_diary_save) and new options view to manage the public diary setting; add sidebar link.
- Extend Note model to persist QSO filter fields and provide new methods to fetch QSO lists/summaries for date ranges and satellite-only filtering; wire filter usage into summary generation.
- Update notes add/edit views to include QSO Summary Filters (date range + satellite-only).
- Add translations for the new options keys across multiple language files.
- Update public station diary listing view styling/path and minor content cleanup; other views updated to support feature.
- Remove obsolete cache files (.htaccess, index.html).

These changes enable admins to toggle a public station diary and let note authors control which QSOs are included in summaries via date ranges and SAT-only filtering.
2026-03-08 13:34:31 +00:00
Peter Goodhall
babcdf87d1 Add RSS feed_url and update fonts/styles
Controller: pass a 'feed_url' value into the RSS view (site_url for the feed). RSS view: compute the current request URL (respecting HTTPS) and use it for the atom:link self href. Public view: load Google Fonts (Merriweather & Lora), add preconnect hints, switch typography to the new fonts, increase line-height and adjust font-weights/sizes for headings and body to improve readability.
2026-03-08 12:07:51 +00:00
Peter Goodhall
ee69b8ad74 Mirror diary form messages to modal footer
Add a dedicated footer message container and client-side logic to mirror form messages into the modal footer. Removed the `required` attribute from the quick logbook select, introduced `#diaryFormFooterMessages`, and added a MutationObserver + htmx:afterSwap listener to copy content from `#diaryFormMessages` to the footer. Also consolidated error rendering into a single HTML snippet and clear both message areas when the modal closes. This surfaces HTMX/server messages in the modal footer for better visibility and avoids duplicated message handling.
2026-03-08 11:53:52 +00:00
Peter Goodhall
dbed529f5d Require logbook for QSO summary; fix band ordering
Add numeric band sorting in Note model and make logbook selection required when including a QSO summary. Note model: select COL_BAND+0 as band_num and order by band_num to ensure proper numeric ordering. Views (notes/add, notes/edit, view_log/index): update labels and placeholder option text, mark the logbook <select> as required, adjust helper text, and add JS to toggle the required attribute and visibility based on the "Include QSO summary" checkbox (including setting initial state for validation).
2026-03-08 11:48:17 +00:00
Peter Goodhall
5d034d0963 Add public Station Diary with images & RSS
Introduce public Station Diary functionality: add global config flag, routes, controller, model changes, views and DB migrations. New migrations (252-254) add is_public/include_qso_summary, diary_images table and logbook_id on notes. Notes model updated to handle public flags, diary images, qso summaries, caching (per-user cache version), and helper methods for listing/counting public diary entries. New Stationdiary controller serves paginated public pages and RSS feed with caching. Notes controller updated to handle image uploads, attach images to diary entries, and provide an AJAX endpoint to delete images. Views updated to support public visibility options, logbook selector, image upload UI and Quill editor assets; routes and migration version bumped accordingly. Includes file upload example added to uploads/diary.
2026-03-08 11:42:41 +00:00
Peter Goodhall
b9d842ca47 Use correct eQSL received flag field
Fixes a bug where the wrong array key was checked when determining if an eQSL was received. The code previously used $record['qsl_sent']; it now checks $record['eqsl_qsl_rcvd'] to set $qsl_rcvd (or an empty string) using config['eqsl_rcvd_mark'], ensuring imports correctly mark received eQSLs.
2026-03-07 14:35:45 +00:00
Peter Goodhall
e233839127 Add FT2 MFSK submode migration, bump version
Adds migration 251_add_ft2_submode.php which inserts a new 'FT2' submode under mode 'MFSK' into the adif_modes table (qrgmode='DATA', active=1) if it doesn't already exist, and provides a down() to remove it. Also bumps application migration_version to 251. Note: FT2 is not part of the ADIF spec yet.
2026-02-20 18:27:53 +00:00
Peter Goodhall
fe38b96cce Add migration 250 tagging release 2.8.8
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.
2026-02-19 16:06:41 +00:00
Peter Goodhall
88e95b0db9 Add HTMX modal upload and cert table refresh
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.
2026-02-18 15:51:19 +00:00
Peter Goodhall
7f7d2a6426 Add left-positioned dropdown submenu styles
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).
2026-02-17 22:58:21 +00:00
Peter Goodhall
f26c112437 Report found vs updated LoTW QSOs
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.
2026-02-17 15:35:06 +00:00
Peter Goodhall
9338ca4769 Include LoTW status in table HTML
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.
2026-02-17 15:33:41 +00:00
Peter Goodhall
a94a8759e0 Remove LoTW Status column; add status summary
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.
2026-02-17 15:30:53 +00:00
Peter Goodhall
ad81bd81de Support batch updates by primary key
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.
2026-02-17 15:28:53 +00:00
Peter Goodhall
392a1389d6 Map additional satellite names in Logbook_model
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.
2026-02-17 14:21:24 +00:00
Peter Goodhall
60fe6ddbf2 Format notes view templates
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.
2026-02-13 11:16:49 +00:00
Peter Goodhall
680612ca01 Add Station Diary print view & action
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.
2026-02-12 22:30:08 +00:00
Peter Goodhall
bef1e54820 Show saved timestamp in notes views
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".
2026-02-12 22:20:52 +00:00
Peter Goodhall
a4ec01a8ea Add Station Diary modal and quick_add endpoint
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.
2026-02-12 22:08:55 +00:00
Peter Goodhall
440f5b18a9 Skip unsaved-change warning if callsign empty
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()).
2026-02-11 21:45:03 +00:00
Peter Goodhall
c57c250b45 Use distinct() and fix station field
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.
2026-02-11 14:16:51 +00:00
Peter Goodhall
41a8849d7e Cache dashboard stats and add DB indexes
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.
2026-02-11 13:18:52 +00:00
Peter Goodhall
654c456a35 Fix migration index drop logic
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.
2026-02-11 13:07:55 +00:00
Peter Goodhall
d3d551c59b Remove gridsquare index drop; re-enable db_debug
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.
2026-02-11 13:05:16 +00:00
Peter Goodhall
d4a7e4cfac Batch eQSL updates and add indexes
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.
2026-02-11 11:32:25 +00:00
Peter Goodhall
bcd9ded47e Rename LOTW index to idx_confirmation_match
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.
2026-02-11 11:17:09 +00:00
Peter Goodhall
cfa24d9f1a Add LoTW batch updates and performance indexes
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.
2026-02-11 11:14:59 +00:00
Peter Goodhall
2cb8d62860 Add gridsquare prefix index and optimizations
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.
2026-02-11 11:09:39 +00:00
Peter Goodhall
f01599e6a5 Add indexes and batch processing for uploads
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.
2026-02-11 10:59:24 +00:00