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 parent MODE:

Client / mode ADIF sent Stored before Wanted
WSJT-X FT4 <MODE:4>MFSK<SUBMODE:3>FT4 MFSK FT4
JS8Call <MODE:4>MFSK<SUBMODE:3>JS8 MFSK JS8
WSJT-X FST4 <MODE:4>MFSK<SUBMODE:4>FST4 MFSK FST4
fldigi PSK31 <MODE:3>PSK<SUBMODE:5>PSK31 PSK PSK31

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 sidebands USB/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

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
nodelog Ready Ready Preview, Comment Jul 24, 2026 6:08am

Request Review

Sign up for free to 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