Add a custom management panel for Irrigation Unlimited - #239
Open
uspass wants to merge 106 commits into
Open
Conversation
NEW FILE -- part of the custom frontend panel, not present in upstream master.
NEW FILE -- part of the custom frontend panel, not present in upstream master.
NEW FILE -- part of the custom frontend panel, not present in upstream master (upstream ships no frontend assets).
NEW FILE (and entire frontend/ directory) -- not present in upstream master.
NEW FILE -- part of the custom frontend panel, not present in upstream master.
NEW FILE -- part of the custom frontend panel, not present in upstream master.
NEW FILE -- part of the custom frontend panel, not present in upstream master.
NEW FILE -- part of the custom frontend panel, not present in upstream master.
NEW FILE -- part of the custom frontend panel, not present in upstream master.
NEW FILE -- not present in upstream master.
Add _fmtTime helper to format schedule's time field for display, since time can now be a string (HH:MM:SS), a sun-event dict {sun, before?, after?}, or a cron dict {cron}. Previously the raw value was
interpolated directly into the template, producing "[object Object]"
for sun/cron schedules. Applied in both _schedList (zone schedules)
and _sqSchedList (sequence schedules).
Add optional `required` parameter (default false) to fText and fEntityPicker. When true, renders a red asterisk span next to the field's label, matching the visual convention used for fields that are vol.Required in IU's schema.
- Add .req: red asterisk style for required field labels (used by
fText/fEntityPicker's new `required` parameter).
- Add layout styles for the zone's multi-entity picker:
* .ep-header: label + add button on one row (flex space-between)
* .ep-header .ep-add:disabled: dimmed state when the add button is disabled (last row empty)
* .ep-multi / .ep-row: vertical stack of entity rows, each row
flex-aligned with its delete button
Add 10 new translation keys used by recent UI additions: Entity picker validation: - err.entity_id_req, err.entity_id_domain, err.entity_id_not_found - btn.add_entity (currently unused -- superseded by the inline + button in .ep-header; removed) Schedule validation: - err.sched_time_req, err.duration_req YAML export: - btn.copy, btn.copied, btn.download, err.copy_failed
Entity picker validation: - err.entity_id_req, err.entity_id_domain, err.entity_id_not_found - btn.add_entity (currently unused -- superseded by the inline + button in .ep-header; removed) Schedule validation: - err.sched_time_req, err.duration_req YAML export: - btn.copy, btn.copied, btn.download, err.copy_failed
Add 10 new translation keys used by recent UI additions: Entity picker validation: - err.entity_id_req, err.entity_id_domain, err.entity_id_not_found - btn.add_entity (currently unused -- superseded by the inline + button in .ep-header; removed) Schedule validation: - err.sched_time_req, err.duration_req YAML export: - btn.copy, btn.copied, btn.download, err.copy_failed
Add 10 new translation keys used by recent UI additions: Entity picker validation: - err.entity_id_req, err.entity_id_domain, err.entity_id_not_found - btn.add_entity (currently unused -- superseded by the inline + button in .ep-header; removed) Schedule validation: - err.sched_time_req, err.duration_req YAML export: - btn.copy, btn.copied, btn.download, err.copy_failed
Entity picker validation: - err.entity_id_req, err.entity_id_domain, err.entity_id_not_found - btn.add_entity (currently unused -- superseded by the inline + button in .ep-header; removed) Schedule validation: - err.sched_time_req, err.duration_req YAML export: - btn.copy, btn.copied, btn.download, err.copy_failed
Add 10 new translation keys used by recent UI additions: Entity picker validation: - err.entity_id_req, err.entity_id_domain, err.entity_id_not_found - btn.add_entity (currently unused -- superseded by the inline + button in .ep-header; removed) Schedule validation: - err.sched_time_req, err.duration_req YAML export: - btn.copy, btn.copied, btn.download, err.copy_failed
Owner
|
Hi @uspass, thank you for all your good work on this. I am currently travelling through the Red Centre slowly heading north. I have not had the time to review the changes. It's a little difficult given the resources at my disposal. In fact, there is a bit of a backlog at the moment as didn't expect to receive this many PR's all at once. I am happy for all the support I have been receiving recently. Thanks for everything. |
- Add set narrow(val) setter that reflects the narrow state as a host
attribute ("narrow") so that CSS :host([narrow]) ha-menu-button
can show the sidebar toggle on mobile.
- Detect HA Companion app (Android/iOS) in the constructor via
window.externalBus, window.webkit.messageHandlers.externalBus,
and io.robbie.HomeAssistant UA string. The Companion app always
passes narrow=false (it has native navigation), so we force
narrow=true to keep the hamburger visible.
- Set hass and narrow properties on ha-menu-button before appending
to the shadow root (avoids null-hass crash on LitElement's first
render cycle).
- Add set panel(val) setter stub for future use.
Replace the <a href="..." target="_top"> Integration button with a
nav-integration action that uses history.pushState() +
window.dispatchEvent(new Event("location-changed")).
target="_top" caused the HA Companion app to open an external browser
instead of navigating within the app. The location-changed event is
HA's standard routing mechanism and works correctly in both the
browser and the Companion app WebView.
Hide ha-menu-button by default; show it via :host([narrow]) when the panel host element carries the narrow attribute (set by the narrow setter in irrigation-unlimited-panel.js when HA signals mobile mode).
…ion app - Add ha-menu-button to the toolbar. Hidden by default via CSS; visible when the panel host carries the narrow attribute (set by the narrow setter in irrigation-unlimited-panel.js). - Replace <a href="..." target="_top"> Integration link with a plain button (data-a="nav-integration"). target="_top" caused the HA Companion app to open an external browser. The new handler in actions-mixin uses history.pushState() + location-changed event.
Author
|
Hi @smoki3, Thank you for reporting this! For any future issues, please open them directly on my GitHub repository — it makes it much easier for me to track, reference and follow up on bug reports. Thanks again! |
Restructure the panel layout so the toolbar is a sibling of the content wrapper instead of nested inside it: _html() returns toolbar + .wrap as siblings inside a .page flex column. Toolbar uses HA header variables with fallbacks (--header-height, --app-header-background-color, --app-header-text-color, --app-header-border-bottom) plus safe-area insets for the Companion app notch/status bar. Native layout order (menu button, title flex:1, actions right) with new .bhdr button style. Content scrolls independently under the sticky header. Direction credit: #10
The toolbar used box-sizing: content-box, so the 1px border-bottom was added on top of --header-height — 57px total vs HA's native 56px header, leaving a visible 1px gap at the sidebar boundary. Switch to border-box with the safe-area folded into the height: height: calc(var(--header-height, 56px) + var(--safe-area-inset-top, 0px)). Desktop aligns exactly (inset = 0); on notched phones the padding-top consumes the inset while content keeps the full header height. Reported in issue #10.
Omit 'enabled' key from YAML output for cleaner format.
Updated error handling for schedule time and duration requirements.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Add a custom management panel for Irrigation Unlimited
Summary
This PR adds a full custom sidebar panel ("Irrigation") that lets users manage all Irrigation Unlimited configuration — controllers, zones, sequences, schedules, adjustments, all-zones defaults, and global settings — directly from the Home Assistant UI, with no YAML editing required.
The upstream config-entry setup wizard / options flow / subentry flow (~760 lines in
config_flow.py) is replaced by an instant, zero-step config entry. All CRUD that wizard used to handle is now done through the new panel, backed by a persistent JSON store and a dedicated WebSocket API.The panel is fully multilingual (English / French / Italian / Romanian / Spanish, easy to extend) and shows a live "running" indicator on zones currently irrigating.
What's new
Backend
storage.py(new) —IUStore: persistent, panel-managed source of truth for all controller configuration (Store(STORAGE_VERSION, STORAGE_KEY)). Provides:to_iu_config_multi()/generate_yaml()— converts panel storage into the full multi-controller IU config (and equivalent YAML), applying:enabled: true,allow_manual: false,future_span: 3,anchor: "start",preamble/postamble: 00:00:00, ...)8:2→ stores/exports08:02:00)future_spanasint(avoids3.0in YAML)entity_idalways wrapped as a list (required by IU's iteration)weekday/month/zone_idrendered as YAML flow-style lists ([mon, wed, sat]){"zones": [...], "sequences": [...]}formatwebsocket_api.py(new) — WebSocket commands consumed by the panel for every CRUD operation (irrigation_unlimited/config,save_controller,save_zone,save_schedule,save_adjustment,save_sequence,save_sequence_zone,save_sequence_schedule,save_all_zones_config,save_global_config,generate_yaml, and matchingdelete_*). Every save/delete schedules a debounced (4s) reload of the config entry so the IU coordinator picks up changes without a HA restart.nameexists, its zones/sequences are imported automatically.config_flow.py(rewritten, 762 → ~30 lines) — single-step, no-form setup.async_set_unique_idensures only one config entry can exist (the panel manages multiple physical controllers internally).__init__.py(rewritten):/irrigation_unlimited_static→ bundledfrontend/) and a custom sidebar panel ("Irrigation",mdi:water).IUStoreand registers the WebSocket commands.entry.data/ HA-native subentries intoIUStore.async_unload_entrynow preservesstore/yaml_config/ panel & static-path / WS registration across reloads (previouslyhass.data[DOMAIN]was fully wiped on every reload, forcing re-registration on every panel save).async_remove_entryfor full cleanup (removes the sidebar panel) when the integration is deleted.manifest.json— added"integration_type": "hub".Frontend (new
frontend/directory)A vanilla-JS Web Component (ES modules, no build step), split for maintainability:
Features:
hass.language; adding another language is just a newtranslations/<lang>.json.entity_idis currentlyon, updated on everyhassupdate without a full re-render (no flicker).switch/input_boolean/valveentities.IUStore.generate_yaml().Documentation
All new files and all modified sections (vs. upstream
master) are documented with English docstrings/comments explaining what changed and why, to make future diffs against upstream easier.Testing
Breaking changes
None for new installs (instant setup). Existing installs with controllers configured via the old options/subentry flow or via YAML are migrated automatically into the new panel storage on first load.