Skip to content

refactor: rationalise channel data model field types and vendor mappings #52

Description

@pskillen

Problem

The internal Channel model was bootstrapped from OpenGD77 CPS columns and most optional fields are untyped strings in the UI and model. The channel edit form exposes free-text inputs for values that are really numbers or enums, often carrying OpenGD77-specific wire values that are opaque in a vendor-neutral tool.

Examples today:

Field Stored / UI today Desired internal semantics (illustrative)
power P2, Master (OpenGD77) 50% / 100% or low / high / full
bandwidthKHz "12.5" string 12.5 number or enum narrow / wide
colourCode string 115 integer
timeslot string 1 | 2 enum
squelch 75%, Disabled typed enum or numeric level
rxOnly Yes / No string boolean
transmitTimeout string seconds number
rxTone / txTone free text structured CTCSS/DCS/none

This makes validation weak, UI inconsistent, and export mappers pass vendor strings through unchanged rather than translating at the boundary.

Intended outcome

Manually rationalise each channel field — decide the vendor-neutral internal representation, document it, then update code and ETL.

Per-field deliverables

For each Channel field (and related entities as discovered):

  1. Decision — internal type, allowed values, default, whether vendor-specific values live only in import/export mappers.
  2. Documentation — update docs/features/data-model/README.md with typed definitions and semantics.
  3. Reference doc — where values are domain knowledge (power levels, tones, bandwidths), add or extend docs/reference/ entries.
  4. Model — update src/models/codeplug.ts types and channelFieldDefaults().
  5. Migration — schema version bump; migrate existing localStorage projects (map old string values → new types).
  6. Import — OpenGD77 (src/lib/import/opengd77/) maps vendor wire → internal model.
  7. Export — OpenGD77 (src/lib/export/opengd77/) maps internal model → vendor wire.
  8. UI — channel edit/detail/list use appropriate controls (Select, NumberInput, Checkbox, not TextInput) per field.
  9. Import/export docs — update docs/features/import/opengd77.md and export docs with mapping tables.

Suggested field groups (non-exhaustive)

  • RF: bandwidthKHz, power, rxTone, txTone, squelch, rxOnly
  • DMR: colourCode, timeslot, dmrId
  • Behaviour: transmitTimeout, voxEnabled, scanSkip (some already boolean)
  • Frequencies: consider numeric MHz internally vs string (separate decision)

Power is the canonical motivating example: internal powerLevel: 'low' | 'high' | 'full' (or %) with OpenGD77 export mapping low → P2, full → Master, etc.

Affected

  • src/models/codeplug.ts + migration
  • src/lib/import/opengd77/, src/lib/export/opengd77/
  • src/routes/channels/ (edit, detail, list)
  • src/lib/validation/ (if present) — typed validation rules
  • docs/features/data-model/, docs/features/import/opengd77.md, docs/features/export/
  • docs/reference/ — new field-value references as needed

Notes / dependencies

Out of scope

  • Automatic inference of field types from CSV headers without explicit design decisions.
  • Changing entity relationships (contacts, TG lists) — channel scalar fields only unless unavoidable.

Workflow note

Branch from origin/main, atomic conventional commits per field/group, PR linking Closes #. Use progress-tracking / feature-docs skills for a rationalisation checklist.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions