Problem
Channels today store a single name (OpenGD77 Channel Name) and a derived callsign (first whitespace-separated token of name). That works for import but does not model the operator's intent:
- Callsign — e.g.
GB7GL (repeater/site id, used for map labels and external lookups)
- Display name — e.g.
Glasgow (human-readable qualifier)
On export to CPS CSV, operators often want a composed wire name such as GB7GL Glasgow, with control over whether/how the callsign is included. This was scoped in #11 and deferred from PR #42; see docs/features/crud/crud-outstanding.md.
Intended outcome
Data model
- Treat
callsign and name (display name) as first-class, independently editable channel fields.
- Add a per-channel export name mode (working title — refine in UI copy), e.g.:
verbatim — export display name only (Glasgow)
callsign — GB7GL Glasgow (full callsign + space + display name)
callsign_suffix — last two letters + display name (GL Glasgow) — common convention
omit_callsign — same as verbatim; alias if clearer in UI
- Compose the OpenGD77
Channel Name on export from callsign + display name according to the selected mode.
- Respect CPS field length limits when composing (truncate or validate with a clear error — decide during implementation).
- Bump schema version and document migration (existing codeplugs: keep
name as display name, infer callsign best-effort from current name / callsign).
- While we're here, add a
description field (single line) and note (multi line). These will generally be internal to our models but some CPS may support
Import (best effort)
- On OpenGD77 CSV import, parse
Channel Name with a standard callsign regex (UK repeater / amateur allocation patterns).
- When a callsign prefix is recognised, split into
callsign + display name (name).
- Default export name mode to callsign + display name when a split was inferred; otherwise
verbatim.
- Round-trip: import
GB7GL Glasgow → edit display name → export → CPS still gets a valid composed name.
Current helper: extractCallsign() in src/lib/csv.ts (first token only) — replace/extend for regex-based split.
Export
- OpenGD77
Channels.csv Channel Name column is composed from internal fields + export mode (not a blind copy of name).
- Zone
Channel1…Channel80 wire names must use the same composition rules so FK integrity holds.
UI
- Channel create/edit: separate inputs for callsign and display name. add notes and description fields
- Export name mode control must make the feature obvious but optional — users who want CPS names verbatim set mode accordingly.
- Show a live preview of the exported wire name as fields/mode change.
- Channel detail/list: show both fields; band pills etc. unchanged. add col for description, hideable, default on.
Map
CodeplugMap and related helpers currently infer callsign from name (markerLabel, fullChannelName toggle in src/lib/channels.ts).
- After this change, use
channel.callsign directly (no inference from display name).
- Document map label behaviour in
docs/features/map/.
Documentation (deliver with implementation)
| Area |
Path |
| Display / naming conventions |
docs/reference/display-conventions.md |
| Data model |
docs/features/data-model/README.md + src/models/codeplug.ts |
| Import split logic |
docs/features/import/opengd77.md (and/or docs/features/import/) |
| Export composition |
docs/features/export/README.md + OpenGD77 export module docs |
| CRUD / progress |
docs/features/crud/crud-outstanding.md, crud-progress.md |
Acceptance criteria
Related
- Parent context: #11 (CRUD channels — export prefix bullet)
- Shipped without this: PR #42
- Data model today:
docs/features/data-model/README.md (callsign noted as derived)
Problem
Channels today store a single
name(OpenGD77Channel Name) and a derivedcallsign(first whitespace-separated token ofname). That works for import but does not model the operator's intent:GB7GL(repeater/site id, used for map labels and external lookups)Glasgow(human-readable qualifier)On export to CPS CSV, operators often want a composed wire name such as
GB7GL Glasgow, with control over whether/how the callsign is included. This was scoped in #11 and deferred from PR #42; seedocs/features/crud/crud-outstanding.md.Intended outcome
Data model
callsignandname(display name) as first-class, independently editable channel fields.verbatim— export display name only (Glasgow)callsign—GB7GL Glasgow(full callsign + space + display name)callsign_suffix— last two letters + display name (GL Glasgow) — common conventionomit_callsign— same as verbatim; alias if clearer in UIChannel Nameon export from callsign + display name according to the selected mode.nameas display name, infer callsign best-effort from currentname/callsign).descriptionfield (single line) andnote(multi line). These will generally be internal to our models but some CPS may supportImport (best effort)
Channel Namewith a standard callsign regex (UK repeater / amateur allocation patterns).callsign+ display name (name).verbatim.GB7GL Glasgow→ edit display name → export → CPS still gets a valid composed name.Current helper:
extractCallsign()insrc/lib/csv.ts(first token only) — replace/extend for regex-based split.Export
Channels.csvChannel Namecolumn is composed from internal fields + export mode (not a blind copy ofname).Channel1…Channel80wire names must use the same composition rules so FK integrity holds.UI
Map
CodeplugMapand related helpers currently infer callsign fromname(markerLabel,fullChannelNametoggle insrc/lib/channels.ts).channel.callsigndirectly (no inference from display name).docs/features/map/.Documentation (deliver with implementation)
docs/reference/display-conventions.mddocs/features/data-model/README.md+src/models/codeplug.tsdocs/features/import/opengd77.md(and/ordocs/features/import/)docs/features/export/README.md+ OpenGD77 export module docsdocs/features/crud/crud-outstanding.md,crud-progress.mdAcceptance criteria
callsignandname(display name) are editable independently in channel CRUDChannel Nameand zone member names consistently; respects length limitschannel.callsign, not derived-from-nameRelated
docs/features/data-model/README.md(callsignnoted as derived)