refactor(setup): split the controller form into Outputs and Inputs sections

The controller editor mixed outputs and inputs in one flat "Relays" block — relay
direction, the entry-button terminal, and the presence/radar terminal all on the same
row, with the lamp orphaned below. Reorganize into two labelled sections:

- Outputs — relays (barriers + lamp): relay # + direction, the button-light relay, and
  "Pulse open (ms)" (a relay hold-time, NOT an input setting — answers a recurring
  confusion).
- Inputs — terminals (button, sensor): per entry relay, the button + presence/radar
  terminals (kind, active-low) and cooldown, each labelled "For relay N", plus the
  board-wide "Inputs idle HIGH".

UI-only: storage stays config.relays[] (+ config.buttonLight), so saved booth configs
keep working with no migration. pulseMs/inputRestingHigh are pulled out of the generic
field loop and rendered in their section. i18n parity (sq + en).

Also passes the device id to testDevice() so an edited device's stored relay password
re-merges on Test connection (pairs with the secure-merge server change).

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
2026-06-24 19:04:05 +02:00
parent 420542ce10
commit fd15988a73
3 changed files with 259 additions and 135 deletions
+12
View File
@@ -359,6 +359,18 @@ export const en: Catalog = {
relaysTitle: "Relays on this controller",
relaysHint:
"Each relay opens one barrier. Set its direction; for transient entry, set which input terminal the entry button is wired to.",
outputsTitle: "Outputs — relays (barriers + lamp)",
outputsHint:
"Relays are OUTPUTS: each opens a barrier (or drives the button lamp). Set the relay number and direction. The input terminals (button, sensor) are in the Inputs section below.",
pulseOpenMs: "Pulse open (ms)",
pulseOpenHint: "How long a barrier relay is held open (jog). Applies to all barrier relays.",
inputsTitle: "Inputs — terminals (button, sensor)",
inputsHint:
"Inputs are TERMINALS the host READS: the entry button and the presence/radar sensor. Each belongs to an entry barrier — it triggers or gates that relay.",
inputsIdleHigh: "Inputs idle HIGH",
inputsIdleHighHint: "This board idles inputs HIGH (status 1111); a press pulls LOW.",
inputsForRelay: "For relay {{relay}}",
inputsNoEntryRelay: "No entry relay — add an 'Entry' or 'Entry + exit' relay in Outputs to assign terminals.",
relay: "Relay",
entryButtonTerminal: "Entry button on terminal",
presenceInput: "Presence sensor (terminal)",
+12
View File
@@ -368,6 +368,18 @@ export const sq = {
relaysTitle: "Relet në këtë kontrollues",
relaysHint:
"Çdo rele hap një barrierë. Cakto drejtimin e saj; për hyrje kalimtare, cakto në cilin terminal hyrës është lidhur butoni i hyrjes.",
outputsTitle: "Daljet — relet (barrierat + drita)",
outputsHint:
"Relet janë DALJE: secila hap një barrierë (ose ndez dritën e butonit). Cakto numrin e relesë dhe drejtimin. Terminalet hyrëse (butoni, sensori) janë te seksioni Hyrjet më poshtë.",
pulseOpenMs: "Kohëzgjatja e hapjes (ms)",
pulseOpenHint: "Sa kohë mbahet rele e barrierës e hapur (jog). Vlen për të gjitha relet e barrierave.",
inputsTitle: "Hyrjet — terminalet (buton, sensor)",
inputsHint:
"Hyrjet janë TERMINALE që hosti i LEXON: butoni i hyrjes dhe sensori i pranisë/radari. Secila i përket një barriere hyrëse — e gateron ose e nis atë rele.",
inputsIdleHigh: "Hyrjet në pushim HIGH",
inputsIdleHighHint: "Kjo pllakë i mban hyrjet HIGH në pushim (statusi 1111); një shtypje e ul në LOW.",
inputsForRelay: "Për rele {{relay}}",
inputsNoEntryRelay: "Asnjë rele hyrëse — shto një rele 'Hyrje' ose 'Hyrje + dalje' te Daljet që të caktosh terminalet.",
relay: "Rele",
entryButtonTerminal: "Butoni i hyrjes në terminalin",
presenceInput: "Sensori i pranisë (terminali)",