Automated release from CI pipeline
Changes:
feat(homecore-ui iter 4): live per-field validation + inline server errors
CRUD increment 4/6. The form now shows validity feedback on every
keystroke instead of only on Create click, makes the warning vs error
distinction visible (amber vs red), and propagates backend 4xx
responses into the form's own error surface.
frontend/src/components/EntityForm.ts (~80 LOC delta):
- Three new @State fields tracking per-field validity: _idValid,
_stateValid, _attrsValid (each is{ok:true} | {ok:false, level: 'err'|'warn', msg}or null when untouched). - Pure validators outside the class so they can be unit-tested:
validateEntityId, validateState, validateAttrs. - validateEntityId now warns (amber, not red) if the domain prefix
is outside the standard HA set. KNOWN_DOMAINS lists ~40 standard
domains (sensor, light, switch, binary_sensor, climate, cover,
fan, media_player, lock, camera, vacuum, climate, scene, script,
automation, input_*, person, device_tracker, zone, weather, etc.)- homecore-native domain. Unknown domains create entities anyway
(backend regex still passes them) but the operator sees the soft
signal.
- homecore-native domain. Unknown domains create entities anyway
- Sigils render below each field: ✓ green when ok, ✗ red on err,
! amber on warn. Field borders adopt the level color via
.invalid / .warn classes. - New public method
isValid()so the host can bind a disabled
state on its Save button (unused for now; ready for a follow-up). - New public method
setSubmitError(msg)so the host can surface
server-side rejection text inline in the form's red error block,
not just at the page top.
frontend/src/pages/Dashboard.ts (small delta):
_onSubmit()now callsthis._form?.setSubmitError(null)before
each attempt to clear stale text, and on non-2xx responses it
surfaces the server's body text inline viasetSubmitError.
Page-top error block is no longer hijacked for form errors.
Browser-verified end-to-end (real homecore-server :8123):
entity_id field:
BadID → red border + "must match domain.snake_case…"
light.kitchen_test → green ✓ "entity_id OK"
madeup_domain.foo → amber border + "unknown domain 'madeup_domain' — HA-standard…"
state field:
empty → red ✗ required
"on" → green ✓
attributes field:
empty → green ✓ (defaults to {})
[1,2,3] → red ✗ "must be a JSON object…"
{"key": → red ✗ "JSON parse: Unexpected end of JSON input"
{"friendly_name":"Test"} → green ✓
Server-error inline:
Force 401 via wrong token → form red block shows
"server rejected (401): unauthorized"
Successful create: still works, toast still shown, 0 console errors.
Co-Authored-By: claude-flow ruv@ruv.net
Docker Image:
ghcr.io/ruvnet/RuView:3f5a7411db2d449f603532435c5cc68079ffb222