Commit graph

1999 commits

Author SHA1 Message Date
Peter Goodhall
9913eb08a2 Improve callsign lookup, caching & recent details
Add a cached DXCC lookup and a jsondxcc endpoint to speed up country resolution and reduce DB load (file-cache with 1h TTL). Introduce cached_dxcc_lookup(), build_confirmation_where(), and callsign_status() in the Logbook controller; refactor confirmed_grid_before() and worked_grid_before() to accept logbook relationships and confirmation prefs to avoid redundant queries. Use a new Logbook_model::get_recent_callsign_details() to populate recent name/gridsquare/qth/iota/qsl/state/county values in a single query. Update JS to better manage lookup state, invalidate in-flight requests, and perform a debounced quick DXCC lookup to improve UX. Tweak previous-contacts pagination to a compact sliding window and remove a redundant UI note.
2026-04-13 13:57:03 +01:00
Peter Goodhall
e197a5c1f2 Add toggle for QSL Cards menu item
Introduce a user-controllable option to show/hide the "View QSL Cards" link in the Logbook menu. Controller: initialize menu_show_qsl_cards, load/save the 'show_qsl_cards' menu option and sync it to the session during profile updates. Model: fetch the 'show_qsl_cards' option and expose user_show_qsl_cards in the user data. Views: add a checkbox in the user edit form to control the setting, remove the duplicate SSTV storage card UI, and update the header to robustly read the session value and conditionally render the QSL menu item. Defaults to showing the menu item when the option is unset.
2026-04-08 22:26:05 +01:00
Peter Goodhall
297ff0af42 Add SSTV menu toggle for users
Introduce a user preference to show or hide the "View SSTV Images" menu item. Controller: initialize menu_show_sstv_images, load/save the 'menu:show_sstv_images' option and set session user_show_sstv_images when profile is saved. Model: fetches the menu option and exposes user_show_sstv_images (and has_eqsl_credentials) in the returned user data. Views: add a checkbox to the user edit form to toggle the setting, and conditionally render the eQSL/SSTV menu items in the header based on session flags. This lets users control visibility of the SSTV menu entry from their profile.
2026-04-08 22:18:02 +01:00
Peter Goodhall
d4251cdf41 Add no-cache headers and localize HTMX polling
Prevent caching for the HTMX endpoint and move polling into the component. Qso controller now sets Cache-Control/Pragma/Expires headers for the component_past_contacts endpoint to ensure fresh data. The previous_contacts view was updated to self-poll (hx-get with page param, hx-trigger every 5s, hx-target="this", and hx-vals timestamp) to include a cache-busting timestamp. The main qso index removed the redundant recurring poll (now only triggers on load) to avoid duplicate requests.
2026-04-06 16:04:26 +01:00
Peter Goodhall
8716e6caae Clear satellite fields when not SAT and on reset
Ensure satellite fields are cleared whenever propagation mode is not 'SAT' and when the QSO form is reset. In Qso.php, sat_name and sat_mode are set to empty strings if prop_mode != 'SAT' (added in two handling points). In assets/js/sections/qso.js, added clearSatelliteFields() to clear sat_name, sat_mode, satellite_modes_list and related state, call it from reset_fields(), and invoke the form reset flow to ensure no stale satellite data remains after resetting or changing propagation mode.
2026-04-06 14:37:56 +01:00
Peter Goodhall
e904595a9d Lazy-load QSO lists; add time index migration
Bump migration version to 265 and add a migration (265_add_station_time_on_index) that creates idx_station_time_on on (station_id, COL_TIME_ON) for faster time-based queries. Introduce lazy QSO loading: controller now sets defer_qso_list and uses a new POST endpoint get_filtered_qsos to fetch filtered QSO lists and summaries; also updated cache keys/render version and added per-entry cache deletion. Note model: add include_qso_list flag, memoize QSO summaries/lists and station IDs, replace DATE(COL_TIME_ON) filters with half-open datetime ranges (start inclusive, end exclusive) via helper methods to improve index use and performance. View: update public_index to render QSO list containers with data attributes, add JS to fetch and render QSO rows on demand, and support highlight DX updates. Overall changes optimize QSO queries and enable deferred loading to reduce initial page load and DB cost.
2026-04-06 11:11:03 +01:00
Peter Goodhall
5d7135124d Add AJAX QSO save endpoint and client handler
Introduce an AJAX-based QSO save flow: add QSO::ajax_saveqso() in the controller to validate input, set session/cookies, create the QSO and return JSON success/error payloads. Update the QSO view to include a data-ajax-save-url on the form and add a notice-alerts container location. Enhance the qso.js client: add isSubmitting guard, showQsoNotice helper, intercept form submit to POST serialized form data to the AJAX endpoint, handle success (reset form, show notice, refresh recent QSOs via htmx), display validation/server errors, and restore UI state when complete. These changes avoid full page reloads on save and provide inline validation feedback.
2026-04-05 17:36:52 +01:00
Peter Goodhall
aaf3aa85a6 Add API endpoint for accessible public slugs
Introduce API method logbook_public_slugs_accessible($key) that authorizes the API key, updates last-used timestamp, and returns JSON of all station logbooks (owned or shared) that have non-empty public slugs for the key owner. Add Logbooks_model::public_slugs_accessible_by_user($user_id) to select matching logbooks, label access_level as "owner" for owners or the stored permission_level for shared entries, and order results by logbook_name. Endpoint returns 401 for missing/invalid keys and a success payload with status, count, and logbooks on success.
2026-04-03 22:35:25 +01:00
Peter Goodhall
78209d497b Add API endpoint for logbook public slugs
Introduce GET /api/logbook_public_slugs/{key} in the API controller to return a JSON list of the API key owner's station logbooks that have non-empty public slugs. The endpoint authorizes the key, updates last-used timestamp, responds with 401 for missing/invalid keys or 200 with status, count and logbook entries. Add Logbooks_model::public_slugs_by_user to query station_logbooks for non-null/non-empty public_slug values ordered by logbook_name.
2026-04-03 22:00:35 +01:00
Peter Goodhall
41bc5a2104 Add gridsquare support to worked status API
Expose an optional `gridsquare` parameter to logbook_worked_status: update the docblock, parse and normalize the incoming gridsquare, and include it in the response payload. Add worked flags `grid_overall` and `grid_band` (and set them based on logbook_model->check_if_grid_worked_in_logbook results) so clients can check whether a grid square has been worked overall or on a specific band. Input is upper-cased/trimmed like other fields; existing DB logic is left intact.
2026-04-02 14:28:36 +01:00
Peter Goodhall
4ab0bff623 Add logbook_worked_status API endpoint
Introduce POST /api/logbook_worked_status to check "worked" and "confirmed" status for a given callsign (and derived country) against a public logbook. The endpoint requires an API key, logbook_public_slug and callsign, and accepts optional band and mode. It validates input and logbook/station relationships, resolves country via DXCC lookup, maps mode to a main mode, and queries the logbook table for overall and band-specific worked status as well as LoTW/QSL confirmations. Returns structured JSON with worked and confirmed subfields and appropriate HTTP status codes (400/401/404/200). Models used: api_model, logbook_model, logbooks_model; uses configured table_name for DB queries.
2026-04-02 14:06:05 +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
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
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
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
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
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
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
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
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
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
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
Peter Goodhall
c89ac7ceb5 Add contest callsign bearing/distance lookup with DXCC fallback 2026-03-24 14:13:35 +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
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
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
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
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
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
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
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