Skip to content

feat(adif): store the ADIF submode (FT4/JS8/PSK31) as the QSO mode on import - #240

Merged
patrickrb merged 1 commit into
mainfrom
optio/task-23604c5c-7c17-400f-a331-92e932da0952
Jul 24, 2026
Merged

feat(adif): store the ADIF submode (FT4/JS8/PSK31) as the QSO mode on import#240
patrickrb merged 1 commit into
mainfrom
optio/task-23604c5c-7c17-400f-a331-92e932da0952

Conversation

@patrickrb

Copy link
Copy Markdown
Owner

Problem

WSJT-X, JTDX and JS8Call — the primary clients that post to Nextlog's ADIF import and /api/qso endpoint — log the operating mode of a digital QSO as an ADIF SUBMODE beneath a generic parentMODE:

Client / modeADIF sentStored beforeWanted
WSJT-X FT4<MODE:4>MFSK<SUBMODE:3>FT4MFSKFT4
JS8Call<MODE:4>MFSK<SUBMODE:3>JS8MFSKJS8
WSJT-X FST4<MODE:4>MFSK<SUBMODE:4>FST4MFSKFST4
fldigi PSK31<MODE:3>PSK<SUBMODE:5>PSK31PSKPSK31

The importer only read MODE (fields.mode || fields.submode), so every one of those QSOs was stored under its generic parent. But the app treats FT4, FT8, PSK31, etc. as first-class modes — they're in the search page's mode list, and the mode filter / mode statistics / charts group by the flat contacts.mode column (there is no submode column). The result: an FT4 run imported from WSJT-X silently dropped out of the FT4 filter and showed up as a lump of MFSK, skewing per-mode statistics.

Solution

Add a small pure helper resolveAdifMode(mode, submode) in src/lib/adif.ts and use it when inserting a record:

  • Promote the submode to the effective mode when one is present (MFSK+FT4FT4).
  • Except the voice sidebandsUSB/LSB, which stay SSB — promoting them would split every phone QSO out of the SSB filter and phone stats.
  • Falls back to MODE, then to SSB, exactly as before when no usable submode exists.
  • Normalizes to uppercase, matching how modes are stored and exported elsewhere.

Backwards compatibility

  • Existing rows are untouched — this only affects newly imported/posted records.
  • MODE-only imports (FT8, CW, RTTY, SSB, …) resolve to the identical value they did before.
  • No schema change; contacts.mode stays a flat varchar. Export is unaffected (it already emits the flat stored mode, and the app already treats FT4/FT8 as top-level modes).

Testing

  • New tests/adif-mode.spec.ts (6 cases): submode promotion, USB/LSB → SSB, MODE-only fallback, uppercase/trim normalization, SSB default, and an end-to-end parseAdifRecordsresolveAdifMode check on a verbatim WSJT-X FT4 record.
  • Full ADIF suite (adif-parse, adif-generate, adif-datetime, adif-mode) — 34 passed.
  • npm run typecheck clean, eslint clean on touched files, npm run build succeeds.

Future follow-up

  • Optionally reconstruct the MODE+SUBMODE pair on export for the strictest ADIF readers (FT4 is technically a submode of MFSK in the ADIF spec). Deferred because it needs a mode→parent lookup table and the current flat-mode export is already what the rest of the app assumes; LoTW/Cloudlog/N1MM all accept MODE=FT4.

🤖 Generated with Claude Code

… import
WSJT-X, JTDX and JS8Call log the operating mode of a digital QSO as an ADIF
SUBMODE beneath a generic parent MODE — FT4/JS8/FST4 under MFSK, PSK31 under
PSK. The importer only read MODE, so every one of those QSOs was stored as
"MFSK"/"PSK". The mode filter, mode statistics and charts treat FT4/JS8/PSK31
as first-class modes (they're in the search UI's mode list), so an FT4 run
imported from WSJT-X silently dropped out of the FT4 filter and skewed stats.
Add resolveAdifMode(mode, submode): promote the submode when present, except
the voice sidebands (USB/LSB) which stay SSB so phone QSOs keep matching the
SSB filter. Normalized to uppercase to match how modes are stored/exported.
Backwards compatible: existing rows are untouched; only affects newly imported
records. MODE-only imports (FT8, CW, RTTY, SSB) resolve exactly as before.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercelBot commented Jul 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
nodelogReadyReadyPreview, CommentJul 24, 2026 6:08am

Request Review

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@patrickrb