Compare commits

..

526 Commits

Author SHA1 Message Date
Bram Kragten 72ad0f0f61 Change stat_types to supported ones for statistics 2022-09-28 14:36:05 +02:00
Bram Kragten 95bbf6e0d2 prevent fetching stats twice 2022-09-28 14:24:20 +02:00
Erik e31d1aace0 Drop period if invalid 2022-09-28 14:24:19 +02:00
Erik 726ed32626 Drop absolute sum option 2022-09-28 14:24:19 +02:00
Erik 87dedeb9b3 Add option to display state 2022-09-28 14:24:18 +02:00
Erik 0f534423a4 Address review comments 2022-09-28 14:24:18 +02:00
Erik 131957fbb3 Support displaying relative change in statistics graph cards 2022-09-28 14:24:17 +02:00
Erik Montnemery f9d119d33d Add icons for new sensor device classes (#13895) 2022-09-28 14:00:47 +02:00
Erik Montnemery d3b97ae91c Add support for overriding sensor weight unit (#13897) 2022-09-28 12:15:23 +02:00
Paul Bottein 5146fa1d9e Update join beta dialog (#13847) 2022-09-28 09:27:34 +00:00
Paul Bottein fc86a66c33 Use unique id for script (#13817)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-09-28 09:27:09 +00:00
Ignacio Hernandez-Ros 3959a7475c Bug Fix, can't create schedule on Sunday (#13876) 2022-09-28 09:08:30 +00:00
Paul Bottein 61d09072a7 Update Uninstall add-on dialog (#13898) 2022-09-28 11:02:09 +02:00
Paul Bottein 4a07d3d39b Update Restart add-on dialog (#13896) 2022-09-28 11:01:12 +02:00
Paul Bottein be30cdb51f Update change password dialog (#13888)
* Update change password dialog

* Improve wording

* Update modal for people page

* Remove useless async
2022-09-28 11:00:36 +02:00
Meow 894258d7b8 fixed duplicate unit_of_measurement (#13884) 2022-09-28 10:53:25 +02:00
Erik Montnemery 296d5f8ffe Add support for overriding sensor distance unit (#13831) 2022-09-28 09:11:34 +02:00
Erik Montnemery d1c2020ee4 Add support for overriding sensor speed unit (#13832) 2022-09-28 08:49:42 +02:00
Erik Montnemery 3c1b2aa4f3 Add support for overriding sensor volume unit (#13833) 2022-09-28 08:22:16 +02:00
Bram Kragten 17a11809de Prevent re-creation of custom panel when content was not changed (#13747) 2022-09-27 13:39:05 -04:00
David F. Mulcahey 3083d5b04c Clean up ZHA configuration UI (#13610) 2022-09-27 16:02:45 +02:00
Paul Bottein 0848c096b9 Fix script config form (#13878) 2022-09-27 15:40:38 +02:00
Paul Bottein 8d5c36a96a Fix more info with unnamed entity (#13859) 2022-09-27 15:39:49 +02:00
Paul Bottein cc76a6c5ed Add unique_id to entity registry (#13886) 2022-09-27 15:39:14 +02:00
Paul Bottein 01fd2787be Update add application credentials dialog (#13879) 2022-09-27 15:38:29 +02:00
Paul Bottein c79955e76a Add subview option to dashboard views (#13822) 2022-09-27 15:37:48 +02:00
dependabot[bot] 51874329d1 Bump actions/stale from 5.2.0 to 6.0.0 (#13874)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-26 14:15:58 +02:00
Erik Montnemery 6252955bb5 Simplify energy settings (#13846) 2022-09-23 09:03:17 +02:00
Paul Bottein 5422fda990 Update import blueprint dialog (#13840) 2022-09-22 15:24:15 +02:00
Paul Bottein db8bc9d34a Update delete automation dialog (#13765) 2022-09-22 15:22:20 +02:00
Paul Bottein 9f19bdde65 Allow proxy in codespaces env for core (#13842) 2022-09-22 15:21:42 +02:00
Bram Kragten 7336c1280f Fix select issues (#13839) 2022-09-22 15:19:59 +02:00
Bram Kragten 8e245c8a83 Fix move data disk dialog (#13845) 2022-09-22 15:19:34 +02:00
Allen Porter 5a150ac80d Prompt user to remove application credentials when deleting the integration configuration (#13159)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-09-22 10:47:08 +02:00
Paul Bottein eac13980ff Add navigation picker for dashboards (#13826)
* Add navigation picker for dashboards

* Rename to navigation

* Fix empty title and path

* Use hass panels instead of fetching dashboards

* Apply suggestions
2022-09-21 14:42:51 +02:00
Erik Montnemery 977fdd9fbb Add missing translations to statistics graph card editor (#13836) 2022-09-21 09:30:58 +00:00
Paul Bottein cedde3d6a2 Avoid overflow with combobox (#13835) 2022-09-21 11:23:22 +02:00
Bram Kragten 56c78ae108 Fix price units for gas (#13824) 2022-09-21 11:16:19 +02:00
Erik Montnemery 82a641a200 Fix unit columns for statistics developer tool (#13830) 2022-09-21 11:15:57 +02:00
Erik Montnemery 04181e9c28 Adapt energy to core changes (#13779) 2022-09-20 17:44:03 -04:00
Paul Bottein 4b8960c236 Update Move datadisk (not found) dialog (#13812) 2022-09-19 12:39:05 +00:00
Paul Bottein fc104e7280 Fix name in confirmation delete dialog (#13815) 2022-09-19 12:34:06 +02:00
Paul Bottein 8c125f4dee Update Delete automation trigger/condition/action dialog (#13813) 2022-09-19 12:33:27 +02:00
Paul Bottein b93f457d53 Add destructive style to scene delete button (#13814) 2022-09-19 12:32:17 +02:00
Paul Bottein e8ce6ad919 Improve confirm unsaved dialog (#13807) 2022-09-19 11:35:33 +02:00
Salamandar 0ce695577c Fix shortcuts for non-qwerty keyboard layouts (revert #12892) (#13190) 2022-09-19 08:21:45 +00:00
Franck Nijhof 50b67751d9 Fix time trigger description pointing to entity (#13786) 2022-09-19 10:11:56 +02:00
Franck Nijhof 05515f21c3 Add timer states to state selector (#13788) 2022-09-19 10:11:10 +02:00
Paul Bottein 063c377797 Fix back button on automation editor on Safari (#13806) 2022-09-19 10:10:50 +02:00
dependabot[bot] aee11da671 Bump actions/stale from 5.1.1 to 5.2.0 (#13805)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-19 09:22:59 +02:00
Paul Bottein 5fcb219fcd Update delete script dialog (#13768) 2022-09-16 16:40:41 +02:00
Paul Bottein a97dfbb51f Update delete blueprint dialog (#13770) 2022-09-16 16:40:25 +02:00
Paul Bottein c5f4e8ffdd Update certificate information dialog (#13773) 2022-09-16 16:40:10 +02:00
Paul Bottein 7ffd30643a Update delete person dialog (#13763) 2022-09-16 16:39:51 +02:00
Paul Bottein dcfcd54f10 Update delete scene dialog (#13767) 2022-09-16 16:39:29 +02:00
Paul Bottein 3b103619ec Update delete resource dialog (#13764) 2022-09-16 16:38:29 +02:00
Paulus Schoutsen 614c1574ca Type outgoing messages on EM and add matter (#13775) 2022-09-16 08:33:21 -04:00
Paul Bottein e1e3f9d925 Update delete and disable integration dialog (#13772) 2022-09-16 13:52:26 +02:00
Paul Bottein 0ba4a07b92 Update webhook dialog (#13774) 2022-09-16 13:50:44 +02:00
Paul Bottein 5a5f31b32c Update restart Home Assistant dialog (#13776) 2022-09-16 13:49:15 +02:00
Paul Bottein ff92768973 Update reboot shutdown host dialog (#13777) 2022-09-16 13:48:55 +02:00
Erik Montnemery bb0529ecd2 Improve statistics graph editor (#13630) 2022-09-16 13:48:10 +02:00
Paul Bottein bc62e9372b Update delete dashboard dialog (#13762) 2022-09-16 13:40:41 +02:00
Erik Montnemery 087a897cbe Add comment about input number not supporting initial (#13758) 2022-09-16 13:40:08 +02:00
Franck Nijhof 589efa8cc5 Exclude scenes, schedules & updates from scenes (#13759) 2022-09-16 13:39:38 +02:00
Bram Kragten c93179c307 Use primary color for active tabs in traces (#13760) 2022-09-16 13:38:45 +02:00
Paul Bottein 9e416e829c Do not recreate entities list at each re-order (#13751) 2022-09-16 13:38:31 +02:00
Paul Bottein e13c632afa Update delete user dialog (#13761)
* Add destructive confirmation style

* Update delete user dialog
2022-09-15 16:21:25 +02:00
Erik Montnemery 544c8fe3bb Improve StatisticsChart to only fetch needed metadata (#13617) 2022-09-15 11:58:26 +00:00
Paul Bottein 81b21f874b Improve cover entity definition (#13750) 2022-09-15 12:31:36 +02:00
Bram Kragten ea319d55ef Allow to disable a select option (#13618) 2022-09-15 12:00:00 +02:00
Paul Bottein 8c03bbdccc Improve light entity definition (#13744) 2022-09-15 11:58:36 +02:00
Paul Bottein 321914d53a Fix empty hardware when fetching hardware info (#13738) 2022-09-14 09:13:32 +00:00
Paul Bottein 490d46396e Fix system blank page (#13731) 2022-09-14 09:08:37 +02:00
Bram Kragten 3c62bc9b18 Fix hass subpage (#13730) 2022-09-14 09:02:51 +02:00
Erik Montnemery 48b10005e3 Revert "Add initial field to the helper input_number in UI" (#13713) 2022-09-13 14:53:55 -04:00
Bram Kragten b3d64fc52a use the correct inputmode (#13722) 2022-09-13 18:53:19 +00:00
Bram Kragten 23e5a47b3b improve duration rendering for state trigger (#13723) 2022-09-13 20:49:39 +02:00
uvjustin 5d4c090b26 Bump hls.js to v1.2.3 (#13718) 2022-09-13 20:15:01 +02:00
Pierre b84240edbc fix: add previous repeat action configuration on change (#13717) 2022-09-13 20:00:20 +02:00
Paul Bottein f4dc74b2e8 Show confirm dialog when clicking traces (#13716) 2022-09-13 19:59:35 +02:00
Joakim Sørensen c95d19299b Fix open config flow when coming from a my link (#13720) 2022-09-13 19:58:32 +02:00
Paul Bottein 7696df56ac Don't use selector inside choose action (#13705) 2022-09-13 10:43:38 +02:00
Paul Bottein 771733d326 Fix rtl support for hass subpage layout (#13702) 2022-09-13 10:42:15 +02:00
Joakim Sørensen 4f3c708109 Guard repairs subscription (#13708) 2022-09-13 10:41:19 +02:00
Erik Montnemery d2078a7e50 Fix customizing sensor unit (#13710) 2022-09-13 10:40:48 +02:00
Joakim Plate d70cb24722 Revert "Either show range or fix target temperature... #13638 (#13706) 2022-09-13 10:40:18 +02:00
Paul Bottein 6902537666 Fix script config editor (#13703) 2022-09-12 11:04:07 -05:00
Joakim Plate 9ea1f61971 Display entity friendly name for disabled entities (#13696) 2022-09-12 15:55:03 +02:00
Paul Bottein 782c95cf04 Fix empty value for state picker (#13699) 2022-09-12 15:53:18 +02:00
Erik Montnemery d5d6216cfe Move recorder statistics API to data/recorder.ts (#13672)
* Move recorder statistics API to data/recorder.ts

* Fix import

* prettier
2022-09-12 13:23:02 +02:00
Felipe Santos 1086c85964 Use newspaper icon for change log button (#13668) 2022-09-12 12:22:49 +02:00
krazos 47c0901df2 Eliminate redundant "for" in trigger description (#13669) 2022-09-12 11:57:53 +02:00
J. Nick Koston d323ab6726 Add support for subscribing to config entry changes (#13585) 2022-09-11 10:22:26 -05:00
Erik Montnemery 07b5856190 Don't call deprecated history/* statistics API (#13658) 2022-09-08 16:03:35 -04:00
Bram Kragten 462dee0351 use input instead of change (#13660) 2022-09-08 17:43:36 +02:00
Paul Bottein f181a085de Move automation trace actions to overflow menu (#13656) 2022-09-08 12:00:52 +02:00
Joakim Sørensen bf5589b88d Guard more of the hardware panel (#13650) 2022-09-07 19:59:08 -05:00
Bram Kragten fd431f36f7 Fix state picker (#13644) 2022-09-07 16:43:04 +02:00
Bram Kragten 7acf3a049e Bumped version to 20220907.0 2022-09-07 16:33:01 +02:00
Bram Kragten cfb0e8b39e cleanup script editor (#13639) 2022-09-07 16:26:32 +02:00
Bram Kragten a3abbf3812 remove tabs from trace pages (#13640) 2022-09-07 16:26:22 +02:00
Philip Allgaier 980156d23a Add separator option to overflow icon menu (#13627) 2022-09-07 13:56:18 +00:00
Paul Bottein 37c2a3636e Improve scene layout (#13641) 2022-09-07 15:33:17 +02:00
Raman Gupta b682d13486 Change typing of zwave_js API return based on lib version bump (#13393) 2022-09-07 08:13:13 -05:00
Philip Allgaier 7f82b90c25 Either show range or fix target temperature control in climate more-info (#13638) 2022-09-07 14:27:54 +02:00
Paul Bottein 3e9d6ea2c5 Bring reorder mode to script sequence (#13636) 2022-09-07 14:25:06 +02:00
Paul Bottein 57c5c1c191 Remove re order mode for blueprint automation editor (#13637) 2022-09-07 14:23:42 +02:00
Paul Bottein b553a3fd92 Some fixes for automation picker and editor (#13634) 2022-09-07 07:47:56 -04:00
Paul Bottein d1964e92ea Some fixes for script picker and editor (#13635)
* Show error when user try to delete or duplicate yaml only script

* Use same layout as automation
2022-09-07 07:47:24 -04:00
Zack Barett a889969bb8 Fix Back button on Safari and disable information menu item until saved (#13633) 2022-09-07 01:53:09 +00:00
Paul Bottein f80b2c578b Fix run script translation (#13626)
fix translation
2022-09-06 17:42:15 +00:00
Bram Kragten d13c6d3e7b Bumped version to 20220906.0 2022-09-06 17:38:39 +02:00
Bram Kragten e78c875e8e Add last activated column to scenes data table (#13622) 2022-09-06 17:34:49 +02:00
Bram Kragten 5e8c54b00f Update ha-config-helpers.ts 2022-09-06 16:50:02 +02:00
Paul Bottein 71bc74893f Add overflow menu for script picker (#13620) 2022-09-06 16:48:22 +02:00
Paul Bottein df72e5099e Add overflow menu for scene picker (#13621) 2022-09-06 16:48:09 +02:00
Paulus Schoutsen e6862daa38 Avoid script editor dirty on load (#13619) 2022-09-06 15:33:53 +02:00
Paul Bottein 66db8c999f Open external device configuration url to a new tab/window (#13613)
* Open external device configuration url to a new tab/window

* Remove rel in action options
2022-09-06 10:24:03 +00:00
Joakim Sørensen 00bc315fc1 Fetch OS info from Supervisor if we do not return anything for hardware (#13614)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-09-06 09:48:41 +00:00
Paul Bottein f461825a59 Fix icon picker in dialog (#13616) 2022-09-06 09:48:13 +00:00
Bram Kragten 8c98326e31 Fix netlify demo deploy (#13611) 2022-09-05 20:24:09 -04:00
Bram Kragten 7bb619b0c3 Update translations 2022-09-06 01:26:34 +02:00
Bram Kragten 07bc9081b8 dont remove id from automation config (#13609) 2022-09-05 22:46:30 +00:00
Philip Allgaier 91fa5972d1 Prevent combo box issues with duplicate labels (#13608) 2022-09-06 00:33:39 +02:00
Bram Kragten ccd617d68e Bumped version to 20220905.0 2022-09-05 19:39:30 +02:00
Bram Kragten 8a7f35cee6 Improve rename automation dialog (#13601) 2022-09-05 19:38:51 +02:00
Bram Kragten e510e5b371 Link logbook row to trace if available (#13599)
* Link logbook row to trace if available

* Update ha-logbook-renderer.ts
2022-09-05 19:36:09 +02:00
Paul Bottein aa6ee0f6d2 Fix icon picker reset by hass update (#13587)
* Fix icon picker reset by hass update

* Update src/components/ha-icon-picker.ts

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

* Only update when not opened

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-09-05 19:01:20 +02:00
Bram Kragten f3449c4d9b Add description to automation editor (#13603) 2022-09-05 19:00:54 +02:00
Matthias de Baat 3c289deb21 Add remove, delete, add and create guidelines (#13593)
Co-authored-by: Philip Allgaier <philip.allgaier@gmx.de>
2022-09-05 18:28:54 +02:00
Paul Bottein 847d163cc8 Disable close on outside click for rename + mode dialogs (#13602) 2022-09-05 16:26:32 +00:00
Paul Bottein 28d11703fc Reorder overflow menu (#13596) 2022-09-05 18:18:58 +02:00
Bram Kragten 1f003ae3be Remove tabs from area and device pages (#13600) 2022-09-05 18:18:32 +02:00
chpego a57d7813e7 typo dialogs (#13598) 2022-09-05 15:55:48 +00:00
J. Nick Koston 5842b10a10 Handle logbook updates where the new records are in the middle of the old records (#13595) 2022-09-05 17:47:48 +02:00
Paul Bottein 8ee9655bd5 On larger screens, move traces button out of the overflow menu (#13597) 2022-09-05 17:44:10 +02:00
Paul Bottein 3ef567dcd5 Automation change mode dialog (#13591) 2022-09-05 17:43:34 +02:00
Joakim Sørensen 37f6b4f6be Show hardware if hassio or hardware (#13594) 2022-09-05 16:47:28 +02:00
Philip Allgaier a817faae54 Add back blank before percent sign ("%") based on language (#13590)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2022-09-05 12:49:21 +00:00
Paul Bottein ab745f6e8e Reorder automation elements (#13548) 2022-09-05 08:19:38 -04:00
Bram Kragten 02d608b704 only show cpu and mem when available (#13589) 2022-09-05 08:12:04 -04:00
Bram Kragten 310df387e7 Fix tag trigger (#13588) 2022-09-05 08:08:52 -04:00
Bram Kragten fe8e79a67f Remove tabs from scene and script edit page (#13592) 2022-09-05 08:03:00 -04:00
Paulus Schoutsen 8ffe676827 Move edit description into rename dialog (#13580) 2022-09-05 10:49:07 +02:00
David F. Mulcahey f032d0dbcf Fix ZHA visualization page (#13584) 2022-09-04 22:25:03 -04:00
Philip Allgaier 81cc745c0a Align wording in automation and script editor overflow menus (#13575) 2022-09-03 13:22:42 -04:00
Michel van de Wetering 43f9c9ebc9 Add mediadescription for channel media type (#13434) 2022-09-03 11:44:02 +02:00
Michel van de Wetering a9d1feb196 Hide soundmode when mediaplayer is off or unavailable (#13347) 2022-09-03 11:41:24 +02:00
Paulus Schoutsen 72aea57105 Bumped version to 20220902.0 2022-09-02 16:14:53 -04:00
Philip Allgaier 031ecf5be8 Align visuals of automation and script editor after redesign (#13567) 2022-09-02 13:03:53 -04:00
Paul Bottein 93e7927686 Fix automation trace link (#13563) 2022-09-02 13:02:50 -04:00
Paul Bottein 320d8e6190 Improve blueprint editor layout (#13564) 2022-09-02 13:02:36 -04:00
Paul Bottein efa4f65686 Add information in overflow menu (#13570) 2022-09-02 13:02:01 -04:00
Paul Bottein ec257710ff Add overflow menu to automation picker (#13569) 2022-09-02 13:01:05 -04:00
Paulus Schoutsen ffad6f340f Fix some descriptions (#13562) 2022-09-01 21:43:30 -05:00
Zack Barett 9f9b0b6457 Bumped version to 20220901.0 (#13560) 2022-09-01 20:11:10 +00:00
Zack Barett a4227680de Fix Unable to select last slot (#13559) 2022-09-01 19:54:32 +00:00
Zack Barett 5cfd263617 Fix Sunday issue and add minutes to events (#13556) 2022-09-01 16:06:51 +00:00
Bram Kragten 430e671901 unique-id -> id (#13552) 2022-09-01 11:51:38 -04:00
Ernst Klamer 8fcd396445 Add icon for device class moisture (#13553) 2022-09-01 11:48:04 -04:00
Erik Montnemery e273b6b659 Improve delete device button and confirmation dialog (#13500) 2022-09-01 10:38:56 -05:00
Bram Kragten 2751adf440 remove duplicate controls blueprint automation (#13554) 2022-09-01 10:37:22 -05:00
Matthias de Baat d661450121 Typo on dialogs page (#13555) 2022-09-01 10:36:56 -05:00
Steve Repsher 4511ded205 Add semantic heading to script editor (#13546) 2022-09-01 16:19:08 +02:00
Erik Montnemery 2bf0c5d72d Only update device class if changed by user (#13551) 2022-09-01 12:25:32 +00:00
Steve Repsher 604e5d5e09 Add semantic headings to automation editor (#13542)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-08-31 14:15:14 -05:00
Bram Kragten 774aee406c Fix tag trigger (#13540)
* Fix tag trigger

* Fix
2022-08-31 12:28:50 -04:00
Zack Barett 775837b60f Bumped version to 20220831.0 (#13539) 2022-08-31 18:28:31 +02:00
Bram Kragten 030b2b921a Format duration object (#13538) 2022-08-31 16:24:24 +00:00
Bram Kragten 229bc26327 Don't fire change on tag picker when not changed (#13537) 2022-08-31 16:08:35 +00:00
Bram Kragten 99e85173eb Change padding buttons entity settings (#13536) 2022-08-31 15:48:54 +00:00
Bram Kragten be0c22d7ae Fix header mobile automation editor (#13534) 2022-08-31 15:42:00 +00:00
Zack Barett fee1092a08 Fix Selection on IOS (#13533) 2022-08-31 15:40:03 +00:00
Bram Kragten d041bd9fd3 use device and area names in service call description (#13532) 2022-08-31 15:30:44 +00:00
Matthias de Baat 93debac19a Add dialogs guidelines (#13526)
* Add dialogs guidelines

* Updated the Buttons and X-icon text
2022-08-31 11:00:19 -04:00
Bram Kragten 3fc94106b8 Add entities, devices and areas to hass (#13530) 2022-08-31 13:15:21 +00:00
Bram Kragten e976f9c119 Simplify action descriptions (#13529) 2022-08-31 12:48:28 +00:00
Bram Kragten be4dcbe405 Fix dialog placement and overflow (#13527) 2022-08-31 07:55:26 -04:00
Paul Bottein c116ad67ed Fix multiple sortable (#13522) 2022-08-31 12:01:36 +02:00
Erik Montnemery 1e19799da9 Improve handling of units in energy dashboard (#13454) 2022-08-31 11:30:50 +02:00
Paulus Schoutsen 9b2dcbdb59 Fix script/size_stats 2022-08-30 21:53:17 -04:00
Steve Repsher ae4a37f23a Combo-box accessibility and other fixes (#13496) 2022-08-30 21:50:04 -04:00
puddly e463a997c1 Add a button for launching the ZHA options flow to reconfigure the radio (#13506)
* Add a button for launching the ZHA options flow to reconfigure the radio

* Remove unnecessary whitespace

* Rename `Reconfigure` to `Migrate Radio`

* Rename `Download Network Backup` to `Download Backup`
2022-08-30 21:46:20 -04:00
Zack Barett 92c8de307d Add CPU and Memory Graphs to hardware page (#13399)
* CPU and Memory Graphs

* localize

* Comments

* Always show the graphs

* Use Subscribe Mixin
2022-08-30 21:45:37 -04:00
Zack Barett c751b0b759 Fix schedule bug (#13521) 2022-08-30 21:45:00 -04:00
Erik Montnemery cb5621032d Allow controlling an input_select in unknown state (#13524) 2022-08-30 14:24:05 -04:00
Paul Bottein e861460318 Fix drag and drop entities on firefox (#13518) 2022-08-30 11:34:18 -04:00
Zack Barett 8fd99fcb15 Fix Schedule Helper UI (#13515) 2022-08-29 21:51:07 -04:00
Bram Kragten 260855abbb fix buttons at bottom of entity settings dialog (#13517) 2022-08-29 15:56:57 -05:00
Paulus Schoutsen 3648c8c07a Revert "Add redirect_uri to each interaction with login flow (#13389)" (#13504) 2022-08-29 20:23:40 +02:00
Yosi Levy e74fd5fcdc Fix RTL issue on date selector in lower resolutions & color slider (#13326) 2022-08-29 20:23:06 +02:00
uvjustin 2e46b04204 Bump hls.js to v1.2.1 (#13497) 2022-08-29 20:22:05 +02:00
Franck Nijhof 989a0b9173 Fix media players with unknown state not being able to browse media (#13502) 2022-08-29 12:14:56 -04:00
Joakim Sørensen 80a2a7b989 Adds fixed schedule entity icon (#13514) 2022-08-29 11:19:14 -04:00
Franck Nijhof 2547a975f6 Always show description field in automation editor (#13503) 2022-08-26 13:25:01 +00:00
Franck Nijhof 35fa763086 Automation icon tweaks (#13495) 2022-08-25 20:39:21 -04:00
Franck Nijhof 44e38cd24e Redesign automation editor main settings (#13488) 2022-08-25 19:34:39 +00:00
Franck Nijhof ad58d16dfa Move condition test button into overflow menu (#13478) 2022-08-25 18:57:29 +00:00
Franck Nijhof 98352ae7b7 Replace service call icon (#13491) 2022-08-25 14:23:23 -04:00
J. Nick Koston b9fbad663d Bump home-assistant-js-websocket to 8.0.0 (#13492) 2022-08-25 18:03:34 +00:00
J. Nick Koston fd166fa89e Show when an integration is being setup in the UI (#13446)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2022-08-25 14:01:06 -04:00
Franck Nijhof 88decba851 Move all destructive device actions to the bottom of the overflow menu (#13490) 2022-08-25 18:33:09 +02:00
Franck Nijhof 8db1881a93 Hide else/default in if/choose actions (#13480) 2022-08-25 10:49:32 -05:00
Franck Nijhof 0038f54cea Add missing icon to ZHA device remove action (#13489) 2022-08-25 10:43:54 -05:00
Yosi Levy a3d80f1280 RTL heater+state fixes (#13366) 2022-08-25 14:20:04 +00:00
Joakim Sørensen 1c05bc6380 Catch reload issues (#13487) 2022-08-25 15:02:30 +02:00
Erik Montnemery 5d1536030a Refactor getStatisticLabel (#13486) 2022-08-25 12:53:16 +00:00
Erik Montnemery a8833a5ec1 Use name from statistics metadata in energy config panel (#13474) 2022-08-25 13:47:44 +02:00
Erik Montnemery 6446534e0b Use name from statistics metadata in energy dashboard (#13469) 2022-08-25 13:47:32 +02:00
Erik Montnemery d64c81a123 Use name from metadata in statistics card (#13451)
* Use name from metadata in statistics card

* Refactor to use getStatisticLabel
2022-08-25 13:47:16 +02:00
Paulus Schoutsen 80e7993923 Move restored entity warning up and use ha-alert (#13477) 2022-08-25 13:09:31 +02:00
Franck Nijhof 700af72303 Add icon to trigger/condition/action editor rows (#13481) 2022-08-25 13:04:40 +02:00
Joakim Sørensen 255cb23c7d Show homeassistant when creating partial backup (#13482) 2022-08-25 11:26:56 +02:00
Florian Rüchel 669f7efa97 Fix scripts docs link (#13484)
In home-assistant/home-assistant.io#22391 the editor docs were removed
making the current link invalid. This points the docs link to the syntax
docs one level up.
2022-08-25 11:01:52 +02:00
Paulus Schoutsen 166d6f1c88 Show graph for zone in more info (#13475) 2022-08-24 09:18:45 -05:00
Paulus Schoutsen d64ade3848 Scroll to new added trigger/condition/row (#13473) 2022-08-24 08:58:29 -05:00
Franck Nijhof c2542a3baa Use yarn to resolve lint-staged in pre-commit (#13470) 2022-08-24 09:27:35 -04:00
Franck Nijhof 6b7c00edbc Change integration enable/disable icons to match automations (#13472) 2022-08-24 08:00:33 -05:00
Franck Nijhof 89c6fa7383 Conditionally add extra divider in integration card overflow menu (#13468) 2022-08-24 08:00:13 -05:00
Franck Nijhof ca91f71d2e Remove default actions/conditions from parallel and if actions (#13467) 2022-08-24 07:58:12 -05:00
Bram Kragten 25e0c05723 Fix padding navigation list (#13466) 2022-08-24 11:53:51 +02:00
Steve Repsher 8fd5273fae Fix various issues in time/duration input (#13462) 2022-08-24 11:25:29 +02:00
Zack Barett 807bb10199 Add some Trigger Descriptions (#13460)
Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-08-24 09:18:50 +00:00
Franck Nijhof 5ce81232b5 Fix automation/script conditions editor (#13465) 2022-08-24 10:59:27 +02:00
Steve Repsher a1bc748bc1 Fix accessibility of settings and system navigation (#12845) 2022-08-23 23:45:44 -04:00
Franck Nijhof be169f9c83 Redesign trigger/condition/action overflow menus (#13453)
* Redesign trigger/condition/action overflow menus

* Reorder items, changed enable/disable icons, cleanup aria

* Simplify menu item names
2022-08-23 18:26:38 -04:00
Franck Nijhof ed82ae9f68 Add config entry selector (#13432)
* Add config entry selector

* Let backend filter by integration

* Add to gallery

* Adjust translation

* Fix imports

* Rename in gallery as well

* Fix typo in localize key

* Prettier
2022-08-23 18:26:15 -04:00
Franck Nijhof 8bcbeb299b Add icons to integration action overflow menu (#13457) 2022-08-23 21:37:37 +02:00
Franck Nijhof fc1481d365 Add icons to device action overflow menu (#13455)
* Add icons to device action overflow menu

* Update size of meta icon

* Tweak naming as suggest by Paulus

* Missed on suggestion, also adjusted

* Delete device -> Delete

* View network

* Rename key

* Prettier

Co-authored-by: Zack <zackbarett@hey.com>
2022-08-23 19:13:22 +00:00
Paulus Schoutsen 2475f6bd41 Glue percent sign (#13458) 2022-08-23 15:45:08 +00:00
Franck Nijhof dff3ffe935 Add support for renaming actions, conditions and triggers (#13444) 2022-08-23 17:21:16 +02:00
puddly 1616911ba9 Display ZHA network settings and allow downloading backups (#13415) 2022-08-23 10:24:38 -04:00
Franck Nijhof 8d18fb79fb Use icons in add trigger/condition/action menus (#13452) 2022-08-23 09:13:39 -05:00
Zack Barett f5b44656cf Update a few Condition Descriptions (#13404)
* Update a few Describe-conditions

* Update to multiple states
2022-08-23 10:12:55 -04:00
Zack Barett c82782fa1b Update Automation Picker Table (#13405) 2022-08-23 09:47:15 -04:00
Franck Nijhof ab14cf9e9b Use trigger alias in trace timelines (#13447) 2022-08-23 08:58:05 -04:00
Franck Nijhof c0051aeb68 Tweak displayed action/condition/trigger names (#13445) 2022-08-22 20:25:27 -05:00
Franck Nijhof 44422086d7 Add alias support to all triggers (#13442) 2022-08-22 16:08:32 -05:00
Franck Nijhof 738367a7c7 Use alias instead of description in case set in actions/conditions (#13441) 2022-08-22 13:27:13 -05:00
Franck Nijhof 5fb2e3316a Use number selector for above & below in numeric trigger/condition (#13422) 2022-08-22 11:16:11 -05:00
Franck Nijhof 82f48d106f Use template selector in numeric state templates (#13428) 2022-08-22 12:04:36 -04:00
Steve Repsher bbc5b02a22 Tighten UI localize key exceptions (#13430) 2022-08-22 12:04:02 -04:00
Paulus Schoutsen dfface6904 Merge more info "info" and "history" like before (#13425) 2022-08-22 13:56:48 +00:00
Franck Nijhof 9ed0cb3011 Use duration input for timeout in wait_for_trigger action (#13426)
* Use duration input for timeout in wait_for_trigger action

* Specify event type
2022-08-22 08:55:26 -04:00
Franck Nijhof 4b54cb4a35 Make updates more distinct recognizable by device name (#13433) 2022-08-22 08:17:52 -04:00
Franck Nijhof 1b5c30712e Rename exclude_attributes to hide_attributes for clarity (#13436) 2022-08-22 11:25:17 +02:00
Joakim Sørensen 7d3d800d4c Fix progressbar margins (#13435) 2022-08-22 10:46:07 +02:00
Franck Nijhof d4262ecb09 Use dropdown mode for script mode selector (#13429) 2022-08-20 22:00:20 -04:00
Franck Nijhof ec7dea93a0 Allow days in calendar trigger offset (#13427) 2022-08-20 18:38:44 -04:00
Franck Nijhof aa2641d5c9 Add exclude attributes support to attribute selector (#13421)
* Add exclude attribute support to attribute selector

* Fix typing

* Fix rebase f-up

* Revert const removal

* Make exclude_attributes readonly and fix some propert mismatches

Co-authored-by: Zack <zackbarett@hey.com>
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com>
2022-08-20 14:54:42 -04:00
Paulus Schoutsen 5ecde44243 Do not hide overflow in expansion panel when expanded (#13423) 2022-08-20 18:38:03 +00:00
Paulus Schoutsen 209ba79823 Expand trigger/condition/row when menu item changes editor (#13424) 2022-08-20 14:29:43 -04:00
Steve Repsher 52a1594969 Remove all exceptions from supervisor localize keys (#13402) 2022-08-20 13:37:57 -04:00
Steve Repsher 24509425ca Fix some localize key type errors in lovelace editors (#13403) 2022-08-20 13:36:58 -04:00
ildar170975 7e5cd9a1c8 Logbook card: place a gap between an icon/image & a text (#13348) 2022-08-20 14:29:29 +00:00
Franck Nijhof 8b13a9ff2e Add attribute support to state selector (#13420) 2022-08-20 09:24:11 -05:00
Paulus Schoutsen b33c546610 Combine more info and entity registry editor (#13416) 2022-08-19 21:27:07 -05:00
Franck Nijhof 38fd6108b4 Keep formatted attribute name in attribute selector (#13413) 2022-08-19 08:44:42 -05:00
Franck Nijhof 57fdea19fd Fix trigger state attribute selector (#13410) 2022-08-19 08:44:02 -05:00
Franck Nijhof d2a19e04ef Add state selector (#13411) 2022-08-19 09:20:13 -04:00
Steve Repsher 196456d0c4 Add translations to nightly artifacts (#13409) 2022-08-19 08:57:58 -04:00
Paulus Schoutsen 5c16447eed Fix DOM reuse for trigger/condition/action (#13407) 2022-08-19 08:05:15 -04:00
Paulus Schoutsen f3d92ba0e0 Fix Gallery menu expansion (#13408) 2022-08-18 23:32:56 -04:00
Steve Repsher 088b3587e0 Remove string exception for localize keys (#13354) 2022-08-18 12:43:15 -04:00
Paulus Schoutsen ede9d8a073 Add back learn more labels to automation editor (#13401) 2022-08-18 16:17:19 +00:00
Paulus Schoutsen 8c71885b4c Add support for the file selector (#13382) 2022-08-18 11:43:43 -04:00
Paulus Schoutsen 47b820d28f Collapse automation/script editor sections by default (#13390) 2022-08-18 14:04:35 +00:00
Steve Repsher d7b888f761 Fix localize key types related to form schemas (Group 3) (#13400)
* Fix key type errors for card editors (Round 4)

* Fix key type errors for remaining form schemas
2022-08-17 23:57:26 -04:00
Paulus Schoutsen 12e57dfcae Allow testing describe functionality in the gallery (#13398) 2022-08-17 13:20:35 -05:00
Steve Repsher 9a1fc02755 Fix localize key types related to form schemas (Group 2) (#13342) 2022-08-17 11:01:05 -05:00
Steve Repsher eb4dbef610 Bump husky & lint-staged and prevent translation edits (#13392) 2022-08-17 08:09:07 -04:00
Paulus Schoutsen 33ce27de02 Bumped version to 20220816.0 2022-08-16 17:18:38 -04:00
Paulus Schoutsen 089f531492 Add redirect_uri to each interaction with login flow (#13389) 2022-08-16 17:17:18 -04:00
uvjustin 3aa813e391 Bump hls.js to v1.2.0 (#13383) 2022-08-16 09:10:18 -05:00
Zack Barett a989eb1c66 Fix Target Selector (#13380) 2022-08-13 20:56:15 -05:00
alvinchen1 e0448be24d Add initial field to the helper input_number in UI (#13378) 2022-08-13 17:29:33 -04:00
Franck Nijhof 651cafc464 Allow Markdown and description placeholder usage in data field descriptions (#13377)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-08-13 18:57:28 +00:00
Zack Barett 38607a6410 Add UI for Schedule Helper (#13375) 2022-08-12 13:58:08 +00:00
Steve Repsher 9046c0d0bf Merge pull request #13372 from steverep/fix-more-keys
Fix more bad or missing localize keys
2022-08-10 16:48:12 -04:00
Steve Repsher 589cec10f6 Fix bad key for quick bar hint
Also fixed a bunch of lit plugin errors.
2022-08-10 16:25:01 -04:00
Steve Repsher dba9658658 Fix bad key for add entities to view 2022-08-10 15:59:15 -04:00
Steve Repsher d21bdf2807 Add missing key in logbook card 2022-08-10 15:30:58 -04:00
Steve Repsher 3fe5075ad4 Add missing key in input_select helper dialog 2022-08-10 12:32:46 -04:00
Steve Repsher f76a3ea2ce Merge pull request #13364 from steverep/fix-random-bad-keys 2022-08-09 12:50:50 -04:00
Steve Repsher e95a5ebbbf Merge changes in repair flow header 2022-08-09 12:22:47 -04:00
Steve Repsher ae28eb3813 Fix bad key in system information 2022-08-09 12:04:06 -04:00
Steve Repsher b0807cb80c Fix bad keys in repair flow dialog 2022-08-09 11:55:10 -04:00
Steve Repsher 95231554d5 Add missing key for required tag name 2022-08-09 11:01:51 -04:00
Steve Repsher f3b543f46c Fix bad key on error screen 2022-08-08 18:21:39 -04:00
Steve Repsher 9eb81e2211 Add missing key for area not found 2022-08-08 17:59:15 -04:00
Franck Nijhof 1322ff9295 Process description placeholders in titles for repairs flows (#13362) 2022-08-08 17:36:46 -04:00
Zack Barett 5f169b48d9 Merge pull request #13360 from steverep/fix-blueprint-target-types 2022-08-08 12:27:03 -05:00
Steve Repsher 75d05cdb0e Fix key type errors in target picker 2022-08-08 12:12:13 -04:00
Steve Repsher b444d0030f Fix key type errors for blueprints 2022-08-08 12:10:56 -04:00
Zack Barett e241b20378 Merge pull request #13357 from steverep/fix-some-card-keys 2022-08-08 09:38:27 -05:00
Joakim Sørensen ca28feca80 Missing import and refresh correct collection (#13358) 2022-08-08 10:16:13 +02:00
Zack Barett f5d9a7d662 Merge pull request #13353 from home-assistant/Make-sure-we-have-supervisor.addon 2022-08-07 16:56:33 -05:00
Steve Repsher 3d236a8f49 Fix key type errors for cloud TTS 2022-08-07 15:34:26 -04:00
Steve Repsher 0ebeec0db6 Fix key type errors for media player 2022-08-07 15:33:08 -04:00
Steve Repsher d23d774ec1 Fix some key type errors in cards 2022-08-07 15:28:22 -04:00
Joakim Sørensen 0d5b86e2b6 Check store for addons when using my link (#13352) 2022-08-07 12:56:44 -04:00
ludeeus 825558c8db Make sure we have supervisor.addon 2022-08-07 16:53:09 +00:00
Zack Barett 12239d7fe3 Merge pull request #13344 from steverep/update-vaadin 2022-08-05 13:52:56 -05:00
Zack Barett 6eac6aef18 Merge pull request #13284 from raman325/ws_api 2022-08-05 12:56:47 -05:00
Steve Repsher a79d6b6a4d Upgrade vaadin to 23.1.5 for combobox accessibility 2022-08-05 12:31:07 -04:00
Steve Repsher 1d47303127 Separate supervisor localize key exceptions and disallow string (#13317) 2022-08-05 15:39:19 +02:00
Steve Repsher 150bc00c31 Fix localize key types related to form schemas (Group 1) (#13258) 2022-08-05 15:37:54 +02:00
Zack Barett d4232a2256 Bumped version to 20220802.0 (#13328) 2022-08-02 17:06:00 +02:00
Zack Barett f7e348c19b Fix Automation Creation Dialog (#13322) 2022-08-02 13:48:22 +00:00
Zack Barett f44fd35b90 Fix input and number more info dialog (#13321) 2022-08-02 15:26:17 +02:00
Erik Montnemery dac1d76bd2 Offer to remove statistics for entities with unsupported state class (#13325) 2022-08-02 11:12:05 +00:00
Franck Nijhof 0ab823bcf5 Adjust MDI icon for Repairs menu (#13324) 2022-08-02 09:33:36 +02:00
dependabot[bot] 65e952aaeb Bump actions/stale from 5.1.0 to 5.1.1 (#13313)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-02 09:25:58 +02:00
Zack Barett cfdf043444 Add ability to auto open system health with params (#13303)
* Add ability to auto open system health with params

* Update my link

* Update url when opening dialog

* comment
2022-08-02 09:23:30 +02:00
Zack Barett ecc1bf5206 Merge pull request #13319 from home-assistant/fix-device-page-strip 2022-08-01 16:03:50 -05:00
Zack Barett 57d664d87d Merge pull request #13318 from home-assistant/fix-create-helper 2022-08-01 15:47:11 -05:00
Zack cf2cd4043d Fix Device Page name stripping 2022-08-01 15:41:01 -05:00
Bram Kragten 98761cab3f Fix create helper dialog
Fixes #13274
2022-08-01 22:05:52 +02:00
Erik Montnemery 4a622f9424 Tweak suggested_value in HA-form (#13316) 2022-08-01 09:25:33 +00:00
Zack Barett c27e3325d9 Bumped version to 20220728.0 (#13300) 2022-07-28 10:10:28 -05:00
Zack Barett 08efc2fdd1 Update dialog with status line and other stuff (#13293) 2022-07-28 15:10:05 +00:00
Zack Barett 53519ae8ab Fix Dark Mode Map when set in Dashboard card (#13297) 2022-07-28 10:00:37 -05:00
Zack Barett 9baeabed19 Add integration dialog Scroll bar styles (#13299) 2022-07-28 09:54:41 -05:00
Zack Barett f3229bb8a7 Update Show Skipped/ignored in updates/repairs, update dialog of integration startup time (#13296) 2022-07-28 10:39:16 +02:00
Franck Nijhof 86c971b76a Add My support for Repairs (#13294) 2022-07-28 02:07:07 +02:00
Paulus Schoutsen afc69cb270 Render brand icon for repairs based on issue_domain (#13290) 2022-07-27 22:53:59 +02:00
Paulus Schoutsen a379d29a6c Remove non fixable from repair dialog (#13292) 2022-07-27 15:50:07 -05:00
Franck Nijhof 0769b14566 Add Bluetooth as discovery source (#13291) 2022-07-27 20:30:51 +00:00
Paulus Schoutsen 1dc68b72da Pass translation placeholders to repair title translations (#13289) 2022-07-27 19:30:22 +00:00
Bram Kragten c08be957ce Merge branch 'master' into dev 2022-07-27 12:23:47 +02:00
Bram Kragten 140e269697 Bumped version to 20220727.0 2022-07-27 12:22:43 +02:00
Bram Kragten 7c18d5aa0e Use subscribe to fetch repair issues (#13285) 2022-07-27 12:15:31 +02:00
Yosi Levy 1acdc9cd6c Various RTL fixes (#13268) 2022-07-27 11:40:50 +02:00
Yosi Levy 7501849044 Fix conversation RTL + text-alignment (#13264) 2022-07-27 11:39:44 +02:00
Yosi Levy 26ed13e548 RTL - Humidifier more info location (#13253) 2022-07-27 11:38:35 +02:00
Steve Repsher 086c33d8b3 Fix localize key types to remove user groups exception (#13259) 2022-07-27 11:37:52 +02:00
Zack Barett c73677f15d Move System Information to Repairs (#13281)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-07-27 09:23:55 +00:00
Zack Barett f7090583ac Update Repairs to new design (#13276)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-07-27 09:06:38 +00:00
Zack Barett 68517018cc Add IP Information Dialog (#13283)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-07-27 08:47:03 +00:00
Raman Gupta 62a0a64554 Update zwave_js WS API commands 2022-07-27 00:08:06 -04:00
Zack Barett adf3fa6a0e Use new subscribe mixin for the sidebar to show counts of repairs (#13282)
* Use new subscribe mixin for the sidebar

* spelling
2022-07-26 15:43:46 -05:00
Bram Kragten b443ec0af5 Repair issue fixes (#13272) 2022-07-25 15:37:33 +02:00
Zack Barett b9ae0e72b1 Add Ignore Action + dialog updates (#13254) 2022-07-25 11:36:00 +02:00
Zack Barett 63ea8e6568 Allows for My to support Supported Brands (#13256) 2022-07-25 11:35:13 +02:00
Steve Repsher 5be624f45d Fix localize key types to remove config_entry exception (#13257) 2022-07-22 11:01:44 +02:00
Bram Kragten 38f19b6180 Repair: load translations for all integrations with issues (#13252) 2022-07-21 09:52:44 -05:00
Steve Repsher c99f00ba50 Setup stronger type for localize key (#13244) 2022-07-21 13:13:11 +00:00
Zack Barett ce5776f59d Add Repairs to Settings (#13249)
Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-07-21 14:48:37 +02:00
Steve Repsher 12ff70020a Fix more bad localize keys (#13250) 2022-07-21 12:17:29 +02:00
Felipe Santos 5d605447a5 Support more icons for media players (#12997)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-07-21 12:16:00 +02:00
Michael Irigoyen 6d88d46ce4 Update Material Design Icons to v7.0.96 (#13175)
* Update Material Design Icons to v7.0.96

* Fetch updated MDI packages
2022-07-21 11:43:48 +02:00
Bram Kragten cbe2643146 Use translation_key for repairs (#13246) 2022-07-20 11:52:55 -05:00
Steve Repsher d332b8ab14 Fix bad localize keys (#13245)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-07-20 18:34:09 +02:00
Bram Kragten adfef05110 Bump contrast and brightness of dark mode map (#13243) 2022-07-20 14:15:34 +00:00
Yosi Levy ca6a7bfbe2 Additional RTL energy fixes (#13182) 2022-07-20 14:37:48 +02:00
Franck Nijhof a22f96a481 Migrate repairs to repairs API (#13242) 2022-07-20 14:34:57 +02:00
Yosi Levy 688109524d RTL fixes - media, attributes (#13241) 2022-07-20 11:14:50 +02:00
Sven Serlier 62dd7111ce Update design.home-assistant.io (#13240)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-07-20 08:24:52 +00:00
Zack Barett 1267575f62 Merge pull request #13235 from home-assistant/fix-builds
Stringify Python version to use 3.10 vs 3.1
2022-07-19 23:25:39 -05:00
Paulus Schoutsen b7da4dc68f Stringify Python version to use 3.10 vs 3.1 2022-07-19 21:11:21 -07:00
Zack Barett 826474518f Merge pull request #13228 from voydz/lovelace-map-autofit 2022-07-19 16:44:48 -05:00
Maximilian Ertl a4b92fef3a Correctly set "allow-downloads" flag on iframes (#13218) 2022-07-19 20:59:45 +02:00
Bram Kragten d41159591c Change map styles to "Voyager" (#13227) 2022-07-19 20:56:50 +02:00
Felix Rudat cb256bc386 Add auto_fit config option to lovelace map card 2022-07-19 17:45:48 +02:00
Zack Barett bd50d6a6a3 Start the Repairs dashboard (#13192)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-07-19 14:25:47 +00:00
Bram Kragten 05418fc83b Fix dev tools event (#13225) 2022-07-19 11:17:13 +00:00
Franck Nijhof 8b675cdbba Remove unused mypy config from pyproject (#13224) 2022-07-19 13:14:20 +02:00
Franck Nijhof 36b4909950 Bump Python to 3.10 (#13223) 2022-07-19 12:28:57 +02:00
Raman Gupta 157b3ba5f2 Clean up zwave_js device actions logic (#13185) 2022-07-19 12:11:05 +02:00
Yosi Levy 72443b4f24 RTL card fixes (#13207) 2022-07-19 12:09:50 +02:00
J. Nick Koston 1c7d3fe610 Sync frontend recoverable states with core (#13197) 2022-07-19 12:09:20 +02:00
Franck Nijhof 6ac4560b36 Use YAML in developer tools events (#13222) 2022-07-19 12:07:51 +02:00
Zack Barett 9309a4c7bc Update language when ZHA or Zwave arent installed (re: supported brands) (#13191) 2022-07-19 11:44:02 +02:00
Franck Nijhof b582a4d014 Bump node to 16 (#13221) 2022-07-19 11:39:08 +02:00
Zack Barett e4d233afa8 Filter Integration in Target and Area selectors + clean up some code (#13202) 2022-07-18 22:07:55 +02:00
dependabot[bot] b131b255ec Bump actions/stale from 3.0.13 to 5.1.0 (#13212)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-18 17:09:37 +02:00
Kendell R 20bdb9ff35 Use theme default font for charts (#13210)
* Use theme default font for charts

* Prettier
2022-07-18 15:35:51 +02:00
Zack Barett 666ef7a978 Merge pull request #13199 from home-assistant/2022.7-hotfix 2022-07-14 17:26:04 -05:00
Zack 24a97347df Version Bump 2022-07-14 17:13:02 -05:00
Zack Barett 0825d5c64e Fix Suggested Value in HA-Form (#13173) 2022-07-14 17:11:53 -05:00
Erik Montnemery 535e752ec7 Correct display of barometric pressure and rain (#13183) 2022-07-14 17:11:39 -05:00
Zack Barett b611a58fce Add support for Supported Brands (#13184) 2022-07-13 17:51:17 +02:00
Zack Barett 24e54554ad Fix History Graph Name not being friendly (#13179) 2022-07-13 11:48:52 +02:00
Erik Montnemery d23fca4dd1 Correct display of barometric pressure and rain (#13183) 2022-07-12 16:13:29 -05:00
Paulus Schoutsen 729e2f5248 Use entity name in device info page (#13165)
* Use entity name in device info page

* Adjust to new format

* Use latest API

* Fix types

* Fix CI?

Co-authored-by: Zack <zackbarett@hey.com>
2022-07-11 19:07:07 -07:00
Zack Barett 437723c6a6 Fix Number Selector Label (#13178) 2022-07-12 01:05:47 +00:00
Bram Kragten a30c8205b1 Update dialog styles (#13132) 2022-07-11 15:07:10 -05:00
puddly c50cf78bb4 Allow stale ZHA coordinator entries to be deleted (#13154)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-07-11 13:14:37 -05:00
Zack Barett be52ba0ea9 Fix Suggested Value in HA-Form (#13173) 2022-07-11 09:46:32 -05:00
Yosi Levy 55e9ebc4d2 Energy panel/cards - RTL fixes (#13171) 2022-07-11 15:47:22 +02:00
Bram Kragten 29c3fb0f92 Fix energy demo (#13172) 2022-07-11 08:44:34 -05:00
Erik Montnemery 7c3cd9d88d Merge pull request #13170 from home-assistant/number_customize_units
Allow customizing number unit of measurement
2022-07-11 14:49:47 +02:00
Erik 4881d699e3 Allow customizing number unit of measurement 2022-07-11 14:05:23 +02:00
Joakim Sørensen 414db83359 Hide homeassistant from partial restore if no version (#13168) 2022-07-11 12:55:43 +02:00
Joakim Sørensen cd4f6e19f4 Await backup restore (#13167) 2022-07-11 12:50:37 +02:00
Joakim Sørensen da709cbbd1 Add hacs_repository my redirect (#13153) 2022-07-11 09:06:45 +02:00
Bram Kragten ee9ca16eb5 Merge pull request #13138 from home-assistant/dev 2022-07-07 15:29:24 +02:00
Raman Gupta 399efca411 Only show firmware update warning if no firmware update is in progress (#13068) 2022-07-07 15:03:11 +02:00
Bram Kragten f8bccf9e79 Bumped version to 20220707.0 2022-07-07 15:02:08 +02:00
Bram Kragten 87aab72b63 opti search params history 2022-07-07 15:01:29 +02:00
Bram Kragten 24688ba18e fix reload history when no selection made (#13137) 2022-07-07 14:58:51 +02:00
Zack Barett e8086b6a6f Refactor History Panel Code a bit (#13129)
Co-authored-by: D3v01dZA <caltona1@gmail.com>
2022-07-07 14:27:28 +02:00
Bram Kragten 4358437278 Merge pull request #13126 from home-assistant/dev
20220706.0
2022-07-06 18:56:12 +02:00
Zack Barett e0a9c57a54 Bumped version to 20220706.0 (#13125) 2022-07-06 18:55:52 +02:00
Bram Kragten e63953ecbc Fix scene editor (#13123) 2022-07-06 13:50:37 +00:00
Bram Kragten 72af200190 Remove localstorage from history, use url (#13122) 2022-07-06 08:44:28 -05:00
Zack Barett 2094ae534b Fix History Panel when no entities are found (#13103) 2022-07-06 01:05:40 +02:00
Bram Kragten f6d6fd179f Merge pull request #13099 from home-assistant/dev
Bump to 20220705.0
2022-07-05 18:55:51 +02:00
Zack Barett 153ebb2a20 Bumped version to 20220705.0 (#13098) 2022-07-05 18:40:26 +02:00
Michael Irigoyen 5d58e52eea Update MDI to v6.9.96 (#13096) 2022-07-05 18:38:24 +02:00
Zack Barett 5038f9c3c6 Some Updates to the History Panel (#13095) 2022-07-05 15:31:17 +00:00
Zack Barett b285fda61b Move Sign out back to Account Card for Cloud (#13094) 2022-07-05 17:15:09 +02:00
D3v01dZA 6cd38472cd Multiple entities on history panel bugfix and additional improvements (#13045)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-07-05 09:23:38 -05:00
Erik Montnemery 8fd5f53f96 Exclude config and diagnostic entities from scenes (#13072)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-07-05 08:49:05 -05:00
Zack Barett b70eee77ef Remove config Path from about (#13049)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-07-05 09:41:40 +00:00
Raman Gupta 4148b8c7aa Get rid of dupe HTML in zwave_js firmware upload dialog (#13067) 2022-07-05 11:26:38 +02:00
Zack Barett e22dd0c49d Fix Energy Compare Translations (#13055)
* Fix Energy Compare Translations

* Fix alert
2022-07-05 11:23:46 +02:00
dependabot[bot] 30a254f98f Bump actions/checkout from 2 to 3 (#13075)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 10:45:41 +02:00
dependabot[bot] 8fcb3a017b Bump actions/setup-python from 2 to 4 (#13078)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 10:28:53 +02:00
dependabot[bot] 5e29c7efa9 Bump dessant/lock-threads from 2.0.1 to 3.0.0 (#13077)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 10:26:46 +02:00
dependabot[bot] b6cc3e3ef0 Bump actions/setup-node from 2 to 3 (#13080)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 10:04:22 +02:00
dependabot[bot] 184bdc0c85 Bump github/codeql-action from 1 to 2 (#13081)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 10:04:02 +02:00
Sven Serlier f7fb731dc8 Add dependabot (#13073)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
2022-07-05 09:40:57 +02:00
Raman Gupta 77977f64a3 Don't check zwave_js node firmware update capabilities (#13066) 2022-07-03 13:45:19 -07:00
Franck Nijhof e8da573ba2 Only upload nighlty wheel build artifact (#13064) 2022-07-02 08:49:27 -05:00
Franck Nijhof 07332bf155 Fix version detection in build env to allow for nightly builds (#13062) 2022-07-02 00:22:54 +02:00
Franck Nijhof f3c7583bf7 Add nightly frontend builds (#13061) 2022-07-01 14:30:40 -07:00
Paulus Schoutsen 1cc02415d3 Fix rendering config entry titles (#13060)
* Fix rendering config entry titles

* Fix location height

* Only fetch installation type when user not created yet
2022-07-01 13:52:56 -05:00
Paulus Schoutsen 6ca3f06ea0 Merge pull request #13057 from home-assistant/hide-sun-onboarding
Do not show the sun during onboarding
2022-07-01 11:05:45 -07:00
Paulus Schoutsen 198e2b7bdf Do not show the sun during onboarding 2022-07-01 10:23:23 -07:00
Zack Barett 5a68e2c977 Merge pull request #13053 from home-assistant/improve-autocompletion
improve autocompletion
2022-06-30 14:57:42 -05:00
Sven Serlier d9d29db560 Fix demo labels (#13033) 2022-06-30 21:51:23 +02:00
Zack Barett 124c6dc2b8 Merge pull request #13048 from emufan/patch-1 2022-06-30 14:49:52 -05:00
Bram Kragten 0f3886e053 improve autocompletion 2022-06-30 21:41:58 +02:00
Paulus Schoutsen 68bb3558b4 Merge pull request #13051 from home-assistant/dev 2022-06-30 10:22:17 -07:00
Zack Barett b8bd15aa33 Bumped version to 20220630.0 (#13050) 2022-06-30 10:17:43 -07:00
Zack Barett ed39aa6a7c Merge pull request #13046 from Nardol/no_fix_em_dash 2022-06-30 08:20:41 -05:00
Zack Barett 405cae9b5f Merge pull request #13047 from piitaya/feat/ha-code-editor-autocomplete-icon-option 2022-06-30 08:19:54 -05:00
emufan 3ca2cbb3f9 Update ha-config-integrations.ts 2022-06-30 15:03:34 +02:00
piitaya c295ae56ab separate autocomplete options in ha-code-editor 2022-06-30 11:27:04 +02:00
piitaya 830364721b separate autocomplete options in ha-code-editor 2022-06-30 11:22:30 +02:00
Patrick ZAJDA 19089213e3 Add em dash instead of blank when no fix is needed in statistics
Signed-off-by: Patrick ZAJDA <patrick@zajda.fr>
2022-06-30 11:12:35 +02:00
Zack Barett b633067e5c Merge pull request #13041 from home-assistant/Fix-About-Page 2022-06-29 17:50:43 -05:00
Zack 1b8874cbd4 Fix Translation on About Page 2022-06-29 15:27:54 -05:00
Zack Barett a5f8ce85ba Merge pull request #13032 from home-assistant/dev 2022-06-29 11:25:03 -05:00
Bram Kragten 56eacf5733 20220629.0 (#13030)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
Co-authored-by: ImgBotApp <ImgBotHelp@gmail.com>
Co-authored-by: foreign-sub <51928805+foreign-sub@users.noreply.github.com>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
Co-authored-by: Philip Allgaier <philip.allgaier@gmx.de>
Co-authored-by: Philip Allgaier <mail@spacegaier.de>
Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Raman Gupta <7243222+raman325@users.noreply.github.com>
Co-authored-by: wizmo2 <wizmo.home@yahoo.com>
Co-authored-by: Yosi Levy <37745463+yosilevy@users.noreply.github.com>
Co-authored-by: RoboMagus <68224306+RoboMagus@users.noreply.github.com>
Co-authored-by: loeffelpan <34661317+loeffelpan@users.noreply.github.com>
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com>
Co-authored-by: Joakim Sørensen <ludeeus@ludeeus.dev>
Co-authored-by: Allen Porter <allen@thebends.org>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
Co-authored-by: Josh McCarty <josh@joshmccarty.com>
Co-authored-by: imgbot[bot] <31301654+imgbot[bot]@users.noreply.github.com>
Co-authored-by: Brandon Rothweiler <brandonrothweiler@gmail.com>
Co-authored-by: James Baker <j.baker@outlook.com>
Co-authored-by: Sven Serlier <85389871+wrt54g@users.noreply.github.com>
Co-authored-by: Alessandro Ghedini <alessandro@ghedini.me>
Co-authored-by: Emanuele <55278049+elax46@users.noreply.github.com>
Co-authored-by: Pascal Vizeli <pascal.vizeli@syshack.ch>
Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
Co-authored-by: Kristján Bjarni <kristjanbjarni@gmail.com>
Co-authored-by: D3v01dZA <caltona1@gmail.com>
2022-06-29 11:22:17 -05:00
Bram Kragten 9324061d05 Add auto completion for mdi icons to code editor (#13022)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-06-29 16:12:16 +00:00
Bram Kragten eafcbdc65b Merge branch 'master' into dev 2022-06-29 18:02:42 +02:00
Zack Barett 0175522c17 Bumped version to 20220629.0 (#13029) 2022-06-29 18:00:50 +02:00
D3v01dZA cff3f51d34 Multiple entities on history panel (#9946)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-06-29 10:39:38 -05:00
Kristján Bjarni 0f580a91c9 Add optional label for gauge segment (#12960)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-06-29 10:36:18 -05:00
Erik Montnemery 389f50b29a Merge pull request #13028 from home-assistant/add_wind_speed_units
Support knots and ft/s in weather wind speed
2022-06-29 16:34:53 +02:00
J. Nick Koston b689bb8fcf Pause the logbook stream when scrolled (#13026) 2022-06-29 13:49:44 +00:00
Erik 36f067ede4 Support knots and ft/s in weather wind speed 2022-06-29 15:47:28 +02:00
Zack Barett c2178622dd Add Switch as X Icon and Threshold Icon (#13024) 2022-06-29 09:03:04 +02:00
Zack Barett 014448e7ea Update about page (#12653)
Co-authored-by: Philip Allgaier <mail@spacegaier.de>
2022-06-29 08:56:30 +02:00
Zack Barett 08eff0509a Fix General Config Zone update on Mobile (#13011)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-06-29 08:54:19 +02:00
Marc Mueller 62d0882e82 Support editable installs (#12838)
* Support editable installs

* Update setup.cfg
2022-06-28 17:25:21 -07:00
Sven Serlier 86a574dbbd Fix demo labes (#13025) 2022-06-28 18:22:31 +00:00
Yosi Levy 71ac4620c5 RTL Fixes (#13023) 2022-06-28 09:28:34 -05:00
Zack Barett f611049517 Remove Restart Moved Tip (#13009) 2022-06-27 10:55:12 +02:00
Zack Barett 45fa8c272f Remove TTS moved Tip (#13010) 2022-06-27 10:54:49 +02:00
Yosi Levy 28a1c97571 Various card RTL fixes (#13006) 2022-06-24 10:18:39 -05:00
Zack Barett d9a5ae0cf1 Bumped version to 20220624.0 (#13008) 2022-06-24 03:10:20 +00:00
Raman Gupta c03849d30b Only show zwave_js firmware action if no other updates in progress (#13002)
* Only show zwave_js firmware update action if no other updates in progress

* readability
2022-06-23 19:19:20 -05:00
Pascal Vizeli 535fe2686b Use new wheels builder (#13001) 2022-06-23 14:11:06 +02:00
Emanuele 709bc87a36 Fix missing translatable energy texts (#12877)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
Co-authored-by: Philip Allgaier <philip.allgaier@gmx.de>
2022-06-23 11:02:02 +02:00
Raman Gupta 2812b467ec Add manual firmware update support for zwave-js devices (#12910)
* Subscribe to zwave_js node status updates in device panel

* Add typing for message

* Add manual firmware update support for zwave-js devices

* Tweaks based on upstream changes

* Tweaks

* remove unused CSS

* Update zwave_js.ts

* Tweaks after somet esting

* Bold device name instead of italic, catch abort errors and show the message

* Incorporate new commands tweak the UI and messaging

* Add a warning about firmware updates potentially bricking a device, and use Promise.all where possible

* Better typing so we can clean up code

* Additional tweaks

* Remove commented out code

* change style a bit

* prettier

* Be more precise with progress because it always helps the user if they can see progress

* nit

* Update src/translations/en.json

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Bram's review

* Only ask for firmware target if there is more than one available

* Only offer another firmware update if the original firmware update failed

* Only offer firmware upgrade if node is ready and pass firmware capabilities into dialog so we don't have to make call again

* Use ha-form

* Add comment

* Switch schema name

* Import icon

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2022-06-23 10:51:52 +02:00
Erik Montnemery 7d118a5715 Allow customizing weather units (#12947)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
Co-authored-by: foreign-sub <51928805+foreign-sub@users.noreply.github.com>
2022-06-23 10:48:39 +02:00
Alessandro Ghedini 8bd7370a02 Show moisture/flood alerts in the Area card (#12978) 2022-06-22 19:26:32 -05:00
Alessandro Ghedini 9fa8a96d09 Show humidity sensor values in Area card (#12976) 2022-06-22 10:45:38 -05:00
Alessandro Ghedini 508d1fffef Show icon for temperature values in Area card (#12977) 2022-06-22 10:42:39 -05:00
J. Nick Koston 3633daa814 Use websocket endpoint to fetch config entries (#12964) 2022-06-21 13:10:39 -05:00
Sven Serlier 05346ae9fc Fix demo labels (#12984) 2022-06-21 10:36:42 -05:00
Yosi Levy ea667cf0b9 RTL safari fix (#12963) 2022-06-21 11:03:22 +02:00
James Baker 048ac3965e Fix grammar in NFC settings tab description (#12979) 2022-06-20 17:24:07 +00:00
Brandon Rothweiler 276b6f4d1f Fix a bug in the climate entity more info card (#12973) 2022-06-20 14:29:42 +02:00
Paulus Schoutsen e765d7749c Update text around updating cloud entity exposed defaults (#12954) 2022-06-20 14:28:32 +02:00
imgbot[bot] 9a3b4d6df2 [ImgBot] Optimize images (#12985)
*Total -- 298.28kb -> 241.37kb (19.08%)

/gallery/public/images/logo-with-text.png -- 66.64kb -> 46.13kb (30.79%)
/gallery/public/images/clearspace.png -- 43.46kb -> 31.99kb (26.39%)
/gallery/public/images/using-our-logo.png -- 32.47kb -> 24.92kb (23.24%)
/gallery/public/images/logo-variants.png -- 34.86kb -> 26.78kb (23.18%)
/gallery/public/images/logo.png -- 27.30kb -> 21.50kb (21.25%)
/gallery/public/images/sunflowers.jpg -- 93.54kb -> 90.05kb (3.73%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>

Co-authored-by: ImgBotApp <ImgBotHelp@gmail.com>
2022-06-20 14:27:18 +02:00
Raman Gupta 529e27992e Subscribe to zwave_js node status updates in device panel (#12916)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2022-06-19 14:22:02 -05:00
Bram Kragten 6c5cf2a0ec Fix energy panel in Demo (#12906) 2022-06-16 10:00:52 -05:00
Josh McCarty a4cb270f09 Ensures inputmode is set properly for alarm code inputs (#12953) 2022-06-16 09:58:29 -05:00
Bram Kragten 5160a1f55c Don't make dialog boxes fullscreen on mobile (#12928) 2022-06-14 11:04:09 -07:00
Allen Porter 6a3a0db338 Fix application credentials description when loaded from config flow (#12940) 2022-06-14 11:03:40 -07:00
Erik Montnemery 765d4eb3b4 Revert Use unit system definitions for weather units (#10657) (#12946) 2022-06-14 11:03:05 -07:00
Erik Montnemery cc09e24d66 Fix customizing sensor units (#12948) 2022-06-14 11:02:15 -07:00
Joakim Sørensen e7848262ea Split store and installed calls (#12921)
* Split store and installed calls

* Fix issue when installing

* Remove supervisor.addons usage

* one more

* Update core

* Comments
2022-06-11 11:04:54 +02:00
Paulus Schoutsen 0926202eca Clean up unused var (#12930) 2022-06-10 21:10:33 -07:00
Yosi Levy e83af02410 Use ha-list-item in config updates (#12922) 2022-06-10 16:43:31 +02:00
Raman Gupta 74d6a52fa9 Remove unused zwave_js functions (#12915) 2022-06-10 16:43:04 +02:00
Allen Porter 5baa975632 Add application credentials description placeholder (#12869) 2022-06-10 16:42:20 +02:00
Joakim Sørensen 4ad49ef07f Move to supervisor store API (#12911)
* Move to supervisor store API

* Add supervisorApiCall helper to simplify functions

* Do not consider ESPHome as custom repository

* Home Assistant Community Add-ons is not custom
2022-06-08 15:28:40 +02:00
Yosi Levy bc47ecaa57 Various RTL fixes (#12857) 2022-06-08 10:46:39 +02:00
Steve Repsher 2bd617ce6e Add container list and ARIA to create helper listbox (#12885) 2022-06-07 19:52:48 +02:00
loeffelpan dbaf955525 Fix extra space in energy-dist-card (#12905) 2022-06-07 15:18:52 +00:00
RoboMagus 578ff5b53f Energy Dashboard: Align total cost with 'previous cost' column. (#12883)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-06-07 15:11:47 +00:00
Yosi Levy e386942ea7 Quick bar keyboard shortcut international support (#12892) 2022-06-07 17:07:22 +02:00
Paulus Schoutsen 2fdd50f45f Add announce: true when sending TTS from media browser (#12866) 2022-06-07 16:43:34 +02:00
wizmo2 4b36770adf Fix overlapped tiles and hidden title for 2:3 aspect ratio media classes (#12853) 2022-06-07 16:42:37 +02:00
Raman Gupta 54377225ec Add zwave_js device statistics (#12794)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-06-07 16:40:28 +02:00
Philip Allgaier f020add6be Make translation README a bit clearer (#12901) 2022-06-07 16:36:19 +02:00
J. Nick Koston b1a3996cf1 Fix multiple races in logbook subscriptions (#12878)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2022-06-06 22:23:56 -07:00
J. Nick Koston a47a0ed716 Fix history charts not auto refreshing with cached history (#12873)
* Fix history charts refreshing with cached history

Fixes #12859

* return a new array

* Revert "return a new array"

This reverts commit 2b0e265185.
2022-06-06 16:05:22 -07:00
J. Nick Koston 91cd584b4b Request tiny thumbnails for cameras in the entity selector to reduce memory pressure (#12880) 2022-06-05 22:12:54 -07:00
J. Nick Koston 75562efb79 Add counter to logbook continuous domains (#12888) 2022-06-05 21:46:56 -07:00
J. Nick Koston f464bcfc14 Filter entities that will never have entries in the logbook card editor (#12876) 2022-06-05 21:45:58 -07:00
Bram Kragten f8af66d310 20220601.0 (#12843) 2022-06-01 21:57:23 +02:00
Bram Kragten 4922e575f8 Bumped version to 20220601.0 2022-06-01 21:43:38 +02:00
Bram Kragten ac08daa64e Don't fix width of label when not virtualized (#12842)
Don't fix width of label when not virtualized
2022-06-01 21:42:27 +02:00
Bram Kragten 97f082a384 Merge pull request #12835 from home-assistant/dev 2022-05-31 16:09:03 +02:00
Bram Kragten ced37aab4c Make hardware item non interactive 2022-05-31 15:57:19 +02:00
Bram Kragten 1938fb89e6 Bumped version to 20220531.0 2022-05-31 15:51:20 +02:00
Bram Kragten 6842c479d6 Add compare data to individual devices graph (#12829) 2022-05-31 08:36:04 -05:00
Bram Kragten 881f6b0531 Use icon button for compare on narrow (#12831) 2022-05-31 08:29:32 -05:00
Pawel a564ceb9e3 Add proper label for gas energy stats (#12828)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-05-31 08:51:27 +00:00
J. Nick Koston 077fa3f6b2 Fix live logbook starting empty (#12833) 2022-05-30 22:03:51 -07:00
J. Nick Koston ceda911670 Virtualize history panel (#12824) 2022-05-30 10:30:04 -10:00
Bram Kragten afd41e79f0 Make blueprint picker wider (#12830) 2022-05-30 12:53:39 -05:00
Yosi Levy 10f63180eb RTL Auth fix (#12746) 2022-05-30 17:57:37 +02:00
Zack Barett e54802bd87 Actually add Cloud URL Translation.... (#12813) 2022-05-30 17:56:24 +02:00
wizmo2 c1d6b51065 Scale oversized brand thumbnails in media browser (#12820)
* resize brand icons

* add newline JIC

* Now Prettier

* created brand-image style
2022-05-30 17:19:48 +02:00
Joakim Sørensen ab65ce819f Fallback to 0 for undefined offsets (#12823) 2022-05-30 09:57:28 -05:00
Xor 1e011bfe34 Fix color of plant entity when state is problem (#12821) 2022-05-30 09:57:00 -05:00
Joakim Sørensen 5951f5c5c4 Prefer CSS variables in custom panel entrypoint (#12818) 2022-05-30 09:56:13 -05:00
Bram Kragten d810cae194 20220526.0 (#12807)
* Fix setting _externalAccess (#12584)

* Fix enter key support for generic dialog box (#12600)

* Revert #10991 (#12618)

* Replace host-context with css properties

* Remove "Lovelace" from Github issue templates (#12614)

* Remove "Lovelace" from Github issue templates

* Changes from review

* Get full core logs from core (#12639)

* Move YAML to first tab of Developer Tools (#12589)

* Add configuration panel for Application Credentials (#12344)

Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: Zack <zackbarett@hey.com>

* Add label for Fix issue column header in statistics developer tools (#12597)

Signed-off-by: Patrick ZAJDA <patrick@zajda.fr>

* RTL settings clickable list item fix (#12595)

* Update src/state/translations-mixin.ts

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

* Update following review

* Update Translations to create helper (#12656)

* Hide Cloud URL - Add Copy Icon (#12655)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

* Show script traces in logbook (#12643)

* Rtl menu fix (#12561)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

* Use  /

* Update var name

* Use FabBase

* Update ha-fab.ts

* Switch logbook calls to use the new websocket (#12665)

* Add calendar trigger offsets in automation editor (#12486)

* Add calendar trigger offsets in automation editor

* Use duration selector for offset

* Fix typing for offsets/duratons

* Fix strict error handling in Markdown card templates (#12661)

* Add missing label to search icon (#12671)

* Update Lokalise URL (#12684)

* Teach logbook about additional context data (#12667)

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

* Guard for missing backup integration (#12696)

* Rtl changes (#12693)

* Return focus after dialogs close (#11999)

* Bumped version to 20220516.0

* Fix float-end for LTR (#12707)

* Add my support for Application Credentials (#12709)

* Show manage cloud link to config (#12673)

* Add guard logic from PR home-assistant#12181 to input select row (#12703)

* Refactor logbook data fetch logic into reusable class (#12701)

* Add logbook to device info page (#12714)

* Add logbook to area info page (#12715)

* Add missing labels in energy dashboard settings (#12722)

Signed-off-by: Patrick ZAJDA <patrick@zajda.fr>

* Delete focus targets for replaced dialogs (#12724)

* Convert history calls to use new websocket endpoint (#12662)

* Add support for OAuth2 callback via My (#12718)

* Support requesting translations for multiple integrations in one request (#12704)

* Support requesting translations for multiple integrations in one request

- Requires https://github.com/home-assistant/core/pull/71979

* onboarding as well

* integrations -> integration

* fix cache

* short return if they are all loaded

* reduce

* reduce

* reduce

* Show the integration brand icon when there is no entity in logbook (#12713)

* Support requesting multiple integration manifests in a single request (#12706)

* Support requesting multiple integration manifests in a single request

* only fetch if there are some to actually fetch

* handle empty

* not truthy, wrong language

* Do not copy params

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>

* Import all date-fns from modules (#12717)

* Fix 'loading_log' string (#12712)

* Bumped version to 20220518.0

* Fix python to js timestamp conversions in logbook traces (#12677)

- The websocket version needs the time converted from
  where python stores the decimal

* Update Material Design Icons to v6.7.96 (#12111)

* Various RTL fixes (#12721)

* Select + target picker Rtl fixes (#12711)

* Add error handling for application credentials removal (#12686)

* Update zwave_js data collection URL (#12666)

* Use device_id instead of config entry id and node id for zwave_js (#12658)

* Use device_id instead of config entry id and node id for zwave_js

* Add additional cleanup from #12642

* Revert removal of multiple config entries check

* Update src/panels/config/devices/device-detail/integration-elements/zwave_js/ha-device-actions-zwave_js.ts

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

* Update src/panels/config/devices/device-detail/integration-elements/zwave_js/ha-device-info-zwave_js.ts

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

* Get attributes from first state when using minimal responses (#12732)

* Pass device ID to logbook if available (#12728)

* Compute the icon based on the logbook state and not the current state (#12725)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

* Add option to compare energy graphs with previous period (#12723)

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>

* Add an application credentials display name (#12720)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

* Fixes logbook (#12740)

* Bumped version to 20220521.0

* Stop closed event when selecting datadisk (#12749)

* Use logbook livestream when requesting a time window that includes the future (#12744)

* Fetch supervisor info directly (#12751)

* Remove kernel and agent versions from about page (#12750)

* Move `preload_stream` setting to entity settings (#12730)

Co-authored-by: Zack <zackbarett@hey.com>

* Use new localized context state and source in logbook (#12742)

* Use new logbook streaming websocket api for cases where we need end_time (#12753)

* Open Application Credentials from integration configuration flow (#12708)

* Make entities and devices independent in the scene editor (#11046)

Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: Erik <erik@montnemery.com>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>

* Allow setting `device_class` "outlet" again through entity settings (#12669)

* Allow setting `device_class` "outlet" again through UI

* Fixes

* Null check deviceClass and adjust used translation

* Bumped version to 20220523.0 (#12756)

* Adjust logbook stream consumer to handle new metadata (#12755)

* Adjust path to version info in issue template (#12760)

* Add My HA link to about page to Github issue template (#12761)

* RTL updates (#12745)

* Add compare to energy sources table (#12762)

* Fix (#12764)

* Change service_data to just data (#12628)

* Simplify OAuth2 authorize callback URL (#12765)

* Hide hidden media player entities in media panel (#12766)

* Add integration filter to Device Selector (#12680)

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>

* Integration filter for Area Selector (#12682)

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>

* Bump Version to 20220524.0 (#12769)

* Move zwave_js node comments from device config to info page (#12625)

Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>

* Various RTL fixes

* Add controller statistics to zwave_js config dashboard (#12668)

* Move Logbook and make device page better (#12763)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

* Move metadata to pyproject.toml (#12770)

* Add aria-haspopup to button menus (#12758)

Co-authored-by: Zack Barett <zackbarett@hey.com>

* Hardware MVP (#12773)

* Fix "unavailable" handling for climate state rendering (#12778)

* Ensure state is vertically centered in more-info (#12780)

* Update zwave_js/network_status WS API (#12735)

* Bumped version to 20220525.0 (#12779)

* Use dynamic weather domain icon + icon alignment fix weather more-info (#12781)

* Fix typo in credentials removal dialog (#12784)

* Handle history api being passed entity ids as CSV (#12787)

* Fix history cache when there is cacheConfig (#12788)

* Use Hardware Integration for System Menu (#12789)

* Fix Media Player More info cramped controls (#12790)

* Fix Switch as X unable to change to a new type (#12797)

* Fix Zwave Alerts on device page (#12785)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

* Set Error if entity is unavailable (#12791)

* Dynamically determine the correct action config struct (#12798)

* Remove import

* Hide Cloud information a bit more (#12802)

* Add dynamic header/footer config determination and update struct (#12795)

* Bump HAWS to 7.1.0 (#12804)

* Update Narrow Order on Device Page (#12801)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

* Fix combo box inside dialog (#12805)

* Bumped version to 20220526.0

Co-authored-by: Joakim Sørensen <ludeeus@ludeeus.dev>
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com>
Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: Yosi Levy <yosilevy@gmail.com>
Co-authored-by: Philip Allgaier <mail@spacegaier.de>
Co-authored-by: Allen Porter <allen@thebends.org>
Co-authored-by: Patrick ZAJDA <patrick@zajda.fr>
Co-authored-by: Yosi Levy <37745463+yosilevy@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Sven <85389871+wrt54g@users.noreply.github.com>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: breakthestatic <breakthestatic@gmail.com>
Co-authored-by: RoboMagus <68224306+RoboMagus@users.noreply.github.com>
Co-authored-by: Michael Irigoyen <michael@irigoyen.dev>
Co-authored-by: Raman Gupta <7243222+raman325@users.noreply.github.com>
Co-authored-by: David F. Mulcahey <david.mulcahey@me.com>
Co-authored-by: Erik <erik@montnemery.com>
Co-authored-by: Thomas Lovén <thomasloven@gmail.com>
Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
2022-05-26 23:41:27 +02:00
621 changed files with 67453 additions and 34874 deletions
+8
View File
@@ -0,0 +1,8 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: weekly
time: "06:00"
open-pull-requests-limit: 10
+9 -9
View File
@@ -11,7 +11,7 @@ on:
- master
env:
NODE_VERSION: 14
NODE_VERSION: 16
NODE_OPTIONS: --max_old_space_size=6144
jobs:
@@ -19,9 +19,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out files from GitHub
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
@@ -43,9 +43,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out files from GitHub
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
@@ -62,9 +62,9 @@ jobs:
needs: [lint, test]
steps:
- name: Check out files from GitHub
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
@@ -81,9 +81,9 @@ jobs:
needs: [lint, test]
steps:
- name: Check out files from GitHub
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
+4 -4
View File
@@ -23,7 +23,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
@@ -36,14 +36,14 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -57,4 +57,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
+4 -6
View File
@@ -6,7 +6,7 @@ on:
- dev
env:
NODE_VERSION: 14
NODE_VERSION: 16
NODE_OPTIONS: --max_old_space_size=6144
jobs:
@@ -14,9 +14,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out files from GitHub
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
@@ -27,9 +27,7 @@ jobs:
- name: Build Demo
run: ./node_modules/.bin/gulp build-demo
- name: Deploy to Netlify
uses: netlify/actions/cli@master
run: npx netlify-cli deploy --dir=demo/dist --prod
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_DEMO_DEV_SITE_ID }}
with:
args: deploy --dir=demo/dist --prod
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v2.0.1
- uses: dessant/lock-threads@v3.0.0
with:
github-token: ${{ github.token }}
issue-lock-inactive-days: "30"
+73
View File
@@ -0,0 +1,73 @@
name: Nightly
on:
workflow_dispatch:
schedule:
- cron: "0 1 * * *"
env:
PYTHON_VERSION: "3.10"
NODE_VERSION: 16
NODE_OPTIONS: --max_old_space_size=6144
permissions:
actions: none
jobs:
nightly:
name: Nightly
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout the repository
uses: actions/checkout@v3
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
- name: Install dependencies
run: yarn install
- name: Download translations
run: ./script/translations_download
env:
LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
- name: Bump version
run: script/version_bump.js nightly
- name: Build nightly Python wheels
run: |
pip install build
yarn install
script/build_frontend
rm -rf dist home_assistant_frontend.egg-info
python3 -m build
- name: Archive translations
run: tar -czvf translations.tar.gz translations
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist/home_assistant_frontend*.whl
if-no-files-found: error
- name: Upload translations
uses: actions/upload-artifact@v3
with:
name: translations
path: translations.tar.gz
if-no-files-found: error
+10 -32
View File
@@ -6,8 +6,8 @@ on:
- published
env:
PYTHON_VERSION: 3.8
NODE_VERSION: 14
PYTHON_VERSION: "3.10"
NODE_VERSION: 16
NODE_OPTIONS: --max_old_space_size=6144
# Set default workflow permissions
@@ -21,21 +21,21 @@ jobs:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write # Required to upload release assets
contents: write # Required to upload release assets
steps:
- name: Checkout the repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Verify version
uses: home-assistant/actions/helpers/verify-version@master
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
@@ -74,33 +74,11 @@ jobs:
version=$(echo "${{ github.ref }}" | awk -F"/" '{print $NF}' )
echo "home-assistant-frontend==$version" > ./requirements.txt
- name: Upload requirements.txt
uses: actions/upload-artifact@v2
with:
name: requirements
path: ./requirements.txt
build-wheels:
name: Build wheels for ${{ matrix.arch }}
needs: wheels-init
runs-on: ubuntu-latest
strategy:
matrix:
arch: ["aarch64", "armhf", "armv7", "amd64", "i386"]
tag:
- "3.9-alpine3.14"
steps:
- name: Download requirements.txt
uses: actions/download-artifact@v2
with:
name: requirements
- name: Build wheels
uses: home-assistant/wheels@master
uses: home-assistant/wheels@2022.06.7
with:
tag: ${{ matrix.tag }}
arch: ${{ matrix.arch }}
wheels-host: ${{ secrets.WHEELS_HOST }}
abi: cp310
tag: musllinux_1_2
arch: amd64
wheels-key: ${{ secrets.WHEELS_KEY }}
wheels-user: wheels
requirements: "requirements.txt"
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 90 days stale policy
uses: actions/stale@v3.0.13
uses: actions/stale@v6.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 90
+2 -2
View File
@@ -8,7 +8,7 @@ on:
- src/translations/en.json
env:
NODE_VERSION: 14
NODE_VERSION: 16
jobs:
upload:
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Upload Translations
run: |
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
yarn run lint-staged --relative --shell "/bin/bash"
+1 -1
View File
@@ -1 +1 @@
14
16
+1 -1
View File
@@ -27,7 +27,7 @@ module.exports = {
version() {
const version = fs
.readFileSync(path.resolve(paths.polymer_dir, "pyproject.toml"), "utf8")
.match(/version\W+=\W"(\d{8}\.\d)"/);
.match(/version\W+=\W"(\d{8}\.\d(?:\.dev)?)"/);
if (!version) {
throw Error("Version not found");
}
+9
View File
@@ -156,3 +156,12 @@ gulp.task("gen-icons-json", (done) => {
done();
});
gulp.task("gen-dummy-icons-json", (done) => {
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
}
fs.writeFileSync(path.resolve(OUTPUT_DIR, "iconList.json"), "[]");
done();
});
+3
View File
@@ -9,6 +9,7 @@ require("./compress.js");
require("./rollup.js");
require("./gather-static.js");
require("./translations.js");
require("./gen-icons-json.js");
gulp.task(
"develop-hassio",
@@ -17,6 +18,7 @@ gulp.task(
process.env.NODE_ENV = "development";
},
"clean-hassio",
"gen-dummy-icons-json",
"gen-index-hassio-dev",
"build-supervisor-translations",
"copy-translations-supervisor",
@@ -33,6 +35,7 @@ gulp.task(
process.env.NODE_ENV = "production";
},
"clean-hassio",
"gen-dummy-icons-json",
"build-supervisor-translations",
"copy-translations-supervisor",
"build-locale-data",
+30 -1
View File
@@ -1 +1,30 @@
[]
[
{
"path": "M20,20H7A2,2 0 0,1 5,18V8.94L2.23,5.64C2.09,5.47 2,5.24 2,5A1,1 0 0,1 3,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20M8.5,7A0.5,0.5 0 0,0 8,7.5V8.5A0.5,0.5 0 0,0 8.5,9H18.5A0.5,0.5 0 0,0 19,8.5V7.5A0.5,0.5 0 0,0 18.5,7H8.5M8.5,11A0.5,0.5 0 0,0 8,11.5V12.5A0.5,0.5 0 0,0 8.5,13H18.5A0.5,0.5 0 0,0 19,12.5V11.5A0.5,0.5 0 0,0 18.5,11H8.5M8.5,15A0.5,0.5 0 0,0 8,15.5V16.5A0.5,0.5 0 0,0 8.5,17H13.5A0.5,0.5 0 0,0 14,16.5V15.5A0.5,0.5 0 0,0 13.5,15H8.5Z",
"name": "android-messages"
},
{
"path": "M4,6H2V20A2,2 0 0,0 4,22H18V20H4V6M20,2H8A2,2 0 0,0 6,4V16A2,2 0 0,0 8,18H20A2,2 0 0,0 22,16V4A2,2 0 0,0 20,2M20,12L17.5,10.5L15,12V4H20V12Z",
"name": "book-variant-multiple"
},
{
"path": "M21,14H3V4H21M21,2H3C1.89,2 1,2.89 1,4V16A2,2 0 0,0 3,18H10L8,21V22H16V21L14,18H21A2,2 0 0,0 23,16V4C23,2.89 22.1,2 21,2Z",
"name": "desktop-mac"
},
{
"path": "M21,14V4H3V14H21M21,2A2,2 0 0,1 23,4V16A2,2 0 0,1 21,18H14L16,21V22H8V21L10,18H3C1.89,18 1,17.1 1,16V4C1,2.89 1.89,2 3,2H21M4,5H15V10H4V5M16,5H20V7H16V5M20,8V13H16V8H20M4,11H9V13H4V11M10,11H15V13H10V11Z",
"name": "desktop-mac-dashboard"
},
{
"path": "M22,24L16.75,19L17.38,21H4.5A2.5,2.5 0 0,1 2,18.5V3.5A2.5,2.5 0 0,1 4.5,1H19.5A2.5,2.5 0 0,1 22,3.5V24M12,6.8C9.32,6.8 7.44,7.95 7.44,7.95C8.47,7.03 10.27,6.5 10.27,6.5L10.1,6.33C8.41,6.36 6.88,7.53 6.88,7.53C5.16,11.12 5.27,14.22 5.27,14.22C6.67,16.03 8.75,15.9 8.75,15.9L9.46,15C8.21,14.73 7.42,13.62 7.42,13.62C7.42,13.62 9.3,14.9 12,14.9C14.7,14.9 16.58,13.62 16.58,13.62C16.58,13.62 15.79,14.73 14.54,15L15.25,15.9C15.25,15.9 17.33,16.03 18.73,14.22C18.73,14.22 18.84,11.12 17.12,7.53C17.12,7.53 15.59,6.36 13.9,6.33L13.73,6.5C13.73,6.5 15.53,7.03 16.56,7.95C16.56,7.95 14.68,6.8 12,6.8M9.93,10.59C10.58,10.59 11.11,11.16 11.1,11.86C11.1,12.55 10.58,13.13 9.93,13.13C9.29,13.13 8.77,12.55 8.77,11.86C8.77,11.16 9.28,10.59 9.93,10.59M14.1,10.59C14.75,10.59 15.27,11.16 15.27,11.86C15.27,12.55 14.75,13.13 14.1,13.13C13.46,13.13 12.94,12.55 12.94,11.86C12.94,11.16 13.45,10.59 14.1,10.59Z",
"name": "discord"
},
{
"path": "M8.06,7.78C7.5,7.78 7.17,7.73 7.08,7.64L6.66,13.73C7.19,14.05 7.88,14.3 8.72,14.5C9.56,14.71 10.78,14.77 12.38,14.67C13.97,14.58 15.63,14.23 17.34,13.64L16.55,4.22C15.67,5.09 14.38,5.91 12.66,6.66C11.13,7.31 9.81,7.69 8.72,7.78H8.06M7.97,5.34C7.28,5.94 7,6.34 7.13,6.56C7.22,6.78 7.7,6.84 8.58,6.75C9.67,6.66 10.91,6.31 12.28,5.72C13.22,5.31 14.03,4.88 14.72,4.41C15.41,3.94 15.88,3.55 16.13,3.23C16.38,2.92 16.47,2.7 16.41,2.58C16.34,2.42 16.03,2.34 15.47,2.34C14.34,2.34 12.94,2.7 11.25,3.42C9.81,4.05 8.72,4.69 7.97,5.34M17.34,2.2C17.41,2.33 17.44,2.47 17.44,2.63L18.61,17C18.61,18.73 18,20.09 16.83,21.07C15.64,22.05 14.03,22.55 12,22.55C10,22.55 8.4,22.04 7.2,21C6,20 5.39,18.64 5.39,16.92L6.09,6.47C6.09,6.22 6.2,5.94 6.42,5.63C6.64,5.31 6.84,5.06 7.03,4.88L7.36,4.59C8.33,3.78 9.5,3.08 10.88,2.5C11.81,2.08 12.73,1.77 13.62,1.57C14.5,1.37 15.3,1.3 16,1.38C16.71,1.46 17.16,1.73 17.34,2.2Z",
"name": "google-home"
},
{
"path": "M19.25,19H4.75V3H19.25M14,22H10V21H14M18,0H6A3,3 0 0,0 3,3V21A3,3 0 0,0 6,24H18A3,3 0 0,0 21,21V3A3,3 0 0,0 18,0Z",
"name": "tablet-android"
}
]
+1 -1
View File
@@ -76,7 +76,7 @@ const createWebpackConfig = ({
chunkIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
},
plugins: [
new WebpackBar({ fancy: !isProdBuild }),
!isStatsBuild && new WebpackBar({ fancy: !isProdBuild }),
new WebpackManifestPlugin({
// Only include the JS of entrypoints
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
+14 -14
View File
@@ -59,7 +59,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
attributes: {
hidden: true,
radius: 50,
friendly_name: "Skolan",
friendly_name: "School",
icon: "mdi:school",
},
},
@@ -137,7 +137,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
state: "73",
attributes: {
unit_of_measurement: "%",
friendly_name: "oskar batteri",
friendly_name: "Oskar battery",
device_class: "battery",
},
},
@@ -146,7 +146,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
state: "88",
attributes: {
unit_of_measurement: "%",
friendly_name: "bella batteri",
friendly_name: "Bella battery",
device_class: "battery",
},
},
@@ -154,7 +154,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
entity_id: "binary_sensor.unifi_camera",
state: "off",
attributes: {
friendly_name: "R\u00f6relsesensor kamera",
friendly_name: "Motion sensor camera",
icon: "mdi:walk",
},
},
@@ -707,7 +707,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
},
],
cloudiness: 25,
friendly_name: "V\u00e4der",
friendly_name: "Weather",
},
},
"binary_sensor.ubiquiti_switch": {
@@ -731,7 +731,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
round_trip_time_max: "0.626",
round_trip_time_mdev: "",
round_trip_time_min: "0.358",
friendly_name: "Entr\u00e9 kamera",
friendly_name: "Entrance camera",
device_class: "connectivity",
icon: "mdi:cctv",
},
@@ -797,7 +797,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
attributes: {
battery_level: 34,
on: true,
friendly_name: "altan_motion_sensor",
friendly_name: "Porch motion sensor",
device_class: "motion",
},
},
@@ -807,7 +807,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
attributes: {
battery_level: 88,
on: true,
friendly_name: "Altand\u00f6rren sensor",
friendly_name: "Back door sensor",
device_class: "opening",
icon: "mdi:door",
},
@@ -818,7 +818,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
attributes: {
battery_level: 74,
on: true,
friendly_name: "badrumssensor",
friendly_name: "Bathroom motion sensor",
device_class: "motion",
},
},
@@ -829,7 +829,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
battery_level: 47,
on: true,
dark: true,
friendly_name: "R\u00f6relsesensor k\u00e4llaren 1",
friendly_name: "Basement motion sensor",
device_class: "motion",
icon: "mdi:walk",
},
@@ -841,7 +841,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
battery_level: 60,
on: true,
dark: true,
friendly_name: "R\u00f6relsesensor tv\u00e4ttstugan",
friendly_name: "Laundy room motion sensor",
device_class: "motion",
icon: "mdi:walk",
},
@@ -863,7 +863,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
attributes: {
battery_level: 60,
on: true,
friendly_name: "R\u00f6relsesensor skafferiet",
friendly_name: "Pantry motion sensor",
device_class: "motion",
icon: "mdi:walk",
},
@@ -875,7 +875,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
battery_level: 60,
on: true,
dark: true,
friendly_name: "R\u00f6relsesensor k\u00e4llaren 2",
friendly_name: "Stair motion sensor",
device_class: "motion",
icon: "mdi:walk",
},
@@ -887,7 +887,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
battery_level: 47,
on: true,
dark: true,
friendly_name: "B\u00e4nksensor",
friendly_name: "Bench sensor",
device_class: "motion",
},
},
+1 -1
View File
@@ -277,7 +277,7 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
],
show_header_toggle: false,
type: "entities",
title: "Bandbredd",
title: "Bandwidth",
},
// {
// title: "Updater",
+38 -5
View File
@@ -1,5 +1,4 @@
// Compat needs to be first import
import "../../src/resources/compatibility";
import { isNavigationClick } from "../../src/common/dom/is-navigation-click";
import { navigate } from "../../src/common/navigate";
import {
@@ -7,9 +6,14 @@ import {
provideHass,
} from "../../src/fake_data/provide_hass";
import { HomeAssistantAppEl } from "../../src/layouts/home-assistant";
import "../../src/resources/compatibility";
import { HomeAssistant } from "../../src/types";
import { selectedDemoConfig } from "./configs/demo-configs";
import { mockAuth } from "./stubs/auth";
import { mockConfigEntries } from "./stubs/config_entries";
import { mockEnergy } from "./stubs/energy";
import { energyEntities } from "./stubs/entities";
import { mockEntityRegistry } from "./stubs/entity_registry";
import { mockEvents } from "./stubs/events";
import { mockFrontend } from "./stubs/frontend";
import { mockHistory } from "./stubs/history";
@@ -20,9 +24,6 @@ import { mockShoppingList } from "./stubs/shopping_list";
import { mockSystemLog } from "./stubs/system_log";
import { mockTemplate } from "./stubs/template";
import { mockTranslations } from "./stubs/translations";
import { mockEnergy } from "./stubs/energy";
import { mockConfig } from "./stubs/config";
import { energyEntities } from "./stubs/entities";
class HaDemo extends HomeAssistantAppEl {
protected async _initializeHass() {
@@ -51,8 +52,40 @@ class HaDemo extends HomeAssistantAppEl {
mockMediaPlayer(hass);
mockFrontend(hass);
mockEnergy(hass);
mockConfig(hass);
mockPersistentNotification(hass);
mockConfigEntries(hass);
mockEntityRegistry(hass, [
{
config_entry_id: "co2signal",
device_id: "co2signal",
area_id: null,
disabled_by: null,
entity_id: "sensor.co2_intensity",
id: "sensor.co2_intensity",
name: null,
icon: null,
platform: "co2signal",
hidden_by: null,
entity_category: null,
has_entity_name: false,
unique_id: "co2_intensity",
},
{
config_entry_id: "co2signal",
device_id: "co2signal",
area_id: null,
disabled_by: null,
entity_id: "sensor.grid_fossil_fuel_percentage",
id: "sensor.co2_intensity",
name: null,
icon: null,
platform: "co2signal",
hidden_by: null,
entity_category: null,
has_entity_name: false,
unique_id: "grid_fossil_fuel_percentage",
},
]);
hass.addEntities(energyEntities());
-41
View File
@@ -1,41 +0,0 @@
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
export const mockConfig = (hass: MockHomeAssistant) => {
hass.mockAPI("config/config_entries/entry", () => [
{
entry_id: "co2signal",
domain: "co2signal",
title: "CO2 Signal",
source: "user",
state: "loaded",
supports_options: false,
supports_unload: true,
pref_disable_new_entities: false,
pref_disable_polling: false,
disabled_by: null,
reason: null,
},
]);
hass.mockWS("config/entity_registry/list", () => [
{
config_entry_id: "co2signal",
device_id: "co2signal",
area_id: null,
disabled_by: null,
entity_id: "sensor.co2_intensity",
name: null,
icon: null,
platform: "co2signal",
},
{
config_entry_id: "co2signal",
device_id: "co2signal",
area_id: null,
disabled_by: null,
entity_id: "sensor.grid_fossil_fuel_percentage",
name: null,
icon: null,
platform: "co2signal",
},
]);
};
+20
View File
@@ -0,0 +1,20 @@
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
export const mockConfigEntries = (hass: MockHomeAssistant) => {
hass.mockWS("config_entries/get", () => [
{
entry_id: "co2signal",
domain: "co2signal",
title: "CO2 Signal",
source: "user",
state: "loaded",
supports_options: false,
supports_remove_device: false,
supports_unload: true,
pref_disable_new_entities: false,
pref_disable_polling: false,
disabled_by: null,
reason: null,
},
]);
};
-5
View File
@@ -11,14 +11,12 @@ export const mockEnergy = (hass: MockHomeAssistant) => {
{
stat_energy_from: "sensor.energy_consumption_tarif_1",
stat_cost: "sensor.energy_consumption_tarif_1_cost",
entity_energy_from: "sensor.energy_consumption_tarif_1",
entity_energy_price: null,
number_energy_price: null,
},
{
stat_energy_from: "sensor.energy_consumption_tarif_2",
stat_cost: "sensor.energy_consumption_tarif_2_cost",
entity_energy_from: "sensor.energy_consumption_tarif_2",
entity_energy_price: null,
number_energy_price: null,
},
@@ -27,14 +25,12 @@ export const mockEnergy = (hass: MockHomeAssistant) => {
{
stat_energy_to: "sensor.energy_production_tarif_1",
stat_compensation: "sensor.energy_production_tarif_1_compensation",
entity_energy_to: "sensor.energy_production_tarif_1",
entity_energy_price: null,
number_energy_price: null,
},
{
stat_energy_to: "sensor.energy_production_tarif_2",
stat_compensation: "sensor.energy_production_tarif_2_compensation",
entity_energy_to: "sensor.energy_production_tarif_2",
entity_energy_price: null,
number_energy_price: null,
},
@@ -55,7 +51,6 @@ export const mockEnergy = (hass: MockHomeAssistant) => {
type: "gas",
stat_energy_from: "sensor.energy_gas",
stat_cost: "sensor.energy_gas_cost",
entity_energy_from: "sensor.energy_gas",
entity_energy_price: null,
number_energy_price: null,
},
+3 -1
View File
@@ -4,4 +4,6 @@ import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
export const mockEntityRegistry = (
hass: MockHomeAssistant,
data: EntityRegistryEntry[] = []
) => hass.mockWS("config/entity_registry/list", () => data);
) => {
hass.mockWS("config/entity_registry/list", () => data);
};
+2 -1
View File
@@ -6,7 +6,7 @@ import {
endOfDay,
} from "date-fns/esm";
import { HassEntity } from "home-assistant-js-websocket";
import { StatisticValue } from "../../../src/data/history";
import { StatisticValue } from "../../../src/data/recorder";
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
interface HistoryQueryParams {
@@ -466,6 +466,7 @@ export const mockHistory = (mockHass: MockHomeAssistant) => {
return results;
}
);
mockHass.mockWS("recorder/get_statistics_metadata", () => []);
mockHass.mockWS("history/list_statistic_ids", () => []);
mockHass.mockWS(
"history/statistics_during_period",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 25 KiB

+2 -2
View File
@@ -8,7 +8,7 @@ module.exports = [
{
category: "lovelace",
// Label for in the sidebar
header: "Lovelace",
header: "Dashboards",
// Specify order of pages. Any pages in the category folder but not listed here will
// automatically be added after the pages listed here.
pages: ["introduction"],
@@ -34,7 +34,7 @@ module.exports = [
},
{
category: "misc",
header: "Miscelaneous",
header: "Miscellaneous",
},
{
category: "brand",
+4 -3
View File
@@ -5,7 +5,7 @@ import { html, css, LitElement, PropertyValues } from "lit";
import { customElement, property, query } from "lit/decorators";
import "../../src/components/ha-icon-button";
import "../../src/managers/notification-manager";
import "../../src/components/ha-expansion-panel";
import { HaExpansionPanel } from "../../src/components/ha-expansion-panel";
import { haStyle } from "../../src/resources/styles";
import { PAGES, SIDEBAR } from "../build/import-pages";
import { dynamicElement } from "../../src/common/dom/dynamic-element-directive";
@@ -174,9 +174,10 @@ class HaGallery extends LitElement {
const menuItem = this.shadowRoot!.querySelector(
`a[href="#${this._page}"]`
)!;
// Make sure section is expanded
if (menuItem.parentElement instanceof HTMLDetailsElement) {
menuItem.parentElement.open = true;
if (menuItem.parentElement instanceof HaExpansionPanel) {
menuItem.parentElement.expanded = true;
}
}
@@ -0,0 +1,56 @@
---
title: When to use remove, delete, add and create
subtitle: The difference between remove/delete and add/create.
---
# Remove vs Delete
Remove and Delete are quite similar, but can be frustrating if used inconsistently.
## Remove
Take away and set aside, but kept in existence.
For example:
* Removing a user's permission
* Removing a user from a group
* Removing links between items
* Removing a widget
* Removing a link
* Removing an item from a cart
## Delete
Erase, rendered nonexistent or nonrecoverable.
For example:
* Deleting a field
* Deleting a value in a field
* Deleting a task
* Deleting a group
* Deleting a permission
* Deleting a calendar event
# Add vs Create
In most cases, Create can be paired with Delete, and Add can be paired with Remove.
## Add
An already-exisiting item.
For example:
* Adding a permission to a user
* Adding a user to a group
* Adding links between items
* Adding a widget
* Adding a link
* Adding an item to a cart
## Create
Something made from scratch.
For example:
* Creating a new field
* Creating a new value in a field
* Creating a new task
* Creating a new group
* Creating a new permission
* Creating a new calendar event
Based on this is [UX magazine article](https://uxmag.com/articles/ui-copy-remove-vs-delete2-banner).
@@ -1,7 +1,9 @@
import { dump } from "js-yaml";
import { html, css, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { customElement, property, state } from "lit/decorators";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-yaml-editor";
import { Action } from "../../../../src/data/script";
import { describeAction } from "../../../../src/data/script_i18n";
import { getEntity } from "../../../../src/fake_data/entity";
import { provideHass } from "../../../../src/fake_data/provide_hass";
@@ -88,6 +90,15 @@ const ACTIONS = [
then: [{ delay: "00:00:01" }],
else: [{ delay: "00:00:05" }],
},
{
if: [{ condition: "state" }],
then: [{ delay: "00:00:01" }],
},
{
if: [{ condition: "state" }, { condition: "state" }],
then: [{ delay: "00:00:01" }],
else: [{ delay: "00:00:05" }],
},
{
choose: [
{
@@ -103,16 +114,38 @@ const ACTIONS = [
},
];
const initialAction: Action = {
service: "light.turn_on",
target: {
entity_id: "light.kitchen",
},
};
@customElement("demo-automation-describe-action")
export class DemoAutomationDescribeAction extends LitElement {
@property({ attribute: false }) hass!: HomeAssistant;
@state() _action = initialAction;
protected render(): TemplateResult {
if (!this.hass) {
return html``;
}
return html`
<ha-card header="Actions">
<div class="action">
<span>
${this._action
? describeAction(this.hass, this._action)
: "<invalid YAML>"}
</span>
<ha-yaml-editor
label="Action Config"
.defaultValue=${initialAction}
@value-changed=${this._dataChanged}
></ha-yaml-editor>
</div>
${ACTIONS.map(
(conf) => html`
<div class="action">
@@ -132,6 +165,11 @@ export class DemoAutomationDescribeAction extends LitElement {
hass.addEntities(ENTITIES);
}
private _dataChanged(ev: CustomEvent): void {
ev.stopPropagation();
this._action = ev.detail.isValid ? ev.detail.value : undefined;
}
static get styles() {
return css`
ha-card {
@@ -147,6 +185,9 @@ export class DemoAutomationDescribeAction extends LitElement {
span {
margin-right: 16px;
}
ha-yaml-editor {
width: 50%;
}
`;
}
}
@@ -1,31 +1,81 @@
import { dump } from "js-yaml";
import { html, css, LitElement, TemplateResult } from "lit";
import { customElement } from "lit/decorators";
import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-yaml-editor";
import { Condition } from "../../../../src/data/automation";
import { describeCondition } from "../../../../src/data/automation_i18n";
import { getEntity } from "../../../../src/fake_data/entity";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import { HomeAssistant } from "../../../../src/types";
const ENTITIES = [
getEntity("light", "kitchen", "on", {
friendly_name: "Kitchen Light",
}),
getEntity("device_tracker", "person", "home", {
friendly_name: "Person",
}),
getEntity("zone", "home", "", {
friendly_name: "Home",
}),
];
const conditions = [
{ condition: "and" },
{ condition: "not" },
{ condition: "or" },
{ condition: "state" },
{ condition: "numeric_state" },
{ condition: "state", entity_id: "light.kitchen", state: "on" },
{
condition: "numeric_state",
entity_id: "light.kitchen",
attribute: "brightness",
below: 80,
above: 20,
},
{ condition: "sun", after: "sunset" },
{ condition: "sun", after: "sunrise" },
{ condition: "zone" },
{ condition: "sun", after: "sunrise", offset: "-01:00" },
{ condition: "zone", entity_id: "device_tracker.person", zone: "zone.home" },
{ condition: "time" },
{ condition: "template" },
];
const initialCondition: Condition = {
condition: "state",
entity_id: "light.kitchen",
state: "on",
};
@customElement("demo-automation-describe-condition")
export class DemoAutomationDescribeCondition extends LitElement {
@property({ attribute: false }) hass!: HomeAssistant;
@state() _condition = initialCondition;
protected render(): TemplateResult {
if (!this.hass) {
return html``;
}
return html`
<ha-card header="Conditions">
<div class="condition">
<span>
${this._condition
? describeCondition(this._condition, this.hass)
: "<invalid YAML>"}
</span>
<ha-yaml-editor
label="Condition Config"
.defaultValue=${initialCondition}
@value-changed=${this._dataChanged}
></ha-yaml-editor>
</div>
${conditions.map(
(conf) => html`
<div class="condition">
<span>${describeCondition(conf as any)}</span>
<span>${describeCondition(conf as any, this.hass)}</span>
<pre>${dump(conf)}</pre>
</div>
`
@@ -34,6 +84,18 @@ export class DemoAutomationDescribeCondition extends LitElement {
`;
}
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");
hass.addEntities(ENTITIES);
}
private _dataChanged(ev: CustomEvent): void {
ev.stopPropagation();
this._condition = ev.detail.isValid ? ev.detail.value : undefined;
}
static get styles() {
return css`
ha-card {
@@ -49,6 +111,9 @@ export class DemoAutomationDescribeCondition extends LitElement {
span {
margin-right: 16px;
}
ha-yaml-editor {
width: 50%;
}
`;
}
}
@@ -1,34 +1,92 @@
import { dump } from "js-yaml";
import { html, css, LitElement, TemplateResult } from "lit";
import { customElement } from "lit/decorators";
import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-yaml-editor";
import { Trigger } from "../../../../src/data/automation";
import { describeTrigger } from "../../../../src/data/automation_i18n";
import { getEntity } from "../../../../src/fake_data/entity";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import { HomeAssistant } from "../../../../src/types";
const ENTITIES = [
getEntity("light", "kitchen", "on", {
friendly_name: "Kitchen Light",
}),
getEntity("person", "person", "", {
friendly_name: "Person",
}),
getEntity("zone", "home", "", {
friendly_name: "Home",
}),
];
const triggers = [
{ platform: "state" },
{ platform: "state", entity_id: "light.kitchen", from: "off", to: "on" },
{ platform: "mqtt" },
{ platform: "geo_location" },
{ platform: "homeassistant" },
{ platform: "numeric_state" },
{ platform: "sun" },
{
platform: "geo_location",
source: "test_source",
zone: "zone.home",
event: "enter",
},
{ platform: "homeassistant", event: "start" },
{
platform: "numeric_state",
entity_id: "light.kitchen",
attribute: "brightness",
below: 80,
above: 20,
},
{ platform: "sun", event: "sunset" },
{ platform: "time_pattern" },
{ platform: "webhook" },
{ platform: "zone" },
{
platform: "zone",
entity_id: "person.person",
zone: "zone.home",
event: "enter",
},
{ platform: "tag" },
{ platform: "time" },
{ platform: "time", at: "15:32" },
{ platform: "template" },
{ platform: "event" },
{ platform: "event", event_type: "homeassistant_started" },
];
const initialTrigger: Trigger = {
platform: "state",
entity_id: "light.kitchen",
};
@customElement("demo-automation-describe-trigger")
export class DemoAutomationDescribeTrigger extends LitElement {
@property({ attribute: false }) hass!: HomeAssistant;
@state() _trigger = initialTrigger;
protected render(): TemplateResult {
if (!this.hass) {
return html``;
}
return html`
<ha-card header="Triggers">
<div class="trigger">
<span>
${this._trigger
? describeTrigger(this._trigger, this.hass)
: "<invalid YAML>"}
</span>
<ha-yaml-editor
label="Trigger Config"
.defaultValue=${initialTrigger}
@value-changed=${this._dataChanged}
></ha-yaml-editor>
</div>
${triggers.map(
(conf) => html`
<div class="trigger">
<span>${describeTrigger(conf as any)}</span>
<span>${describeTrigger(conf as any, this.hass)}</span>
<pre>${dump(conf)}</pre>
</div>
`
@@ -37,6 +95,18 @@ export class DemoAutomationDescribeTrigger extends LitElement {
`;
}
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");
hass.addEntities(ENTITIES);
}
private _dataChanged(ev: CustomEvent): void {
ev.stopPropagation();
this._trigger = ev.detail.isValid ? ev.detail.value : undefined;
}
static get styles() {
return css`
ha-card {
@@ -52,6 +122,9 @@ export class DemoAutomationDescribeTrigger extends LitElement {
span {
margin-right: 16px;
}
ha-yaml-editor {
width: 50%;
}
`;
}
}
@@ -0,0 +1,32 @@
---
title: Dialogs
subtitle: Dialogs provide important prompts in a user flow.
---
# Material Design 3
Our dialogs are based on the latest version of Material Design. Specs and guidelines can be found on it's [website](https://m3.material.io/components/dialogs/overview).
# Highlighted guidelines
## Content
* A best practice is to always use a title, even if it is optional by Material guidelines.
* People mainly read the title and a button. Put the most important information in those two.
* Try to avoid user generated content in the title, this could make the title unreadable long.
* If users become unsure, they read the description. Make sure this explains what will happen.
* Strive for minimalism.
## Buttons and X-icon
* Keep the labels short, for example `Save`, `Delete`, `Enable`.
* Dialog with actions must always have a discard button. On desktop a `Cancel` button and X-icon, on mobile only the X-icon.
* Destructive actions should be a red warning button.
* Alert or confirmation dialogs only have buttons and no X-icon.
* Try to avoid three buttons in one dialog. Especially when you leave the dialog task unfinished.
## Example
### Confirmation dialog
> **Delete dashboard?**
>
> Dashboard [dashboard name] will be permanently deleted from Home Assistant.
>
> Cancel / Delete
@@ -3,6 +3,13 @@ title: Alerts
subtitle: An alert displays a short, important message in a way that attracts the user's attention without interrupting the user's task.
---
<style>
ha-alert {
display: block;
margin: 4px 0;
}
</style>
# Alert `<ha-alert>`
The alert offers four severity levels that set a distinctive icon and color.
@@ -0,0 +1,5 @@
---
title: Expansion Panel
---
Expansion panel following all the ARIA guidelines.
@@ -0,0 +1,157 @@
import { mdiPacMan } from "@mdi/js";
import { css, html, LitElement, TemplateResult } from "lit";
import { customElement } from "lit/decorators";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-expansion-panel";
import "../../../../src/components/ha-markdown";
import "../../components/demo-black-white-row";
import { LONG_TEXT } from "../../data/text";
const SHORT_TEXT = LONG_TEXT.substring(0, 113);
const SAMPLES: {
template: (slot: string, leftChevron: boolean) => TemplateResult;
}[] = [
{
template(slot, leftChevron) {
return html`
<ha-expansion-panel
slot=${slot}
.leftChevron=${leftChevron}
header="Attr header"
>
${SHORT_TEXT}
</ha-expansion-panel>
`;
},
},
{
template(slot, leftChevron) {
return html`
<ha-expansion-panel
slot=${slot}
.leftChevron=${leftChevron}
header="Attr header"
secondary="Attr secondary"
>
${SHORT_TEXT}
</ha-expansion-panel>
`;
},
},
{
template(slot, leftChevron) {
return html`
<ha-expansion-panel
slot=${slot}
.leftChevron=${leftChevron}
.header=${"Prop header"}
>
${SHORT_TEXT}
</ha-expansion-panel>
`;
},
},
{
template(slot, leftChevron) {
return html`
<ha-expansion-panel
slot=${slot}
.leftChevron=${leftChevron}
.header=${"Prop header"}
.secondary=${"Prop secondary"}
>
${SHORT_TEXT}
</ha-expansion-panel>
`;
},
},
{
template(slot, leftChevron) {
return html`
<ha-expansion-panel
slot=${slot}
.leftChevron=${leftChevron}
.header=${"Prop header"}
>
<span slot="secondary">Slot Secondary</span>
${SHORT_TEXT}
</ha-expansion-panel>
`;
},
},
{
template(slot, leftChevron) {
return html`
<ha-expansion-panel slot=${slot} .leftChevron=${leftChevron}>
<span slot="header">Slot header</span>
${SHORT_TEXT}
</ha-expansion-panel>
`;
},
},
{
template(slot, leftChevron) {
return html`
<ha-expansion-panel slot=${slot} .leftChevron=${leftChevron}>
<span slot="header">Slot header with actions</span>
<ha-icon-button
slot="icons"
label="Some Action"
.path=${mdiPacMan}
></ha-icon-button>
${SHORT_TEXT}
</ha-expansion-panel>
`;
},
},
{
template(slot, leftChevron) {
return html`
<ha-expansion-panel
slot=${slot}
.leftChevron=${leftChevron}
header="Attr Header with actions"
>
<ha-icon-button
slot="icons"
label="Some Action"
.path=${mdiPacMan}
></ha-icon-button>
${SHORT_TEXT}
</ha-expansion-panel>
`;
},
},
];
@customElement("demo-components-ha-expansion-panel")
export class DemoHaExpansionPanel extends LitElement {
protected render(): TemplateResult {
return html`
${SAMPLES.map(
(sample) => html`
<demo-black-white-row>
${["light", "dark"].map((slot) =>
sample.template(slot, slot === "dark")
)}
</demo-black-white-row>
`
)}
`;
}
static get styles() {
return css`
ha-expansion-panel {
margin: -16px;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"demo-components-ha-expansion-panel": DemoHaExpansionPanel;
}
}
+14
View File
@@ -3,6 +3,7 @@ import "@material/mwc-button";
import { html, LitElement, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators";
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
import { mockConfigEntries } from "../../../../demo/src/stubs/config_entries";
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
@@ -20,16 +21,22 @@ const ENTITIES = [
}),
getEntity("media_player", "livingroom", "playing", {
friendly_name: "Livingroom",
media_content_type: "music",
device_class: "tv",
}),
getEntity("media_player", "lounge", "idle", {
friendly_name: "Lounge",
supported_features: 444983,
device_class: "speaker",
}),
getEntity("light", "bedroom", "on", {
friendly_name: "Bedroom",
effect: "colorloop",
effect_list: ["colorloop", "random"],
}),
getEntity("switch", "coffee", "off", {
friendly_name: "Coffee",
device_class: "switch",
}),
];
@@ -141,7 +148,13 @@ const SCHEMAS: {
selector: { attribute: { entity_id: "" } },
context: { filter_entity: "entity" },
},
{
name: "State",
selector: { state: { entity_id: "" } },
context: { filter_entity: "entity", filter_attribute: "Attribute" },
},
{ name: "Device", selector: { device: {} } },
{ name: "Config entry", selector: { config_entry: {} } },
{ name: "Duration", selector: { duration: {} } },
{ name: "area", selector: { area: {} } },
{ name: "target", selector: { target: {} } },
@@ -423,6 +436,7 @@ class DemoHaForm extends LitElement {
hass.addEntities(ENTITIES);
mockEntityRegistry(hass);
mockDeviceRegistry(hass, DEVICES);
mockConfigEntries(hass);
mockAreaRegistry(hass, AREAS);
mockHassioSupervisor(hass);
}
@@ -3,6 +3,7 @@ import "@material/mwc-button";
import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators";
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
import { mockConfigEntries } from "../../../../demo/src/stubs/config_entries";
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
@@ -115,11 +116,19 @@ const SCHEMAS: {
name: "One of each",
input: {
entity: { name: "Entity", selector: { entity: {} } },
state: {
name: "State",
selector: { state: { entity_id: "alarm_control_panel.alarm" } },
},
attribute: {
name: "Attribute",
selector: { attribute: { entity_id: "" } },
},
device: { name: "Device", selector: { device: {} } },
config_entry: {
name: "Integration",
selector: { config_entry: {} },
},
duration: { name: "Duration", selector: { duration: {} } },
addon: { name: "Addon", selector: { addon: {} } },
area: { name: "Area", selector: { area: {} } },
@@ -186,6 +195,48 @@ const SCHEMAS: {
},
},
},
select_disabled_list: {
name: "Select disabled option",
selector: {
select: {
options: [
{ label: "Option 1", value: "Option 1" },
{ label: "Option 2", value: "Option 2" },
{ label: "Option 3", value: "Option 3", disabled: true },
],
mode: "list",
},
},
},
select_disabled_multiple: {
name: "Select disabled option",
selector: {
select: {
multiple: true,
options: [
{ label: "Option 1", value: "Option 1" },
{ label: "Option 2", value: "Option 2" },
{ label: "Option 3", value: "Option 3", disabled: true },
],
mode: "list",
},
},
},
select_disabled: {
name: "Select disabled option",
selector: {
select: {
options: [
{ label: "Option 1", value: "Option 1" },
{ label: "Option 2", value: "Option 2" },
{ label: "Option 3", value: "Option 3", disabled: true },
{ label: "Option 4", value: "Option 4", disabled: true },
{ label: "Option 5", value: "Option 5", disabled: true },
{ label: "Option 6", value: "Option 6" },
],
},
},
},
select_custom: {
name: "Select (Custom)",
selector: {
@@ -276,6 +327,7 @@ class DemoHaSelector extends LitElement implements ProvideHassElement {
hass.addEntities(ENTITIES);
mockEntityRegistry(hass);
mockDeviceRegistry(hass, DEVICES);
mockConfigEntries(hass);
mockAreaRegistry(hass, AREAS);
mockHassioSupervisor(hass);
hass.mockWS("auth/sign_path", (params) => params);
+2 -2
View File
@@ -31,7 +31,7 @@ const ENTITIES = [
friendly_name: "Office Light",
}),
getEntity("fan", "kitchen", "on", {
friendly_name: "Second Office Fan",
friendly_name: "Kitchen Fan",
}),
getEntity("binary_sensor", "kitchen_door", "on", {
friendly_name: "Office Door",
@@ -102,7 +102,7 @@ class DemoArea extends LitElement {
picture: "/images/office.jpg",
},
{
name: "Second Office",
name: "Kitchen",
area_id: "kitchen",
picture: "/images/kitchen.png",
},
@@ -75,6 +75,10 @@ const ENTITIES = [
timestamp: 1641801600,
friendly_name: "Date and Time",
}),
getEntity("sensor", "humidity", "23.2", {
friendly_name: "Humidity",
unit_of_measurement: "%",
}),
getEntity("input_select", "dropdown", "Soda", {
friendly_name: "Dropdown",
options: ["Soda", "Beer", "Wine"],
@@ -142,6 +146,7 @@ const CONFIGS = [
- light.non_existing
- climate.ecobee
- input_number.number
- sensor.humidity
`,
},
{
@@ -1,11 +1,11 @@
---
title: Introduction
---
Lovelace has many different cards. Each card allows the user to tell
Dashboards have many different cards. Each card allows the user to tell
a different story about what is going on in their house. These cards
are very customizable, as no household is the same.
This gallery helps our developers and designers to see all the
different states that each card can be in.
Check [the Lovelace documentation](https://www.home-assistant.io/lovelace) for instructions on how to get started with Lovelace.
Check [the Dashboards documentation](https://www.home-assistant.io/dashboards/) for instructions on how to get started with Dashboards.
@@ -191,9 +191,12 @@ const createEntityRegistryEntries = (
hidden_by: null,
entity_category: null,
entity_id: "binary_sensor.updater",
id: "binary_sensor.updater",
name: null,
icon: null,
platform: "updater",
has_entity_name: false,
unique_id: "updater",
},
];
+63 -58
View File
@@ -1,16 +1,7 @@
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, query } from "lit/decorators";
import "../../../../src/components/ha-card";
import {
SUPPORT_OPEN,
SUPPORT_STOP,
SUPPORT_CLOSE,
SUPPORT_SET_POSITION,
SUPPORT_OPEN_TILT,
SUPPORT_STOP_TILT,
SUPPORT_CLOSE_TILT,
SUPPORT_SET_TILT_POSITION,
} from "../../../../src/data/cover";
import { CoverEntityFeature } from "../../../../src/data/cover";
import "../../../../src/dialogs/more-info/more-info-content";
import { getEntity } from "../../../../src/fake_data/entity";
import {
@@ -22,113 +13,127 @@ import "../../components/demo-more-infos";
const ENTITIES = [
getEntity("cover", "position_buttons", "on", {
friendly_name: "Position Buttons",
supported_features: SUPPORT_OPEN + SUPPORT_STOP + SUPPORT_CLOSE,
supported_features:
CoverEntityFeature.OPEN +
CoverEntityFeature.STOP +
CoverEntityFeature.CLOSE,
}),
getEntity("cover", "position_slider_half", "on", {
friendly_name: "Position Half-Open",
supported_features:
SUPPORT_OPEN + SUPPORT_STOP + SUPPORT_CLOSE + SUPPORT_SET_POSITION,
CoverEntityFeature.OPEN +
CoverEntityFeature.STOP +
CoverEntityFeature.CLOSE +
CoverEntityFeature.SET_POSITION,
current_position: 50,
}),
getEntity("cover", "position_slider_open", "on", {
friendly_name: "Position Open",
supported_features:
SUPPORT_OPEN + SUPPORT_STOP + SUPPORT_CLOSE + SUPPORT_SET_POSITION,
CoverEntityFeature.OPEN +
CoverEntityFeature.STOP +
CoverEntityFeature.CLOSE +
CoverEntityFeature.SET_POSITION,
current_position: 100,
}),
getEntity("cover", "position_slider_closed", "on", {
friendly_name: "Position Closed",
supported_features:
SUPPORT_OPEN + SUPPORT_STOP + SUPPORT_CLOSE + SUPPORT_SET_POSITION,
CoverEntityFeature.OPEN +
CoverEntityFeature.STOP +
CoverEntityFeature.CLOSE +
CoverEntityFeature.SET_POSITION,
current_position: 0,
}),
getEntity("cover", "tilt_buttons", "on", {
friendly_name: "Tilt Buttons",
supported_features:
SUPPORT_OPEN_TILT + SUPPORT_STOP_TILT + SUPPORT_CLOSE_TILT,
CoverEntityFeature.OPEN_TILT +
CoverEntityFeature.STOP_TILT +
CoverEntityFeature.CLOSE_TILT,
}),
getEntity("cover", "tilt_slider_half", "on", {
friendly_name: "Tilt Half-Open",
supported_features:
SUPPORT_OPEN_TILT +
SUPPORT_STOP_TILT +
SUPPORT_CLOSE_TILT +
SUPPORT_SET_TILT_POSITION,
CoverEntityFeature.OPEN_TILT +
CoverEntityFeature.STOP_TILT +
CoverEntityFeature.CLOSE_TILT +
CoverEntityFeature.SET_TILT_POSITION,
current_tilt_position: 50,
}),
getEntity("cover", "tilt_slider_open", "on", {
friendly_name: "Tilt Open",
supported_features:
SUPPORT_OPEN_TILT +
SUPPORT_STOP_TILT +
SUPPORT_CLOSE_TILT +
SUPPORT_SET_TILT_POSITION,
CoverEntityFeature.OPEN_TILT +
CoverEntityFeature.STOP_TILT +
CoverEntityFeature.CLOSE_TILT +
CoverEntityFeature.SET_TILT_POSITION,
current_tilt_position: 100,
}),
getEntity("cover", "tilt_slider_closed", "on", {
friendly_name: "Tilt Closed",
supported_features:
SUPPORT_OPEN_TILT +
SUPPORT_STOP_TILT +
SUPPORT_CLOSE_TILT +
SUPPORT_SET_TILT_POSITION,
CoverEntityFeature.OPEN_TILT +
CoverEntityFeature.STOP_TILT +
CoverEntityFeature.CLOSE_TILT +
CoverEntityFeature.SET_TILT_POSITION,
current_tilt_position: 0,
}),
getEntity("cover", "position_slider_tilt_slider", "on", {
friendly_name: "Both Sliders",
supported_features:
SUPPORT_OPEN +
SUPPORT_STOP +
SUPPORT_CLOSE +
SUPPORT_SET_POSITION +
SUPPORT_OPEN_TILT +
SUPPORT_STOP_TILT +
SUPPORT_CLOSE_TILT +
SUPPORT_SET_TILT_POSITION,
CoverEntityFeature.OPEN +
CoverEntityFeature.STOP +
CoverEntityFeature.CLOSE +
CoverEntityFeature.SET_POSITION +
CoverEntityFeature.OPEN_TILT +
CoverEntityFeature.STOP_TILT +
CoverEntityFeature.CLOSE_TILT +
CoverEntityFeature.SET_TILT_POSITION,
current_position: 30,
current_tilt_position: 70,
}),
getEntity("cover", "position_tilt_slider", "on", {
friendly_name: "Position & Tilt Slider",
supported_features:
SUPPORT_OPEN +
SUPPORT_STOP +
SUPPORT_CLOSE +
SUPPORT_OPEN_TILT +
SUPPORT_STOP_TILT +
SUPPORT_CLOSE_TILT +
SUPPORT_SET_TILT_POSITION,
CoverEntityFeature.OPEN +
CoverEntityFeature.STOP +
CoverEntityFeature.CLOSE +
CoverEntityFeature.OPEN_TILT +
CoverEntityFeature.STOP_TILT +
CoverEntityFeature.CLOSE_TILT +
CoverEntityFeature.SET_TILT_POSITION,
current_tilt_position: 70,
}),
getEntity("cover", "position_slider_tilt", "on", {
friendly_name: "Position Slider & Tilt",
supported_features:
SUPPORT_OPEN +
SUPPORT_STOP +
SUPPORT_CLOSE +
SUPPORT_SET_POSITION +
SUPPORT_OPEN_TILT +
SUPPORT_STOP_TILT +
SUPPORT_CLOSE_TILT,
CoverEntityFeature.OPEN +
CoverEntityFeature.STOP +
CoverEntityFeature.CLOSE +
CoverEntityFeature.SET_POSITION +
CoverEntityFeature.OPEN_TILT +
CoverEntityFeature.STOP_TILT +
CoverEntityFeature.CLOSE_TILT,
current_position: 30,
}),
getEntity("cover", "position_slider_only_tilt_slider", "on", {
friendly_name: "Position Slider Only & Tilt Buttons",
supported_features:
SUPPORT_SET_POSITION +
SUPPORT_OPEN_TILT +
SUPPORT_STOP_TILT +
SUPPORT_CLOSE_TILT,
CoverEntityFeature.SET_POSITION +
CoverEntityFeature.OPEN_TILT +
CoverEntityFeature.STOP_TILT +
CoverEntityFeature.CLOSE_TILT,
current_position: 30,
}),
getEntity("cover", "position_slider_only_tilt", "on", {
friendly_name: "Position Slider Only & Tilt",
supported_features:
SUPPORT_SET_POSITION +
SUPPORT_OPEN_TILT +
SUPPORT_STOP_TILT +
SUPPORT_CLOSE_TILT +
SUPPORT_SET_TILT_POSITION,
CoverEntityFeature.SET_POSITION +
CoverEntityFeature.OPEN_TILT +
CoverEntityFeature.STOP_TILT +
CoverEntityFeature.CLOSE_TILT +
CoverEntityFeature.SET_TILT_POSITION,
current_position: 30,
current_tilt_position: 70,
}),
@@ -0,0 +1,3 @@
---
title: Input Number
---
@@ -0,0 +1,60 @@
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, query } from "lit/decorators";
import "../../../../src/components/ha-card";
import "../../../../src/dialogs/more-info/more-info-content";
import { getEntity } from "../../../../src/fake_data/entity";
import {
MockHomeAssistant,
provideHass,
} from "../../../../src/fake_data/provide_hass";
import "../../components/demo-more-infos";
const ENTITIES = [
getEntity("input_number", "box1", 0, {
friendly_name: "Box1",
min: 0,
max: 100,
step: 1,
initial: 0,
mode: "box",
unit_of_measurement: "items",
}),
getEntity("input_number", "slider1", 0, {
friendly_name: "Slider1",
min: 0,
max: 100,
step: 1,
initial: 0,
mode: "slider",
unit_of_measurement: "items",
}),
];
@customElement("demo-more-info-input-number")
class DemoMoreInfoInputNumber extends LitElement {
@property() public hass!: MockHomeAssistant;
@query("demo-more-infos") private _demoRoot!: HTMLElement;
protected render(): TemplateResult {
return html`
<demo-more-infos
.hass=${this.hass}
.entities=${ENTITIES.map((ent) => ent.entityId)}
></demo-more-infos>
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");
hass.addEntities(ENTITIES);
}
}
declare global {
interface HTMLElementTagNameMap {
"demo-more-info-input-number": DemoMoreInfoInputNumber;
}
}
+53 -40
View File
@@ -1,12 +1,7 @@
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, query } from "lit/decorators";
import "../../../../src/components/ha-card";
import {
LightColorModes,
SUPPORT_EFFECT,
SUPPORT_FLASH,
SUPPORT_TRANSITION,
} from "../../../../src/data/light";
import { LightColorMode, LightEntityFeature } from "../../../../src/data/light";
import "../../../../src/dialogs/more-info/more-info-content";
import { getEntity } from "../../../../src/fake_data/entity";
import {
@@ -22,8 +17,8 @@ const ENTITIES = [
getEntity("light", "kitchen_light", "on", {
friendly_name: "Brightness Light",
brightness: 200,
supported_color_modes: [LightColorModes.BRIGHTNESS],
color_mode: LightColorModes.BRIGHTNESS,
supported_color_modes: [LightColorMode.BRIGHTNESS],
color_mode: LightColorMode.BRIGHTNESS,
}),
getEntity("light", "color_temperature_light", "on", {
friendly_name: "White Color Temperature Light",
@@ -32,10 +27,10 @@ const ENTITIES = [
min_mireds: 30,
max_mireds: 150,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
LightColorMode.BRIGHTNESS,
LightColorMode.COLOR_TEMP,
],
color_mode: LightColorModes.COLOR_TEMP,
color_mode: LightColorMode.COLOR_TEMP,
}),
getEntity("light", "color_hs_light", "on", {
friendly_name: "Color HS Light",
@@ -44,13 +39,16 @@ const ENTITIES = [
rgb_color: [30, 100, 255],
min_mireds: 30,
max_mireds: 150,
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_features:
LightEntityFeature.EFFECT +
LightEntityFeature.FLASH +
LightEntityFeature.TRANSITION,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
LightColorModes.HS,
LightColorMode.BRIGHTNESS,
LightColorMode.COLOR_TEMP,
LightColorMode.HS,
],
color_mode: LightColorModes.HS,
color_mode: LightColorMode.HS,
effect_list: ["random", "colorloop"],
}),
getEntity("light", "color_rgb_ct_light", "on", {
@@ -59,22 +57,28 @@ const ENTITIES = [
color_temp: 75,
min_mireds: 30,
max_mireds: 150,
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_features:
LightEntityFeature.EFFECT +
LightEntityFeature.FLASH +
LightEntityFeature.TRANSITION,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
LightColorModes.RGB,
LightColorMode.BRIGHTNESS,
LightColorMode.COLOR_TEMP,
LightColorMode.RGB,
],
color_mode: LightColorModes.COLOR_TEMP,
color_mode: LightColorMode.COLOR_TEMP,
effect_list: ["random", "colorloop"],
}),
getEntity("light", "color_RGB_light", "on", {
friendly_name: "Color Effets Light",
friendly_name: "Color Effects Light",
brightness: 255,
rgb_color: [30, 100, 255],
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_color_modes: [LightColorModes.BRIGHTNESS, LightColorModes.RGB],
color_mode: LightColorModes.RGB,
supported_features:
LightEntityFeature.EFFECT +
LightEntityFeature.FLASH +
LightEntityFeature.TRANSITION,
supported_color_modes: [LightColorMode.BRIGHTNESS, LightColorMode.RGB],
color_mode: LightColorMode.RGB,
effect_list: ["random", "colorloop"],
}),
getEntity("light", "color_rgbw_light", "on", {
@@ -83,13 +87,16 @@ const ENTITIES = [
rgbw_color: [30, 100, 255, 125],
min_mireds: 30,
max_mireds: 150,
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_features:
LightEntityFeature.EFFECT +
LightEntityFeature.FLASH +
LightEntityFeature.TRANSITION,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
LightColorModes.RGBW,
LightColorMode.BRIGHTNESS,
LightColorMode.COLOR_TEMP,
LightColorMode.RGBW,
],
color_mode: LightColorModes.RGBW,
color_mode: LightColorMode.RGBW,
effect_list: ["random", "colorloop"],
}),
getEntity("light", "color_rgbww_light", "on", {
@@ -98,13 +105,16 @@ const ENTITIES = [
rgbww_color: [30, 100, 255, 125, 10],
min_mireds: 30,
max_mireds: 150,
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_features:
LightEntityFeature.EFFECT +
LightEntityFeature.FLASH +
LightEntityFeature.TRANSITION,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
LightColorModes.RGBWW,
LightColorMode.BRIGHTNESS,
LightColorMode.COLOR_TEMP,
LightColorMode.RGBWW,
],
color_mode: LightColorModes.RGBWW,
color_mode: LightColorMode.RGBWW,
effect_list: ["random", "colorloop"],
}),
getEntity("light", "color_xy_light", "on", {
@@ -114,13 +124,16 @@ const ENTITIES = [
rgb_color: [30, 100, 255],
min_mireds: 30,
max_mireds: 150,
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_features:
LightEntityFeature.EFFECT +
LightEntityFeature.FLASH +
LightEntityFeature.TRANSITION,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
LightColorModes.XY,
LightColorMode.BRIGHTNESS,
LightColorMode.COLOR_TEMP,
LightColorMode.XY,
],
color_mode: LightColorModes.XY,
color_mode: LightColorMode.XY,
effect_list: ["random", "colorloop"],
}),
];
@@ -6,10 +6,8 @@ import { atLeastVersion } from "../../../src/common/config/version";
import { navigate } from "../../../src/common/navigate";
import { caseInsensitiveStringCompare } from "../../../src/common/string/compare";
import "../../../src/components/ha-card";
import {
HassioAddonInfo,
HassioAddonRepository,
} from "../../../src/data/hassio/addon";
import { HassioAddonRepository } from "../../../src/data/hassio/addon";
import { StoreAddon } from "../../../src/data/supervisor/store";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import { HomeAssistant } from "../../../src/types";
import "../components/hassio-card-content";
@@ -23,20 +21,16 @@ class HassioAddonRepositoryEl extends LitElement {
@property({ attribute: false }) public repo!: HassioAddonRepository;
@property({ attribute: false }) public addons!: HassioAddonInfo[];
@property({ attribute: false }) public addons!: StoreAddon[];
@property() public filter!: string;
private _getAddons = memoizeOne(
(addons: HassioAddonInfo[], filter?: string) => {
if (filter) {
return filterAndSort(addons, filter);
}
return addons.sort((a, b) =>
caseInsensitiveStringCompare(a.name, b.name)
);
private _getAddons = memoizeOne((addons: StoreAddon[], filter?: string) => {
if (filter) {
return filterAndSort(addons, filter);
}
);
return addons.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name));
});
protected render(): TemplateResult {
const repo = this.repo;
@@ -87,10 +81,10 @@ class HassioAddonRepositoryEl extends LitElement {
? this.supervisor.localize(
"common.new_version_available"
)
: this.supervisor.localize("addon.installed")
: this.supervisor.localize("addon.state.installed")
: addon.available
? this.supervisor.localize("addon.not_installed")
: this.supervisor.localize("addon.not_available")}
? this.supervisor.localize("addon.state.not_installed")
: this.supervisor.localize("addon.state.not_available")}
.iconClass=${addon.installed
? addon.update_available
? "update"
+17 -8
View File
@@ -14,16 +14,18 @@ import memoizeOne from "memoize-one";
import { atLeastVersion } from "../../../src/common/config/version";
import { fireEvent } from "../../../src/common/dom/fire_event";
import { navigate } from "../../../src/common/navigate";
import "../../../src/components/search-input";
import { extractSearchParam } from "../../../src/common/url/search-params";
import "../../../src/components/ha-button-menu";
import "../../../src/components/ha-icon-button";
import "../../../src/components/search-input";
import {
HassioAddonInfo,
HassioAddonRepository,
reloadHassioAddons,
} from "../../../src/data/hassio/addon";
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
import { StoreAddon } from "../../../src/data/supervisor/store";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
import "../../../src/layouts/hass-loading-screen";
import "../../../src/layouts/hass-subpage";
import { HomeAssistant, Route } from "../../../src/types";
@@ -59,17 +61,24 @@ class HassioAddonStore extends LitElement {
@state() private _filter?: string;
public async refreshData() {
await reloadHassioAddons(this.hass);
await this._loadData();
try {
await reloadHassioAddons(this.hass);
} catch (err) {
showAlertDialog(this, {
text: extractApiErrorMessage(err),
});
} finally {
await this._loadData();
}
}
protected render(): TemplateResult {
let repos: TemplateResult[] = [];
if (this.supervisor.addon.repositories) {
if (this.supervisor.store.repositories) {
repos = this.addonRepositories(
this.supervisor.addon.repositories,
this.supervisor.addon.addons,
this.supervisor.store.repositories,
this.supervisor.store.addons,
this._filter
);
}
@@ -145,7 +154,7 @@ class HassioAddonStore extends LitElement {
private addonRepositories = memoizeOne(
(
repositories: HassioAddonRepository[],
addons: HassioAddonInfo[],
addons: StoreAddon[],
filter?: string
) =>
repositories.sort(sortRepos).map((repo) => {
@@ -336,7 +336,7 @@ class HassioAddonConfig extends LitElement {
fireEvent(this, "hass-api-called", eventdata);
} catch (err: any) {
this._error = this.supervisor.localize(
"addon.common.update_available",
"addon.failed_to_reset",
"error",
extractApiErrorMessage(err)
);
@@ -81,7 +81,7 @@ class HassioAddonDocumentationDashboard extends LitElement {
);
} catch (err: any) {
this._error = this.supervisor.localize(
"addon.documentation.get_logs",
"addon.documentation.get_documentation",
"error",
extractApiErrorMessage(err)
);
+23 -19
View File
@@ -12,15 +12,17 @@ import { navigate } from "../../../src/common/navigate";
import { extractSearchParam } from "../../../src/common/url/search-params";
import "../../../src/components/ha-circular-progress";
import {
fetchAddonInfo,
fetchHassioAddonInfo,
fetchHassioAddonsInfo,
HassioAddonDetails,
} from "../../../src/data/hassio/addon";
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
import {
fetchHassioSupervisorInfo,
setSupervisorOption,
} from "../../../src/data/hassio/supervisor";
addStoreRepository,
fetchSupervisorStore,
StoreAddonDetails,
} from "../../../src/data/supervisor/store";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import { showConfirmationDialog } from "../../../src/dialogs/generic/show-dialog-box";
import "../../../src/layouts/hass-error-screen";
@@ -45,7 +47,9 @@ class HassioAddonDashboard extends LitElement {
@property({ attribute: false }) public route!: Route;
@property({ attribute: false }) public addon?: HassioAddonDetails;
@property({ attribute: false }) public addon?:
| HassioAddonDetails
| StoreAddonDetails;
@property({ type: Boolean }) public narrow!: boolean;
@@ -71,7 +75,7 @@ class HassioAddonDashboard extends LitElement {
></hass-error-screen>`;
}
if (!this.addon) {
if (!this.addon || !this.supervisor?.addon) {
return html`<hass-loading-screen></hass-loading-screen>`;
}
@@ -173,10 +177,10 @@ class HassioAddonDashboard extends LitElement {
const requestedAddon = extractSearchParam("addon");
const requestedAddonRepository = extractSearchParam("repository_url");
if (requestedAddonRepository) {
const supervisorInfo = await fetchHassioSupervisorInfo(this.hass);
const storeInfo = await fetchSupervisorStore(this.hass);
if (
!supervisorInfo.addons_repositories.find(
(repo) => repo === requestedAddonRepository
!storeInfo.repositories.find(
(repo) => repo.source === requestedAddonRepository
)
) {
if (
@@ -197,12 +201,7 @@ class HassioAddonDashboard extends LitElement {
}
try {
await setSupervisorOption(this.hass, {
addons_repositories: [
...supervisorInfo.addons_repositories,
requestedAddonRepository,
],
});
await addStoreRepository(this.hass, requestedAddonRepository);
} catch (err: any) {
this._error = extractApiErrorMessage(err);
}
@@ -210,8 +209,8 @@ class HassioAddonDashboard extends LitElement {
}
if (requestedAddon) {
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
const validAddon = addonsInfo.addons.some(
const store = await fetchSupervisorStore(this.hass);
const validAddon = store.addons.some(
(addon) => addon.slug === requestedAddon
);
if (!validAddon) {
@@ -239,12 +238,14 @@ class HassioAddonDashboard extends LitElement {
if (["uninstall", "install", "update", "start", "stop"].includes(path)) {
fireEvent(this, "supervisor-collection-refresh", {
collection: "supervisor",
collection: "addon",
});
}
if (path === "uninstall") {
window.history.back();
} else if (path === "install") {
this.addon = await fetchHassioAddonInfo(this.hass, this.addon!.slug);
} else {
await this._routeDataChanged();
}
@@ -262,8 +263,11 @@ class HassioAddonDashboard extends LitElement {
return;
}
try {
const addoninfo = await fetchHassioAddonInfo(this.hass, addon);
this.addon = addoninfo;
if (!this.supervisor.addon) {
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
fireEvent(this, "supervisor-update", { addon: addonsInfo });
}
this.addon = await fetchAddonInfo(this.hass, this.supervisor, addon);
} catch (err: any) {
this._error = `Error fetching addon info: ${extractApiErrorMessage(err)}`;
this.addon = undefined;
+4 -1
View File
@@ -1,5 +1,6 @@
import { customElement, property } from "lit/decorators";
import { HassioAddonDetails } from "../../../src/data/hassio/addon";
import { StoreAddonDetails } from "../../../src/data/supervisor/store";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import {
HassRouterPage,
@@ -20,7 +21,9 @@ class HassioAddonRouter extends HassRouterPage {
@property({ attribute: false }) public supervisor!: Supervisor;
@property({ attribute: false }) public addon!: HassioAddonDetails;
@property({ attribute: false }) public addon!:
| HassioAddonDetails
| StoreAddonDetails;
protected routerOptions: RouterOptions = {
defaultPage: "info",
+35 -21
View File
@@ -40,6 +40,7 @@ import "../../../../src/components/ha-settings-row";
import "../../../../src/components/ha-svg-icon";
import "../../../../src/components/ha-switch";
import {
AddonCapability,
fetchHassioAddonChangelog,
fetchHassioAddonInfo,
HassioAddonDetails,
@@ -59,7 +60,10 @@ import {
fetchHassioStats,
HassioStats,
} from "../../../../src/data/hassio/common";
import { StoreAddon } from "../../../../src/data/supervisor/store";
import {
StoreAddon,
StoreAddonDetails,
} from "../../../../src/data/supervisor/store";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
import {
showAlertDialog,
@@ -100,7 +104,9 @@ class HassioAddonInfo extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public addon!: HassioAddonDetails;
@property({ attribute: false }) public addon!:
| HassioAddonDetails
| StoreAddonDetails;
@property({ attribute: false }) public supervisor!: Supervisor;
@@ -143,7 +149,7 @@ class HassioAddonInfo extends LitElement {
></update-available-card>
`
: ""}
${!this.addon.protected
${"protected" in this.addon && !this.addon.protected
? html`
<ha-alert
alert-type="error"
@@ -518,7 +524,7 @@ class HassioAddonInfo extends LitElement {
: ""}
</div>
<div>
${this.addon.state === "started"
${this.addon.version && this.addon.state === "started"
? html`<ha-settings-row ?three-line=${this.narrow}>
<span slot="heading">
${this.supervisor.localize("addon.dashboard.hostname")}
@@ -669,7 +675,7 @@ class HassioAddonInfo extends LitElement {
}
private async _loadData(): Promise<void> {
if (this.addon.state === "started") {
if ("state" in this.addon && this.addon.state === "started") {
this._metrics = await fetchHassioStats(
this.hass,
`addons/${this.addon.slug}`
@@ -696,7 +702,7 @@ class HassioAddonInfo extends LitElement {
}
private _showMoreInfo(ev): void {
const id = ev.currentTarget.id;
const id = ev.currentTarget.id as AddonCapability;
showHassioMarkdownDialog(this, {
title: this.supervisor.localize(`addon.dashboard.capability.${id}.title`),
content:
@@ -717,18 +723,22 @@ class HassioAddonInfo extends LitElement {
}
private get _computeIsRunning(): boolean {
return this.addon?.state === "started";
return (this.addon as HassioAddonDetails)?.state === "started";
}
private get _pathWebui(): string | null {
return (
this.addon.webui &&
this.addon.webui.replace("[HOST]", document.location.hostname)
return (this.addon as HassioAddonDetails).webui!.replace(
"[HOST]",
document.location.hostname
);
}
private get _computeShowWebUI(): boolean | "" | null {
return !this.addon.ingress && this.addon.webui && this._computeIsRunning;
return (
!this.addon.ingress &&
(this.addon as HassioAddonDetails).webui &&
this._computeIsRunning
);
}
private _openIngress(): void {
@@ -754,7 +764,8 @@ class HassioAddonInfo extends LitElement {
private async _startOnBootToggled(): Promise<void> {
this._error = undefined;
const data: HassioAddonSetOptionParams = {
boot: this.addon.boot === "auto" ? "manual" : "auto",
boot:
(this.addon as HassioAddonDetails).boot === "auto" ? "manual" : "auto",
};
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
@@ -776,7 +787,7 @@ class HassioAddonInfo extends LitElement {
private async _watchdogToggled(): Promise<void> {
this._error = undefined;
const data: HassioAddonSetOptionParams = {
watchdog: !this.addon.watchdog,
watchdog: !(this.addon as HassioAddonDetails).watchdog,
};
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
@@ -798,7 +809,7 @@ class HassioAddonInfo extends LitElement {
private async _autoUpdateToggled(): Promise<void> {
this._error = undefined;
const data: HassioAddonSetOptionParams = {
auto_update: !this.addon.auto_update,
auto_update: !(this.addon as HassioAddonDetails).auto_update,
};
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
@@ -820,7 +831,7 @@ class HassioAddonInfo extends LitElement {
private async _protectionToggled(): Promise<void> {
this._error = undefined;
const data: HassioAddonSetSecurityParams = {
protected: !this.addon.protected,
protected: !(this.addon as HassioAddonDetails).protected,
};
try {
await setHassioAddonSecurity(this.hass, this.addon.slug, data);
@@ -842,7 +853,7 @@ class HassioAddonInfo extends LitElement {
private async _panelToggled(): Promise<void> {
this._error = undefined;
const data: HassioAddonSetOptionParams = {
ingress_panel: !this.addon.ingress_panel,
ingress_panel: !(this.addon as HassioAddonDetails).ingress_panel,
};
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
@@ -870,7 +881,7 @@ class HassioAddonInfo extends LitElement {
showHassioMarkdownDialog(this, {
title: this.supervisor.localize("addon.dashboard.changelog"),
content: extractChangelog(this.addon, content),
content: extractChangelog(this.addon as HassioAddonDetails, content),
});
} catch (err: any) {
showAlertDialog(this, {
@@ -1013,10 +1024,13 @@ class HassioAddonInfo extends LitElement {
button.progress = true;
const confirmed = await showConfirmationDialog(this, {
title: this.addon.name,
text: "Are you sure you want to uninstall this add-on?",
confirmText: "uninstall add-on",
dismissText: "no",
title: this.supervisor.localize("dialog.uninstall_addon.title", {
name: this.addon.name,
}),
text: this.supervisor.localize("dialog.uninstall_addon.text"),
confirmText: this.supervisor.localize("dialog.uninstall_addon.uninstall"),
dismissText: this.supervisor.localize("common.cancel"),
destructive: true,
});
if (!confirmed) {
+4 -5
View File
@@ -98,9 +98,8 @@ export class HassioBackups extends LitElement {
if (backup.content.addons.length !== 0) {
for (const addon of backup.content.addons) {
content.push(
this.supervisor.supervisor.addons.find(
(entry) => entry.slug === addon
)?.name || addon
this.supervisor.addon.addons.find((entry) => entry.slug === addon)
?.name || addon
);
}
}
@@ -177,7 +176,7 @@ export class HassioBackups extends LitElement {
: supervisorTabs(this.hass)}
.hass=${this.hass}
.localizeFunc=${this.supervisor.localize}
.searchLabel=${this.supervisor.localize("search")}
.searchLabel=${this.supervisor.localize("backup.search")}
.noDataText=${this.supervisor.localize("backup.no_backups")}
.narrow=${this.narrow}
.route=${this.route}
@@ -241,7 +240,7 @@ export class HassioBackups extends LitElement {
: html`
<ha-icon-button
.label=${this.supervisor.localize(
"snapshot.delete_selected"
"backup.delete_selected"
)}
.path=${mdiDelete}
id="delete-btn"
@@ -1,8 +1,8 @@
import Fuse from "fuse.js";
import { HassioAddonInfo } from "../../../src/data/hassio/addon";
import { StoreAddon } from "../../../src/data/supervisor/store";
export function filterAndSort(addons: HassioAddonInfo[], filter: string) {
const options: Fuse.IFuseOptions<HassioAddonInfo> = {
export function filterAndSort(addons: StoreAddon[], filter: string) {
const options: Fuse.IFuseOptions<StoreAddon> = {
keys: ["name", "description", "slug"],
isCaseSensitive: false,
minMatchCharLength: 2,
@@ -17,9 +17,12 @@ import {
} from "../../../src/data/hassio/backup";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import { PolymerChangedEvent } from "../../../src/polymer-types";
import { HomeAssistant } from "../../../src/types";
import { HomeAssistant, TranslationDict } from "../../../src/types";
import "./supervisor-formfield-label";
type BackupOrRestoreKey = keyof TranslationDict["supervisor"]["backup"] &
keyof TranslationDict["ui"]["panel"]["page-onboarding"]["restore"];
interface CheckboxItem {
slug: string;
checked: boolean;
@@ -96,7 +99,7 @@ export class SupervisorBackupContent extends LitElement {
: ["ssl", "share", "media", "addons/local"]
);
this.addons = _computeAddons(
this.backup ? this.backup.addons : this.supervisor?.supervisor.addons
this.backup ? this.backup.addons : this.supervisor?.addon.addons
);
this.backupType = this.backup?.type || "full";
this.backupName = this.backup?.name || "";
@@ -108,9 +111,9 @@ export class SupervisorBackupContent extends LitElement {
this._focusTarget?.focus();
}
private _localize = (string: string) =>
this.supervisor?.localize(`backup.${string}`) ||
this.localize!(`ui.panel.page-onboarding.restore.${string}`);
private _localize = (key: BackupOrRestoreKey) =>
this.supervisor?.localize(`backup.${key}`) ||
this.localize!(`ui.panel.page-onboarding.restore.${key}`);
protected render(): TemplateResult {
if (!this.onboarding && !this.supervisor) {
@@ -168,23 +171,24 @@ export class SupervisorBackupContent extends LitElement {
: ""}
${this.backupType === "partial"
? html`<div class="partial-picker">
<ha-formfield
.label=${html`<supervisor-formfield-label
label="Home Assistant"
.iconPath=${mdiHomeAssistant}
.version=${this.backup
? this.backup.homeassistant
: this.hass.config.version}
>
</supervisor-formfield-label>`}
>
<ha-checkbox
.checked=${this.homeAssistant}
@change=${this.toggleHomeAssistant}
>
</ha-checkbox>
</ha-formfield>
${!this.backup || this.backup.homeassistant
? html`<ha-formfield
.label=${html`<supervisor-formfield-label
label="Home Assistant"
.iconPath=${mdiHomeAssistant}
.version=${this.backup
? this.backup.homeassistant
: this.hass.config.version}
>
</supervisor-formfield-label>`}
>
<ha-checkbox
.checked=${this.homeAssistant}
@change=${this.toggleHomeAssistant}
>
</ha-checkbox>
</ha-formfield>`
: ""}
${foldersSection?.templates.length
? html`
<ha-formfield
+2 -2
View File
@@ -24,7 +24,7 @@ class HassioAddons extends LitElement {
? html` <h1>${this.supervisor.localize("dashboard.addons")}</h1> `
: ""}
<div class="card-group">
${!this.supervisor.supervisor.addons?.length
${!this.supervisor.addon.addons.length
? html`
<ha-card outlined>
<div class="card-content">
@@ -34,7 +34,7 @@ class HassioAddons extends LitElement {
</div>
</ha-card>
`
: this.supervisor.supervisor.addons
: this.supervisor.addon.addons
.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name))
.map(
(addon) => html`
@@ -201,26 +201,24 @@ class HassioBackupDialog
}
if (!this._dialogParams?.onboarding) {
this.hass!.callApi(
"POST",
try {
await this.hass!.callApi(
"POST",
`hassio/${
atLeastVersion(this.hass!.config.version, 2021, 9)
? "backups"
: "snapshots"
}/${this._backup!.slug}/restore/partial`,
backupDetails
).then(
() => {
this.closeDialog();
},
(error) => {
this._error = error.body.message;
}
);
`hassio/${
atLeastVersion(this.hass!.config.version, 2021, 9)
? "backups"
: "snapshots"
}/${this._backup!.slug}/restore/partial`,
backupDetails
);
this.closeDialog();
} catch (error: any) {
this._error = error.body.message;
}
} else {
fireEvent(this, "restoring");
fetch(`/api/hassio/backups/${this._backup!.slug}/restore/partial`, {
await fetch(`/api/hassio/backups/${this._backup!.slug}/restore/partial`, {
method: "POST",
body: JSON.stringify(backupDetails),
});
@@ -4,7 +4,7 @@ import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { createCloseHeading } from "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-form/ha-form";
import { HaFormSchema } from "../../../../src/components/ha-form/types";
import type { SchemaUnion } from "../../../../src/components/ha-form/types";
import "../../../../src/components/ha-icon-button";
import "../../../../src/components/ha-settings-row";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
@@ -19,7 +19,7 @@ import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import type { HomeAssistant } from "../../../../src/types";
import { RegistriesDialogParams } from "./show-dialog-registries";
const SCHEMA: HaFormSchema[] = [
const SCHEMA = [
{
name: "registry",
required: true,
@@ -35,7 +35,7 @@ const SCHEMA: HaFormSchema[] = [
required: true,
selector: { text: { type: "password" } },
},
];
] as const;
@customElement("dialog-hassio-registries")
class HassioRegistriesDialog extends LitElement {
@@ -135,8 +135,8 @@ class HassioRegistriesDialog extends LitElement {
`;
}
private _computeLabel = (schema: HaFormSchema) =>
this.supervisor.localize(`dialog.registries.${schema.name}`) || schema.name;
private _computeLabel = (schema: SchemaUnion<typeof SCHEMA>) =>
this.supervisor.localize(`dialog.registries.${schema.name}`);
private _valueChanged(ev: CustomEvent) {
this._input = ev.detail.value;
@@ -15,15 +15,18 @@ import "../../../../src/components/ha-circular-progress";
import { createCloseHeading } from "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-icon-button";
import {
fetchHassioAddonsInfo,
HassioAddonInfo,
HassioAddonRepository,
} from "../../../../src/data/hassio/addon";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
import { setSupervisorOption } from "../../../../src/data/hassio/supervisor";
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import type { HomeAssistant } from "../../../../src/types";
import { HassioRepositoryDialogParams } from "./show-dialog-repositories";
import {
addStoreRepository,
fetchStoreRepositories,
removeStoreRepository,
} from "../../../../src/data/supervisor/store";
@customElement("dialog-hassio-repositories")
class HassioRepositoriesDialog extends LitElement {
@@ -58,7 +61,13 @@ class HassioRepositoriesDialog extends LitElement {
private _filteredRepositories = memoizeOne((repos: HassioAddonRepository[]) =>
repos
.filter((repo) => repo.slug !== "core" && repo.slug !== "local")
.filter(
(repo) =>
repo.slug !== "core" && // The core add-ons repository
repo.slug !== "local" && // Locally managed add-ons
repo.slug !== "a0d7b954" && // Home Assistant Community Add-ons
repo.slug !== "5c53de3b" // The ESPHome repository
)
.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name))
);
@@ -78,7 +87,7 @@ class HassioRepositoriesDialog extends LitElement {
const repositories = this._filteredRepositories(this._repositories);
const usedRepositories = this._filteredUsedRepositories(
repositories,
this._dialogParams.supervisor.supervisor.addons
this._dialogParams.supervisor.addon.addons
);
return html`
<ha-dialog
@@ -215,9 +224,7 @@ class HassioRepositoriesDialog extends LitElement {
private async _loadData(): Promise<void> {
try {
const addonsinfo = await fetchHassioAddonsInfo(this.hass);
this._repositories = addonsinfo.repositories;
this._repositories = await fetchStoreRepositories(this.hass);
fireEvent(this, "supervisor-collection-refresh", { collection: "addon" });
} catch (err: any) {
@@ -231,14 +238,9 @@ class HassioRepositoriesDialog extends LitElement {
return;
}
this._processing = true;
const repositories = this._filteredRepositories(this._repositories!);
const newRepositories = repositories.map((repo) => repo.source);
newRepositories.push(input.value);
try {
await setSupervisorOption(this.hass, {
addons_repositories: newRepositories,
});
await addStoreRepository(this.hass, input.value);
await this._loadData();
input.value = "";
@@ -250,19 +252,8 @@ class HassioRepositoriesDialog extends LitElement {
private async _removeRepository(ev: Event) {
const slug = (ev.currentTarget as any).slug;
const repositories = this._filteredRepositories(this._repositories!);
const repository = repositories.find((repo) => repo.slug === slug);
if (!repository) {
return;
}
const newRepositories = repositories
.map((repo) => repo.source)
.filter((repo) => repo !== repository.source);
try {
await setSupervisorOption(this.hass, {
addons_repositories: newRepositories,
});
await removeStoreRepository(this.hass, slug);
await this._loadData();
} catch (err: any) {
this._error = extractApiErrorMessage(err);
+7 -7
View File
@@ -18,9 +18,11 @@ export const suggestAddonRestart = async (
addon: HassioAddonDetails
): Promise<void> => {
const confirmed = await showConfirmationDialog(element, {
title: supervisor.localize("common.restart_name", "name", addon.name),
title: supervisor.localize("dialog.restart_addon.title", {
name: addon.name,
}),
text: supervisor.localize("dialog.restart_addon.text"),
confirmText: supervisor.localize("dialog.restart_addon.confirm_text"),
confirmText: supervisor.localize("dialog.restart_addon.restart"),
dismissText: supervisor.localize("common.cancel"),
});
if (confirmed) {
@@ -28,11 +30,9 @@ export const suggestAddonRestart = async (
await restartHassioAddon(hass, addon.slug);
} catch (err: any) {
showAlertDialog(element, {
title: supervisor.localize(
"common.failed_to_restart_name",
"name",
addon.name
),
title: supervisor.localize("common.failed_to_restart_name", {
name: addon.name,
}),
text: extractApiErrorMessage(err),
});
}
+8 -3
View File
@@ -22,6 +22,7 @@ import {
Supervisor,
SupervisorObject,
supervisorCollection,
SupervisorKeys,
} from "../../src/data/supervisor/supervisor";
import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
import { urlSyncMixin } from "../../src/state/url-sync-mixin";
@@ -124,9 +125,13 @@ export class SupervisorBaseElement extends urlSyncMixin(
this.supervisor = {
...this.supervisor,
localize: await computeLocalize(this.constructor.prototype, language, {
[language]: data,
}),
localize: await computeLocalize<SupervisorKeys>(
this.constructor.prototype,
language,
{
[language]: data,
}
),
};
}
+18 -28
View File
@@ -23,10 +23,11 @@ import {
showAlertDialog,
showConfirmationDialog,
} from "../../../src/dialogs/generic/show-dialog-box";
import { showJoinBetaDialog } from "../../../src/panels/config/core/updates/show-dialog-join-beta";
import {
UNHEALTHY_REASON_URL,
UNSUPPORTED_REASON_URL,
} from "../../../src/panels/config/system-health/ha-config-system-health";
} from "../../../src/panels/config/repairs/dialog-system-information";
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant } from "../../../src/types";
import { bytesToString } from "../../../src/util/bytes-to-string";
@@ -230,36 +231,27 @@ class HassioSupervisorInfo extends LitElement {
button.progress = true;
if (this.supervisor.supervisor.channel === "stable") {
const confirmed = await showConfirmationDialog(this, {
title: this.supervisor.localize("system.supervisor.warning"),
text: html`${this.supervisor.localize("system.supervisor.beta_warning")}
<br />
<b> ${this.supervisor.localize("system.supervisor.beta_backup")} </b>
<br /><br />
${this.supervisor.localize("system.supervisor.beta_release_items")}
<ul>
<li>Home Assistant Core</li>
<li>Home Assistant Supervisor</li>
<li>Home Assistant Operating System</li>
</ul>
<br />
${this.supervisor.localize("system.supervisor.beta_join_confirm")}`,
confirmText: this.supervisor.localize(
"system.supervisor.join_beta_action"
),
dismissText: this.supervisor.localize("common.cancel"),
showJoinBetaDialog(this, {
join: async () => {
await this._setChannel("beta");
button.progress = false;
},
cancel: () => {
button.progress = false;
},
});
if (!confirmed) {
button.progress = false;
return;
}
} else {
await this._setChannel("stable");
button.progress = false;
}
}
private async _setChannel(
channel: SupervisorOptions["channel"]
): Promise<void> {
try {
const data: Partial<SupervisorOptions> = {
channel:
this.supervisor.supervisor.channel === "stable" ? "beta" : "stable",
channel,
};
await setSupervisorOption(this.hass, data);
await this._reloadSupervisor();
@@ -270,8 +262,6 @@ class HassioSupervisorInfo extends LitElement {
),
text: extractApiErrorMessage(err),
});
} finally {
button.progress = false;
}
}
+9 -2
View File
@@ -1,4 +1,11 @@
module.exports = {
"*.{js,ts}": 'eslint --ignore-pattern "**/build-scripts/**/*.js" --fix',
"!(/translations)*.{js,ts,json,css,md,html}": "prettier --write",
"*.{js,ts}": [
"prettier --write",
'eslint --ignore-pattern "**/build-scripts/**/*.js" --fix',
],
"!(/translations)*.{json,css,md,html}": "prettier --write",
"translations/*/*.json": (files) =>
'printf "%s\n" "These files should not be modified. Instead, make the necessary modifications in src/translations/en.json. Please see translations/README.md for details." ' +
files.join(" ") +
" >&2 && exit 1",
};
+13 -14
View File
@@ -16,6 +16,9 @@
"lint:lit": "lit-analyzer \"**/src/**/*.ts\" --format markdown --outFile result.md",
"lint": "yarn run lint:eslint && yarn run lint:prettier && yarn run lint:types",
"format": "yarn run format:eslint && yarn run format:prettier",
"postinstall": "husky install",
"prepack": "pinst --disable",
"postpack": "pinst --enable",
"test": "instant-mocha --webpack-config ./test/webpack.config.js --require ./test/setup.js \"test/**/*.ts\""
},
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
@@ -46,6 +49,7 @@
"@fullcalendar/daygrid": "5.9.0",
"@fullcalendar/interaction": "5.9.0",
"@fullcalendar/list": "5.9.0",
"@fullcalendar/timegrid": "5.9.0",
"@lit-labs/motion": "^1.0.2",
"@lit-labs/virtualizer": "patch:@lit-labs/virtualizer@0.7.0-pre.2#./.yarn/patches/@lit-labs/virtualizer/event-target-shim.patch",
"@material/chips": "14.0.0-canary.261f2db59.0",
@@ -72,8 +76,8 @@
"@material/mwc-textfield": "0.25.3",
"@material/mwc-top-app-bar-fixed": "^0.25.3",
"@material/top-app-bar": "14.0.0-canary.261f2db59.0",
"@mdi/js": "6.7.96",
"@mdi/svg": "6.7.96",
"@mdi/js": "7.0.96",
"@mdi/svg": "7.0.96",
"@polymer/app-layout": "^3.1.0",
"@polymer/iron-flex-layout": "^3.0.1",
"@polymer/iron-icon": "^3.0.1",
@@ -89,8 +93,8 @@
"@polymer/paper-tooltip": "^3.0.1",
"@polymer/polymer": "3.4.1",
"@thomasloven/round-slider": "0.5.4",
"@vaadin/combo-box": "^23.0.10",
"@vaadin/vaadin-themable-mixin": "^23.0.10",
"@vaadin/combo-box": "^23.2.0",
"@vaadin/vaadin-themable-mixin": "^23.2.0",
"@vibrant/color": "^3.2.1-alpha.1",
"@vibrant/core": "^3.2.1-alpha.1",
"@vibrant/quantizer-mmcq": "^3.2.1-alpha.1",
@@ -107,15 +111,14 @@
"deep-freeze": "^0.0.1",
"fuse.js": "^6.0.0",
"google-timezones-json": "^1.0.2",
"hls.js": "^1.1.5",
"home-assistant-js-websocket": "^7.1.0",
"hls.js": "^1.2.3",
"home-assistant-js-websocket": "^8.0.0",
"idb-keyval": "^5.1.3",
"intl-messageformat": "^9.9.1",
"js-yaml": "^4.1.0",
"leaflet": "^1.7.1",
"leaflet-draw": "^1.0.4",
"lit": "^2.1.2",
"lit-vaadin-helpers": "^0.3.0",
"marked": "^4.0.12",
"memoize-one": "^5.2.1",
"node-vibrant": "3.2.1-alpha.1",
@@ -202,9 +205,9 @@
"gulp-rename": "^2.0.0",
"gulp-zopfli-green": "^3.0.1",
"html-minifier": "^4.0.0",
"husky": "^1.3.1",
"husky": "^8.0.1",
"instant-mocha": "^1.3.1",
"lint-staged": "^11.1.2",
"lint-staged": "^13.0.3",
"lit-analyzer": "^1.2.1",
"lodash.template": "^4.5.0",
"magic-string": "^0.25.7",
@@ -213,6 +216,7 @@
"mocha": "^8.4.0",
"object-hash": "^2.0.3",
"open": "^7.0.4",
"pinst": "^3.0.0",
"prettier": "^2.4.1",
"require-dir": "^1.2.0",
"rollup": "^2.8.2",
@@ -245,11 +249,6 @@
"@lit/reactive-element": "1.2.1"
},
"main": "src/home-assistant.js",
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"prettier": {
"trailingComma": "es5",
"arrowParens": "always"
+1 -6
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
version = "20220526.0"
version = "20220907.0"
license = {text = "Apache-2.0"}
description = "The Home Assistant frontend"
readme = "README.md"
@@ -23,8 +23,3 @@ include-package-data = true
[tool.setuptools.packages.find]
include = ["hass_frontend*"]
[tool.mypy]
python_version = 3.4
show_error_codes = true
strict = true
+8
View File
@@ -46,6 +46,14 @@ frontend:
# development_repo: ${WD}" >> "${WD}/config/configuration.yaml"
fi
if [ ! -z "${CODESPACES}" ]; then
echo "
http:
use_x_forwarded_for: true
trusted_proxies:
- 127.0.0.1
" >> "${WD}/config/configuration.yaml"
fi
fi
hass -c "${WD}/config"
+10 -1
View File
@@ -24,10 +24,15 @@ function auto(version) {
return patch(version);
}
function nightly() {
return `${today()}.dev`;
}
const methods = {
patch,
today,
auto,
nightly,
};
async function main(args) {
@@ -57,7 +62,11 @@ async function main(args) {
console.log("Current version:", version);
console.log("New version:", newVersion);
fs.writeFileSync("pyproject.toml", setup.replace(version, newVersion), "utf-8");
fs.writeFileSync(
"pyproject.toml",
setup.replace(version, newVersion),
"utf-8"
);
if (!commit) {
return;
+2
View File
@@ -0,0 +1,2 @@
# Setuptools v62.3 doesn't support editable installs with just 'pyproject.toml' (PEP 660).
# Keep this file until it does!
+2 -1
View File
@@ -314,7 +314,8 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
}
private _computeStepDescription(step: DataEntryFlowStepForm) {
const resourceKey = `ui.panel.page-authorize.form.providers.${step.handler[0]}.step.${step.step_id}.description`;
const resourceKey =
`ui.panel.page-authorize.form.providers.${step.handler[0]}.step.${step.step_id}.description` as const;
const args: string[] = [];
const placeholders = step.description_placeholders || {};
Object.keys(placeholders).forEach((key) => {
+14 -47
View File
@@ -6,6 +6,7 @@ import {
mdiAlert,
mdiAngleAcute,
mdiAppleSafari,
mdiArrowLeftRight,
mdiBell,
mdiBookmark,
mdiBrightness5,
@@ -25,7 +26,6 @@ import {
mdiFlower,
mdiFormatListBulleted,
mdiFormTextbox,
mdiGasCylinder,
mdiGauge,
mdiGestureTapButton,
mdiGoogleAssistant,
@@ -37,6 +37,8 @@ import {
mdiLightningBolt,
mdiMailbox,
mdiMapMarkerRadius,
mdiMeterGas,
mdiMicrophoneMessage,
mdiMolecule,
mdiMoleculeCo,
mdiMoleculeCo2,
@@ -47,13 +49,14 @@ import {
mdiRobotVacuum,
mdiScriptText,
mdiSineWave,
mdiTextToSpeech,
mdiSpeedometer,
mdiThermometer,
mdiThermostat,
mdiTimerOutline,
mdiVideo,
mdiWaterPercent,
mdiWeatherCloudy,
mdiWeight,
mdiWhiteBalanceSunny,
mdiWifi,
} from "@mdi/js";
@@ -74,8 +77,9 @@ export const FIXED_DOMAIN_ICONS = {
camera: mdiVideo,
climate: mdiThermostat,
configurator: mdiCog,
conversation: mdiTextToSpeech,
conversation: mdiMicrophoneMessage,
counter: mdiCounter,
demo: mdiHomeAssistant,
fan: mdiFan,
google_assistant: mdiGoogleAssistant,
group: mdiGoogleCirclesCommunities,
@@ -97,6 +101,7 @@ export const FIXED_DOMAIN_ICONS = {
proximity: mdiAppleSafari,
remote: mdiRemote,
scene: mdiPalette,
schedule: mdiCalendarClock,
script: mdiScriptText,
select: mdiFormatListBulleted,
sensor: mdiEye,
@@ -119,11 +124,13 @@ export const FIXED_DEVICE_CLASS_ICONS = {
carbon_monoxide: mdiMoleculeCo,
current: mdiCurrentAc,
date: mdiCalendar,
distance: mdiArrowLeftRight,
energy: mdiLightningBolt,
frequency: mdiSineWave,
gas: mdiGasCylinder,
gas: mdiMeterGas,
humidity: mdiWaterPercent,
illuminance: mdiBrightness5,
moisture: mdiWaterPercent,
monetary: mdiCash,
nitrogen_dioxide: mdiMolecule,
nitrogen_monoxide: mdiMolecule,
@@ -137,11 +144,14 @@ export const FIXED_DEVICE_CLASS_ICONS = {
pressure: mdiGauge,
reactive_power: mdiFlash,
signal_strength: mdiWifi,
speed: mdiSpeedometer,
sulphur_dioxide: mdiMolecule,
temperature: mdiThermometer,
timestamp: mdiClock,
volatile_organic_compounds: mdiMolecule,
voltage: mdiSineWave,
// volume: TBD, => no well matching icon found
weight: mdiWeight,
};
/** Domains that have a state card. */
@@ -165,46 +175,6 @@ export const DOMAINS_WITH_CARD = [
"water_heater",
];
/** Domains with separate more info dialog. */
export const DOMAINS_WITH_MORE_INFO = [
"alarm_control_panel",
"automation",
"camera",
"climate",
"configurator",
"counter",
"cover",
"fan",
"group",
"humidifier",
"input_datetime",
"light",
"lock",
"media_player",
"person",
"remote",
"script",
"scene",
"sun",
"timer",
"update",
"vacuum",
"water_heater",
"weather",
];
/** Domains that do not show the default more info dialog content (e.g. the attribute section)
* and do not have a separate more info (so not in DOMAINS_WITH_MORE_INFO). */
export const DOMAINS_HIDE_DEFAULT_MORE_INFO = [
"input_number",
"input_select",
"input_text",
"number",
"scene",
"update",
"select",
];
/** Domains that render an input element instead of a text value when displayed in a row.
* Those rows should then not show a cursor pointer when hovered (which would normally
* be the default) unless the element itself enforces it (e.g. a button). Also those elements
@@ -236,9 +206,6 @@ export const DOMAINS_INPUT_ROW = [
"vacuum",
];
/** Domains that should have the history hidden in the more info dialog. */
export const DOMAINS_MORE_INFO_NO_HISTORY = ["camera", "configurator"];
/** States that we consider "off". */
export const STATES_OFF = ["closed", "locked", "off"];
+23 -1
View File
@@ -1,7 +1,7 @@
import memoizeOne from "memoize-one";
import { FrontendLocaleData } from "../../data/translation";
import { useAmPm } from "./use_am_pm";
import { polyfillsLoaded } from "../translations/localize";
import { useAmPm } from "./use_am_pm";
if (__BUILD__ === "latest" && polyfillsLoaded) {
await polyfillsLoaded;
@@ -28,6 +28,28 @@ const formatDateTimeMem = memoizeOne(
)
);
// Aug 9, 8:23 AM
export const formatShortDateTime = (
dateObj: Date,
locale: FrontendLocaleData
) => formatShortDateTimeMem(locale).format(dateObj);
const formatShortDateTimeMem = memoizeOne(
(locale: FrontendLocaleData) =>
new Intl.DateTimeFormat(
locale.language === "en" && !useAmPm(locale)
? "en-u-hc-h23"
: locale.language,
{
month: "short",
day: "numeric",
hour: useAmPm(locale) ? "numeric" : "2-digit",
minute: "2-digit",
hour12: useAmPm(locale),
}
)
);
// August 9, 2021, 8:23:15 AM
export const formatDateTimeWithSeconds = (
dateObj: Date,
+28
View File
@@ -0,0 +1,28 @@
import { HaDurationData } from "../../components/ha-duration-input";
const leftPad = (num: number) => (num < 10 ? `0${num}` : num);
export const formatDuration = (duration: HaDurationData) => {
const d = duration.days || 0;
const h = duration.hours || 0;
const m = duration.minutes || 0;
const s = duration.seconds || 0;
const ms = duration.milliseconds || 0;
if (d > 0) {
return `${d} days ${h}:${leftPad(m)}:${leftPad(s)}`;
}
if (h > 0) {
return `${h}:${leftPad(m)}:${leftPad(s)}`;
}
if (m > 0) {
return `${m}:${leftPad(s)}`;
}
if (s > 0) {
return `${s} seconds`;
}
if (ms > 0) {
return `${ms} milliseconds`;
}
return null;
};
+15 -1
View File
@@ -1,7 +1,7 @@
import memoizeOne from "memoize-one";
import { FrontendLocaleData } from "../../data/translation";
import { useAmPm } from "./use_am_pm";
import { polyfillsLoaded } from "../translations/localize";
import { useAmPm } from "./use_am_pm";
if (__BUILD__ === "latest" && polyfillsLoaded) {
await polyfillsLoaded;
@@ -64,3 +64,17 @@ const formatTimeWeekdayMem = memoizeOne(
}
)
);
// 21:15
export const formatTime24h = (dateObj: Date) =>
formatTime24hMem().format(dateObj);
const formatTime24hMem = memoizeOne(
() =>
// en-GB to fix Chrome 24:59 to 0:59 https://stackoverflow.com/a/60898146
new Intl.DateTimeFormat("en-GB", {
hour: "numeric",
minute: "2-digit",
hour12: false,
})
);
+5 -1
View File
@@ -76,7 +76,11 @@ class Storage {
public setValue(storageKey: string, value: any): any {
this._storage[storageKey] = value;
try {
window.localStorage.setItem(storageKey, JSON.stringify(value));
if (value === undefined) {
window.localStorage.removeItem(storageKey);
} else {
window.localStorage.setItem(storageKey, JSON.stringify(value));
}
} catch (err: any) {
// Safari in private mode doesn't allow localstorage
}
+8 -13
View File
@@ -5,8 +5,7 @@ export type LeafletModuleType = typeof import("leaflet");
export type LeafletDrawModuleType = typeof import("leaflet-draw");
export const setupLeafletMap = async (
mapElement: HTMLElement,
darkMode?: boolean
mapElement: HTMLElement
): Promise<[Map, LeafletModuleType, TileLayer]> => {
if (!mapElement.parentNode) {
throw new Error("Cannot setup Leaflet map on disconnected element");
@@ -23,7 +22,7 @@ export const setupLeafletMap = async (
mapElement.parentNode.appendChild(style);
map.setView([52.3731339, 4.8903147], 13);
const tileLayer = createTileLayer(Leaflet, Boolean(darkMode)).addTo(map);
const tileLayer = createTileLayer(Leaflet).addTo(map);
return [map, Leaflet, tileLayer];
};
@@ -31,23 +30,19 @@ export const setupLeafletMap = async (
export const replaceTileLayer = (
leaflet: LeafletModuleType,
map: Map,
tileLayer: TileLayer,
darkMode: boolean
tileLayer: TileLayer
): TileLayer => {
map.removeLayer(tileLayer);
tileLayer = createTileLayer(leaflet, darkMode);
tileLayer = createTileLayer(leaflet);
tileLayer.addTo(map);
return tileLayer;
};
const createTileLayer = (
leaflet: LeafletModuleType,
darkMode: boolean
): TileLayer =>
const createTileLayer = (leaflet: LeafletModuleType): TileLayer =>
leaflet.tileLayer(
`https://{s}.basemaps.cartocdn.com/${
darkMode ? "dark_all" : "light_all"
}/{z}/{x}/{y}${leaflet.Browser.retina ? "@2x.png" : ".png"}`,
`https://basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}${
leaflet.Browser.retina ? "@2x.png" : ".png"
}`,
{
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>, &copy; <a href="https://carto.com/attributions">CARTO</a>',
+10 -6
View File
@@ -2,17 +2,18 @@ import { HassEntity } from "home-assistant-js-websocket";
import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
import { FrontendLocaleData } from "../../data/translation";
import {
UPDATE_SUPPORT_PROGRESS,
updateIsInstallingFromAttributes,
UPDATE_SUPPORT_PROGRESS,
} from "../../data/update";
import { formatDuration, UNIT_TO_SECOND_CONVERT } from "../datetime/duration";
import { formatDate } from "../datetime/format_date";
import { formatDateTime } from "../datetime/format_date_time";
import { formatTime } from "../datetime/format_time";
import { formatNumber, isNumericFromAttributes } from "../number/format_number";
import { blankBeforePercent } from "../translations/blank_before_percent";
import { LocalizeFunc } from "../translations/localize";
import { supportsFeatureFromAttributes } from "./supports-feature";
import { formatDuration, UNIT_TO_SECOND_CONVERT } from "../datetime/duration";
import { computeDomain } from "./compute_domain";
import { supportsFeatureFromAttributes } from "./supports-feature";
export const computeStateDisplay = (
localize: LocalizeFunc,
@@ -64,9 +65,12 @@ export const computeStateDisplayFromEntityAttributes = (
// fallback to default
}
}
return `${formatNumber(state, locale)}${
attributes.unit_of_measurement ? " " + attributes.unit_of_measurement : ""
}`;
const unit = !attributes.unit_of_measurement
? ""
: attributes.unit_of_measurement === "%"
? blankBeforePercent(locale) + "%"
: ` ${attributes.unit_of_measurement}`;
return `${formatNumber(state, locale)}${unit}`;
}
const domain = computeDomain(entityId);
+51 -1
View File
@@ -8,6 +8,8 @@ import {
mdiCalendar,
mdiCast,
mdiCastConnected,
mdiCastOff,
mdiChartSankey,
mdiCheckCircleOutline,
mdiClock,
mdiCloseCircleOutline,
@@ -24,6 +26,15 @@ import {
mdiPowerPlug,
mdiPowerPlugOff,
mdiRestart,
mdiSpeaker,
mdiSpeakerOff,
mdiSpeakerPause,
mdiSpeakerPlay,
mdiSwapHorizontal,
mdiTelevision,
mdiTelevisionOff,
mdiTelevisionPause,
mdiTelevisionPlay,
mdiToggleSwitchVariant,
mdiToggleSwitchVariantOff,
mdiWeatherNight,
@@ -125,7 +136,40 @@ export const domainIconWithoutDefault = (
}
case "media_player":
return compareState === "playing" ? mdiCastConnected : mdiCast;
switch (stateObj?.attributes.device_class) {
case "speaker":
switch (compareState) {
case "playing":
return mdiSpeakerPlay;
case "paused":
return mdiSpeakerPause;
case "off":
return mdiSpeakerOff;
default:
return mdiSpeaker;
}
case "tv":
switch (compareState) {
case "playing":
return mdiTelevisionPlay;
case "paused":
return mdiTelevisionPause;
case "off":
return mdiTelevisionOff;
default:
return mdiTelevision;
}
default:
switch (compareState) {
case "playing":
case "paused":
return mdiCastConnected;
case "off":
return mdiCastOff;
default:
return mdiCast;
}
}
case "switch":
switch (stateObj?.attributes.device_class) {
@@ -153,6 +197,12 @@ export const domainIconWithoutDefault = (
? FIXED_DOMAIN_ICONS[domain]
: mdiWeatherNight;
case "switch_as_x":
return mdiSwapHorizontal;
case "threshold":
return mdiChartSankey;
case "update":
return compareState === "on"
? updateIsInstalling(stateObj as UpdateEntity)
+5 -1
View File
@@ -1,10 +1,14 @@
import { HassEntity } from "home-assistant-js-websocket";
import { supportsFeature } from "./supports-feature";
export type FeatureClassNames<T extends number = number> = Partial<
Record<T, string>
>;
// Expects classNames to be an object mapping feature-bit -> className
export const featureClassNames = (
stateObj: HassEntity,
classNames: { [feature: number]: string }
classNames: FeatureClassNames
) => {
if (!stateObj || !stateObj.attributes.supported_features) {
return "";
+281
View File
@@ -0,0 +1,281 @@
import { HassEntity } from "home-assistant-js-websocket";
import { computeStateDomain } from "./compute_state_domain";
import { UNAVAILABLE_STATES } from "../../data/entity";
const FIXED_DOMAIN_STATES = {
alarm_control_panel: [
"armed_away",
"armed_custom_bypass",
"armed_home",
"armed_night",
"armed_vacation",
"arming",
"disarmed",
"disarming",
"pending",
"triggered",
],
automation: ["on", "off"],
binary_sensor: ["on", "off"],
button: [],
calendar: ["on", "off"],
camera: ["idle", "recording", "streaming"],
cover: ["closed", "closing", "open", "opening"],
device_tracker: ["home", "not_home"],
fan: ["on", "off"],
humidifier: ["on", "off"],
input_boolean: ["on", "off"],
input_button: [],
light: ["on", "off"],
lock: ["jammed", "locked", "locking", "unlocked", "unlocking"],
media_player: ["idle", "off", "paused", "playing", "standby"],
person: ["home", "not_home"],
remote: ["on", "off"],
scene: [],
schedule: ["on", "off"],
script: ["on", "off"],
siren: ["on", "off"],
sun: ["above_horizon", "below_horizon"],
switch: ["on", "off"],
timer: ["active", "idle", "paused"],
update: ["on", "off"],
vacuum: ["cleaning", "docked", "error", "idle", "paused", "returning"],
weather: [
"clear-night",
"cloudy",
"exceptional",
"fog",
"hail",
"lightning-rainy",
"lightning",
"partlycloudy",
"pouring",
"rainy",
"snowy-rainy",
"snowy",
"sunny",
"windy-variant",
"windy",
],
};
const FIXED_DOMAIN_ATTRIBUTE_STATES = {
alarm_control_panel: {
code_format: ["number", "text"],
},
binary_sensor: {
device_class: [
"battery",
"battery_charging",
"co",
"cold",
"connectivity",
"door",
"garage_door",
"gas",
"heat",
"light",
"lock",
"moisture",
"motion",
"moving",
"occupancy",
"opening",
"plug",
"power",
"presence",
"problem",
"running",
"safety",
"smoke",
"sound",
"tamper",
"update",
"vibration",
"window",
],
},
button: {
device_class: ["restart", "update"],
},
camera: {
frontend_stream_type: ["hls", "web_rtc"],
},
climate: {
hvac_action: ["off", "idle", "heating", "cooling", "drying", "fan"],
},
cover: {
device_class: [
"awning",
"blind",
"curtain",
"damper",
"door",
"garage",
"gate",
"shade",
"shutter",
"window",
],
},
humidifier: {
device_class: ["humidifier", "dehumidifier"],
},
media_player: {
device_class: ["tv", "speaker", "receiver"],
media_content_type: [
"app",
"channel",
"episode",
"game",
"image",
"movie",
"music",
"playlist",
"tvshow",
"url",
"video",
],
},
number: {
device_class: ["temperature"],
},
sensor: {
device_class: [
"apparent_power",
"aqi",
"battery",
"carbon_dioxide",
"carbon_monoxide",
"current",
"date",
"duration",
"energy",
"frequency",
"gas",
"humidity",
"illuminance",
"monetary",
"nitrogen_dioxide",
"nitrogen_monoxide",
"nitrous_oxide",
"ozone",
"pm1",
"pm10",
"pm25",
"power_factor",
"power",
"pressure",
"reactive_power",
"signal_strength",
"sulphur_dioxide",
"temperature",
"timestamp",
"volatile_organic_compounds",
"voltage",
],
state_class: ["measurement", "total", "total_increasing"],
},
switch: {
device_class: ["outlet", "switch"],
},
update: {
device_class: ["firmware"],
},
water_heater: {
away_mode: ["on", "off"],
},
};
export const getStates = (
state: HassEntity,
attribute: string | undefined = undefined
): string[] => {
const domain = computeStateDomain(state);
const result: string[] = [];
if (!attribute && domain in FIXED_DOMAIN_STATES) {
result.push(...FIXED_DOMAIN_STATES[domain]);
} else if (
attribute &&
domain in FIXED_DOMAIN_ATTRIBUTE_STATES &&
attribute in FIXED_DOMAIN_ATTRIBUTE_STATES[domain]
) {
result.push(...FIXED_DOMAIN_ATTRIBUTE_STATES[domain][attribute]);
}
// Dynamic values based on the entities
switch (domain) {
case "climate":
if (!attribute) {
result.push(...state.attributes.hvac_modes);
} else if (attribute === "fan_mode") {
result.push(...state.attributes.fan_modes);
} else if (attribute === "preset_mode") {
result.push(...state.attributes.preset_modes);
} else if (attribute === "swing_mode") {
result.push(...state.attributes.swing_modes);
}
break;
case "device_tracker":
case "person":
if (!attribute) {
result.push("home", "not_home");
}
break;
case "fan":
if (attribute === "preset_mode") {
result.push(...state.attributes.preset_modes);
}
break;
case "humidifier":
if (attribute === "mode") {
result.push(...state.attributes.available_modes);
}
break;
case "input_select":
case "select":
if (!attribute) {
result.push(...state.attributes.options);
}
break;
case "light":
if (attribute === "effect" && state.attributes.effect_list) {
result.push(...state.attributes.effect_list);
} else if (
attribute === "color_mode" &&
state.attributes.supported_color_modes
) {
result.push(...state.attributes.supported_color_modes);
}
break;
case "media_player":
if (attribute === "sound_mode") {
result.push(...state.attributes.sound_mode_list);
} else if (attribute === "source") {
result.push(...state.attributes.source_list);
}
break;
case "remote":
if (attribute === "current_activity") {
result.push(...state.attributes.activity_list);
}
break;
case "vacuum":
if (attribute === "fan_speed") {
result.push(...state.attributes.fan_speed_list);
}
break;
case "water_heater":
if (!attribute || attribute === "operation_mode") {
result.push(...state.attributes.operation_list);
}
break;
}
if (!attribute) {
// All entities can have unavailable states
result.push(...UNAVAILABLE_STATES);
}
return [...new Set(result)];
};
@@ -0,0 +1,88 @@
import { html } from "lit";
import { getConfigEntries } from "../../data/config_entries";
import { showConfirmationDialog } from "../../dialogs/generic/show-dialog-box";
import { showZWaveJSAddNodeDialog } from "../../panels/config/integrations/integration-panels/zwave_js/show-dialog-zwave_js-add-node";
import type { HomeAssistant } from "../../types";
import { documentationUrl } from "../../util/documentation-url";
import { isComponentLoaded } from "../config/is_component_loaded";
import { fireEvent } from "../dom/fire_event";
import { navigate } from "../navigate";
export const protocolIntegrationPicked = async (
element: HTMLElement,
hass: HomeAssistant,
slug: string
) => {
if (slug === "zwave_js") {
const entries = await getConfigEntries(hass, {
domain: "zwave_js",
});
if (!entries.length) {
// If the component isn't loaded, ask them to load the integration first
showConfirmationDialog(element, {
text: hass.localize(
"ui.panel.config.integrations.config_flow.missing_zwave_zigbee",
{
integration: "Z-Wave",
supported_hardware_link: html`<a
href=${documentationUrl(hass, "/docs/z-wave/controllers")}
target="_blank"
rel="noreferrer"
>${hass.localize(
"ui.panel.config.integrations.config_flow.supported_hardware"
)}</a
>`,
}
),
confirmText: hass.localize(
"ui.panel.config.integrations.config_flow.proceed"
),
confirm: () => {
fireEvent(element, "handler-picked", {
handler: "zwave_js",
});
},
});
return;
}
showZWaveJSAddNodeDialog(element, {
entry_id: entries[0].entry_id,
});
} else if (slug === "zha") {
// If the component isn't loaded, ask them to load the integration first
if (!isComponentLoaded(hass, "zha")) {
showConfirmationDialog(element, {
text: hass.localize(
"ui.panel.config.integrations.config_flow.missing_zwave_zigbee",
{
integration: "Zigbee",
supported_hardware_link: html`<a
href=${documentationUrl(
hass,
"/integrations/zha/#known-working-zigbee-radio-modules"
)}
target="_blank"
rel="noreferrer"
>${hass.localize(
"ui.panel.config.integrations.config_flow.supported_hardware"
)}</a
>`,
}
),
confirmText: hass.localize(
"ui.panel.config.integrations.config_flow.proceed"
),
confirm: () => {
fireEvent(element, "handler-picked", {
handler: "zha",
});
},
});
return;
}
navigate("/config/zha/add");
}
};
+1 -1
View File
@@ -5,6 +5,6 @@ export const clamp = (value: number, min: number, max: number) =>
export const conditionalClamp = (value: number, min?: number, max?: number) => {
let result: number;
result = min ? Math.max(value, min) : value;
result = max ? Math.min(value, max) : value;
result = max ? Math.min(result, max) : result;
return result;
};
+4
View File
@@ -0,0 +1,4 @@
export const titleCase = (s) =>
s.replace(/^_*(.)|_+(.)/g, (_s, c, d) =>
c ? c.toUpperCase() : " " + d.toUpperCase()
);
+3 -1
View File
@@ -70,7 +70,9 @@ export const iconColorCSS = css`
}
}
ha-state-icon[data-domain="plant"][data-state="problem"],
ha-state-icon[data-domain="plant"][data-state="problem"] {
color: var(--state-icon-error-color);
}
/* Color the icon if unavailable */
ha-state-icon[data-state="unavailable"] {
@@ -0,0 +1,18 @@
import { FrontendLocaleData } from "../../data/translation";
// Logic based on https://en.wikipedia.org/wiki/Percent_sign#Form_and_spacing
export const blankBeforePercent = (
localeOptions: FrontendLocaleData
): string => {
switch (localeOptions.language) {
case "cz":
case "de":
case "fi":
case "fr":
case "sk":
case "sv":
return " ";
default:
return "";
}
};
+60 -4
View File
@@ -3,10 +3,66 @@ import { shouldPolyfill as shouldPolyfillPluralRules } from "@formatjs/intl-plur
import { shouldPolyfill as shouldPolyfillRelativeTime } from "@formatjs/intl-relativetimeformat/lib/should-polyfill";
import { shouldPolyfill as shouldPolyfillDateTime } from "@formatjs/intl-datetimeformat/lib/should-polyfill";
import IntlMessageFormat from "intl-messageformat";
import { Resources } from "../../types";
import { Resources, TranslationDict } from "../../types";
import { getLocalLanguage } from "../../util/common-translation";
export type LocalizeFunc = (key: string, ...args: any[]) => string;
// Exclude some patterns from key type checking for now
// These are intended to be removed as errors are fixed
// Fixing component category will require tighter definition of types from backend and/or web socket
export type LocalizeKeys =
| FlattenObjectKeys<Omit<TranslationDict, "supervisor">>
| `panel.${string}`
| `state.${string}`
| `state_attributes.${string}`
| `state_badge.${string}`
| `ui.card.alarm_control_panel.${string}`
| `ui.card.weather.attributes.${string}`
| `ui.card.weather.cardinal_direction.${string}`
| `ui.components.logbook.${string}`
| `ui.components.selectors.file.${string}`
| `ui.dialogs.entity_registry.editor.${string}`
| `ui.dialogs.more_info_control.vacuum.${string}`
| `ui.dialogs.options_flow.loading.${string}`
| `ui.dialogs.quick-bar.commands.${string}`
| `ui.dialogs.repair_flow.loading.${string}`
| `ui.dialogs.unhealthy.reason.${string}`
| `ui.dialogs.unsupported.reason.${string}`
| `ui.panel.config.${string}.${"caption" | "description"}`
| `ui.panel.config.automation.${string}`
| `ui.panel.config.dashboard.${string}`
| `ui.panel.config.devices.${string}`
| `ui.panel.config.energy.${string}`
| `ui.panel.config.helpers.${string}`
| `ui.panel.config.info.${string}`
| `ui.panel.config.integrations.${string}`
| `ui.panel.config.logs.${string}`
| `ui.panel.config.lovelace.${string}`
| `ui.panel.config.network.${string}`
| `ui.panel.config.scene.${string}`
| `ui.panel.config.url.${string}`
| `ui.panel.config.zha.${string}`
| `ui.panel.config.zwave_js.${string}`
| `ui.panel.developer-tools.tabs.${string}`
| `ui.panel.lovelace.card.${string}`
| `ui.panel.lovelace.editor.${string}`
| `ui.panel.page-authorize.form.${string}`
| `component.${string}`;
// Tweaked from https://www.raygesualdo.com/posts/flattening-object-keys-with-typescript-types
export type FlattenObjectKeys<
T extends Record<string, any>,
Key extends keyof T = keyof T
> = Key extends string
? T[Key] extends Record<string, unknown>
? `${Key}.${FlattenObjectKeys<T[Key]>}`
: `${Key}`
: never;
export type LocalizeFunc<Keys extends string = LocalizeKeys> = (
key: Keys,
...args: any[]
) => string;
interface FormatType {
[format: string]: any;
}
@@ -65,12 +121,12 @@ export const polyfillsLoaded =
* }
*/
export const computeLocalize = async (
export const computeLocalize = async <Keys extends string = LocalizeKeys>(
cache: any,
language: string,
resources: Resources,
formats?: FormatsType
): Promise<LocalizeFunc> => {
): Promise<LocalizeFunc<Keys>> => {
if (polyfillsLoaded) {
await polyfillsLoaded;
}
+19
View File
@@ -1,3 +1,4 @@
import { LitElement } from "lit";
import { HomeAssistant } from "../../types";
export function computeRTL(hass: HomeAssistant) {
@@ -15,3 +16,21 @@ export function computeRTLDirection(hass: HomeAssistant) {
export function emitRTLDirection(rtl: boolean) {
return rtl ? "rtl" : "ltr";
}
export function computeDirectionStyles(isRTL: boolean, element: LitElement) {
const direction: string = emitRTLDirection(isRTL);
setDirectionStyles(direction, element);
}
export function setDirectionStyles(direction: string, element: LitElement) {
element.style.direction = direction;
element.style.setProperty("--direction", direction);
element.style.setProperty(
"--float-start",
direction === "ltr" ? "left" : "right"
);
element.style.setProperty(
"--float-end",
direction === "ltr" ? "right" : "left"
);
}
+33
View File
@@ -11,6 +11,8 @@ import { classMap } from "lit/directives/class-map";
import { styleMap } from "lit/directives/style-map";
import { clamp } from "../../common/number/clamp";
export const MIN_TIME_BETWEEN_UPDATES = 60 * 5 * 1000;
interface Tooltip extends TooltipModel<any> {
top: string;
left: string;
@@ -37,6 +39,26 @@ export default class HaChartBase extends LitElement {
@state() private _hiddenDatasets: Set<number> = new Set();
private _releaseCanvas() {
// release the canvas memory to prevent
// safari from running out of memory.
if (this.chart) {
this.chart.destroy();
}
}
public disconnectedCallback() {
this._releaseCanvas();
super.disconnectedCallback();
}
public connectedCallback() {
super.connectedCallback();
if (this.hasUpdated) {
this._setupChart();
}
}
protected firstUpdated() {
this._setupChart();
this.data.datasets.forEach((dataset, index) => {
@@ -166,6 +188,10 @@ export default class HaChartBase extends LitElement {
ChartConstructor.defaults.color = computedStyles.getPropertyValue(
"--secondary-text-color"
);
ChartConstructor.defaults.font.family =
computedStyles.getPropertyValue("--mdc-typography-body1-font-family") ||
computedStyles.getPropertyValue("--mdc-typography-font-family") ||
"Roboto, Noto, sans-serif";
this.chart = new ChartConstructor(ctx, {
type: this.chartType,
@@ -304,6 +330,9 @@ export default class HaChartBase extends LitElement {
width: 16px;
flex-shrink: 0;
box-sizing: border-box;
margin-inline-end: 6px;
margin-inline-start: initial;
direction: var(--direction);
}
.chartTooltip .bullet {
align-self: baseline;
@@ -312,6 +341,9 @@ export default class HaChartBase extends LitElement {
:host([rtl]) .chartTooltip .bullet {
margin-right: inherit;
margin-left: 6px;
margin-inline-end: inherit;
margin-inline-start: 6px;
direction: var(--direction);
}
.chartTooltip {
padding: 8px;
@@ -348,6 +380,7 @@ export default class HaChartBase extends LitElement {
.chartTooltip .title {
text-align: center;
font-weight: 500;
direction: ltr;
}
.chartTooltip .footer {
font-weight: 500;
@@ -8,7 +8,7 @@ import {
} from "../../common/number/format_number";
import { LineChartEntity, LineChartState } from "../../data/history";
import { HomeAssistant } from "../../types";
import "./ha-chart-base";
import { MIN_TIME_BETWEEN_UPDATES } from "./ha-chart-base";
const safeParseFloat = (value) => {
const parsed = parseFloat(value);
@@ -28,11 +28,13 @@ class StateHistoryChartLine extends LitElement {
@property({ type: Boolean }) public isSingleDevice = false;
@property({ attribute: false }) public endTime?: Date;
@property({ attribute: false }) public endTime!: Date;
@state() private _chartData?: ChartData<"line">;
@state() private _chartOptions?: ChartOptions<"line">;
@state() private _chartOptions?: ChartOptions;
private _chartTime: Date = new Date();
protected render() {
return html`
@@ -57,6 +59,7 @@ class StateHistoryChartLine extends LitElement {
locale: this.hass.locale,
},
},
suggestedMax: this.endTime,
ticks: {
maxRotation: 0,
sampleSize: 5,
@@ -120,7 +123,13 @@ class StateHistoryChartLine extends LitElement {
locale: numberFormatToLocale(this.hass.locale),
};
}
if (changedProps.has("data")) {
if (
changedProps.has("data") ||
this._chartTime <
new Date(this.endTime.getTime() - MIN_TIME_BETWEEN_UPDATES)
) {
// If the line is more than 5 minutes old, re-gen it
// so the X axis grows even if there is no new data
this._generateData();
}
}
@@ -130,28 +139,12 @@ class StateHistoryChartLine extends LitElement {
const computedStyles = getComputedStyle(this);
const entityStates = this.data;
const datasets: ChartDataset<"line">[] = [];
let endTime: Date;
if (entityStates.length === 0) {
return;
}
endTime =
this.endTime ||
// Get the highest date from the last date of each device
new Date(
Math.max(
...entityStates.map((devSts) =>
new Date(
devSts.states[devSts.states.length - 1].last_changed
).getTime()
)
)
);
if (endTime > new Date()) {
endTime = new Date();
}
this._chartTime = new Date();
const endTime = this.endTime;
const names = this.names || {};
entityStates.forEach((states) => {
const domain = states.domain;
@@ -9,7 +9,7 @@ import { numberFormatToLocale } from "../../common/number/format_number";
import { computeRTL } from "../../common/util/compute_rtl";
import { TimelineEntity } from "../../data/history";
import { HomeAssistant } from "../../types";
import "./ha-chart-base";
import { MIN_TIME_BETWEEN_UPDATES } from "./ha-chart-base";
import type { TimeLineData } from "./timeline-chart/const";
/** Binary sensor device classes for which the static colors for on/off are NOT inverted.
@@ -83,6 +83,8 @@ export class StateHistoryChartTimeline extends LitElement {
@property({ attribute: false }) public data: TimelineEntity[] = [];
@property() public narrow!: boolean;
@property() public names: boolean | Record<string, string> = false;
@property() public unit?: string;
@@ -91,12 +93,18 @@ export class StateHistoryChartTimeline extends LitElement {
@property({ type: Boolean }) public isSingleDevice = false;
@property({ attribute: false }) public endTime?: Date;
@property({ type: Boolean }) public chunked = false;
@property({ attribute: false }) public startTime!: Date;
@property({ attribute: false }) public endTime!: Date;
@state() private _chartData?: ChartData<"timeline">;
@state() private _chartOptions?: ChartOptions<"timeline">;
private _chartTime: Date = new Date();
protected render() {
return html`
<ha-chart-base
@@ -110,6 +118,7 @@ export class StateHistoryChartTimeline extends LitElement {
public willUpdate(changedProps: PropertyValues) {
if (!this.hasUpdated) {
const narrow = this.narrow;
this._chartOptions = {
maintainAspectRatio: false,
parsing: false,
@@ -123,6 +132,8 @@ export class StateHistoryChartTimeline extends LitElement {
locale: this.hass.locale,
},
},
suggestedMin: this.startTime,
suggestedMax: this.endTime,
ticks: {
autoSkip: true,
maxRotation: 0,
@@ -153,11 +164,18 @@ export class StateHistoryChartTimeline extends LitElement {
drawTicks: false,
},
ticks: {
display: this.data.length !== 1,
display:
this.chunked || !this.isSingleDevice || this.data.length !== 1,
},
afterSetDimensions: (y) => {
y.maxWidth = y.chart.width * 0.18;
},
afterFit: (scaleInstance) => {
if (this.chunked) {
// ensure all the chart labels are the same width
scaleInstance.width = narrow ? 105 : 185;
}
},
position: computeRTL(this.hass) ? "right" : "left",
},
},
@@ -195,7 +213,13 @@ export class StateHistoryChartTimeline extends LitElement {
locale: numberFormatToLocale(this.hass.locale),
};
}
if (changedProps.has("data")) {
if (
changedProps.has("data") ||
this._chartTime <
new Date(this.endTime.getTime() - MIN_TIME_BETWEEN_UPDATES)
) {
// If the line is more than 5 minutes old, re-gen it
// so the X axis grows even if there is no new data
this._generateData();
}
}
@@ -208,34 +232,9 @@ export class StateHistoryChartTimeline extends LitElement {
stateHistory = [];
}
const startTime = new Date(
stateHistory.reduce(
(minTime, stateInfo) =>
Math.min(minTime, new Date(stateInfo.data[0].last_changed).getTime()),
new Date().getTime()
)
);
// end time is Math.max(startTime, last_event)
let endTime =
this.endTime ||
new Date(
stateHistory.reduce(
(maxTime, stateInfo) =>
Math.max(
maxTime,
new Date(
stateInfo.data[stateInfo.data.length - 1].last_changed
).getTime()
),
startTime.getTime()
)
);
if (endTime > new Date()) {
endTime = new Date();
}
this._chartTime = new Date();
const startTime = this.startTime;
const endTime = this.endTime;
const labels: string[] = [];
const datasets: ChartDataset<"timeline">[] = [];
const names = this.names || {};
+146 -36
View File
@@ -1,3 +1,4 @@
import "@lit-labs/virtualizer";
import {
css,
CSSResultGroup,
@@ -6,12 +7,29 @@ import {
PropertyValues,
TemplateResult,
} from "lit";
import { customElement, property } from "lit/decorators";
import { customElement, property, state, eventOptions } from "lit/decorators";
import { isComponentLoaded } from "../../common/config/is_component_loaded";
import { HistoryResult } from "../../data/history";
import {
HistoryResult,
LineChartUnit,
TimelineEntity,
} from "../../data/history";
import type { HomeAssistant } from "../../types";
import "./state-history-chart-line";
import "./state-history-chart-timeline";
import { restoreScroll } from "../../common/decorators/restore-scroll";
const CANVAS_TIMELINE_ROWS_CHUNK = 10; // Split up the canvases to avoid hitting the render limit
const chunkData = (inputArray: any[], chunks: number) =>
inputArray.reduce((results, item, idx) => {
const chunkIdx = Math.floor(idx / chunks);
if (!results[chunkIdx]) {
results[chunkIdx] = [];
}
results[chunkIdx].push(item);
return results;
}, []);
@customElement("state-history-charts")
class StateHistoryCharts extends LitElement {
@@ -19,8 +37,13 @@ class StateHistoryCharts extends LitElement {
@property({ attribute: false }) public historyData!: HistoryResult;
@property() public narrow!: boolean;
@property({ type: Boolean }) public names = false;
@property({ type: Boolean, attribute: "virtualize", reflect: true })
public virtualize = false;
@property({ attribute: false }) public endTime?: Date;
@property({ type: Boolean, attribute: "up-to-now" }) public upToNow = false;
@@ -29,59 +52,104 @@ class StateHistoryCharts extends LitElement {
@property({ type: Boolean }) public isLoadingData = false;
@state() private _computedStartTime!: Date;
@state() private _computedEndTime!: Date;
// @ts-ignore
@restoreScroll(".container") private _savedScrollPos?: number;
@eventOptions({ passive: true })
protected render(): TemplateResult {
if (!isComponentLoaded(this.hass, "history")) {
return html` <div class="info">
return html`<div class="info">
${this.hass.localize("ui.components.history_charts.history_disabled")}
</div>`;
}
if (this.isLoadingData && !this.historyData) {
return html` <div class="info">
return html`<div class="info">
${this.hass.localize("ui.components.history_charts.loading_history")}
</div>`;
}
if (this._isHistoryEmpty()) {
return html` <div class="info">
return html`<div class="info">
${this.hass.localize("ui.components.history_charts.no_history_found")}
</div>`;
}
const computedEndTime = this.upToNow
? new Date()
: this.endTime || new Date();
const now = new Date();
return html`
${this.historyData.timeline.length
? html`
<state-history-chart-timeline
.hass=${this.hass}
.data=${this.historyData.timeline}
.endTime=${computedEndTime}
.noSingle=${this.noSingle}
.names=${this.names}
></state-history-chart-timeline>
`
: html``}
${this.historyData.line.map(
(line) => html`
<state-history-chart-line
.hass=${this.hass}
.unit=${line.unit}
.data=${line.data}
.identifier=${line.identifier}
.isSingleDevice=${!this.noSingle &&
line.data &&
line.data.length === 1}
.endTime=${computedEndTime}
.names=${this.names}
></state-history-chart-line>
`
)}
`;
this._computedEndTime =
this.upToNow || !this.endTime || this.endTime > now ? now : this.endTime;
this._computedStartTime = new Date(
this.historyData.timeline.reduce(
(minTime, stateInfo) =>
Math.min(minTime, new Date(stateInfo.data[0].last_changed).getTime()),
new Date().getTime()
)
);
const combinedItems = this.historyData.timeline.length
? (this.virtualize
? chunkData(this.historyData.timeline, CANVAS_TIMELINE_ROWS_CHUNK)
: [this.historyData.timeline]
).concat(this.historyData.line)
: this.historyData.line;
return this.virtualize
? html`<div class="container ha-scrollbar" @scroll=${this._saveScrollPos}>
<lit-virtualizer
scroller
class="ha-scrollbar"
.items=${combinedItems}
.renderItem=${this._renderHistoryItem}
>
</lit-virtualizer>
</div>`
: html`${combinedItems.map((item, index) =>
this._renderHistoryItem(item, index)
)}`;
}
private _renderHistoryItem = (
item: TimelineEntity[] | LineChartUnit,
index: number
): TemplateResult => {
if (!item || index === undefined) {
return html``;
}
if (!Array.isArray(item)) {
return html`<div class="entry-container">
<state-history-chart-line
.hass=${this.hass}
.unit=${item.unit}
.data=${item.data}
.identifier=${item.identifier}
.isSingleDevice=${!this.noSingle &&
this.historyData.line?.length === 1}
.endTime=${this._computedEndTime}
.names=${this.names}
></state-history-chart-line>
</div> `;
}
return html`<div class="entry-container">
<state-history-chart-timeline
.hass=${this.hass}
.data=${item}
.startTime=${this._computedStartTime}
.endTime=${this._computedEndTime}
.isSingleDevice=${!this.noSingle &&
this.historyData.timeline?.length === 1}
.names=${this.names}
.narrow=${this.narrow}
.chunked=${this.virtualize}
></state-history-chart-timeline>
</div> `;
};
protected shouldUpdate(changedProps: PropertyValues): boolean {
return !(changedProps.size === 1 && changedProps.has("hass"));
}
@@ -96,6 +164,11 @@ class StateHistoryCharts extends LitElement {
return !this.isLoadingData && historyDataEmpty;
}
@eventOptions({ passive: true })
private _saveScrollPos(e: Event) {
this._savedScrollPos = (e.target as HTMLDivElement).scrollTop;
}
static get styles(): CSSResultGroup {
return css`
:host {
@@ -103,11 +176,48 @@ class StateHistoryCharts extends LitElement {
/* height of single timeline chart = 60px */
min-height: 60px;
}
:host([virtualize]) {
height: 100%;
}
.info {
text-align: center;
line-height: 60px;
color: var(--secondary-text-color);
}
.container {
max-height: var(--history-max-height);
}
.entry-container {
width: 100%;
}
.entry-container:hover {
z-index: 1;
}
:host([virtualize]) .entry-container {
padding-left: 1px;
padding-right: 1px;
}
.container,
lit-virtualizer {
height: 100%;
width: 100%;
}
lit-virtualizer {
contain: size layout !important;
}
state-history-chart-timeline,
state-history-chart-line {
width: 100%;
}
`;
}
}
+38 -30
View File
@@ -13,38 +13,45 @@ import {
TemplateResult,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { getGraphColorByIndex } from "../../common/color/colors";
import { isComponentLoaded } from "../../common/config/is_component_loaded";
import { computeStateName } from "../../common/entity/compute_state_name";
import {
formatNumber,
numberFormatToLocale,
} from "../../common/number/format_number";
import {
getStatisticIds,
getStatisticLabel,
getStatisticMetadata,
Statistics,
statisticsHaveType,
StatisticsMetaData,
StatisticType,
} from "../../data/history";
} from "../../data/recorder";
import type { HomeAssistant } from "../../types";
import "./ha-chart-base";
export type ExtendedStatisticType = StatisticType | "state";
export const statTypeMap: Record<ExtendedStatisticType, StatisticType> = {
mean: "mean",
min: "min",
max: "max",
sum: "sum",
state: "sum",
};
@customElement("statistics-chart")
class StatisticsChart extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public statisticsData!: Statistics;
@property({ type: Array }) public statisticIds?: StatisticsMetaData[];
@property() public names: boolean | Record<string, string> = false;
@property() public unit?: string;
@property({ attribute: false }) public endTime?: Date;
@property({ type: Array }) public statTypes: Array<StatisticType> = [
@property({ type: Array }) public statTypes: Array<ExtendedStatisticType> = [
"sum",
"min",
"mean",
@@ -191,18 +198,28 @@ class StatisticsChart extends LitElement {
};
}
private async _getStatisticIds() {
this.statisticIds = await getStatisticIds(this.hass);
}
private _getStatisticsMetaData = memoizeOne(
async (statisticIds: string[] | undefined) => {
const statsMetadataArray = await getStatisticMetadata(
this.hass,
statisticIds
);
const statisticsMetaData = {};
statsMetadataArray.forEach((x) => {
statisticsMetaData[x.statistic_id] = x;
});
return statisticsMetaData;
}
);
private async _generateData() {
if (!this.statisticsData) {
return;
}
if (!this.statisticIds) {
await this._getStatisticIds();
}
const statisticsMetaData = await this._getStatisticsMetaData(
Object.keys(this.statisticsData)
);
let colorIndex = 0;
const statisticsData = Object.values(this.statisticsData);
@@ -233,24 +250,16 @@ class StatisticsChart extends LitElement {
const names = this.names || {};
statisticsData.forEach((stats) => {
const firstStat = stats[0];
const meta = statisticsMetaData?.[firstStat.statistic_id];
let name = names[firstStat.statistic_id];
if (!name) {
const entityState = this.hass.states[firstStat.statistic_id];
if (entityState) {
name = computeStateName(entityState);
} else {
name = firstStat.statistic_id;
}
name = getStatisticLabel(this.hass, firstStat.statistic_id, meta);
}
const meta = this.statisticIds!.find(
(stat) => stat.statistic_id === firstStat.statistic_id
);
if (!this.unit) {
if (unit === undefined) {
unit = meta?.unit_of_measurement;
} else if (unit !== meta?.unit_of_measurement) {
unit = meta?.display_unit_of_measurement;
} else if (unit !== meta?.display_unit_of_measurement) {
unit = null;
}
}
@@ -307,7 +316,7 @@ class StatisticsChart extends LitElement {
: this.statTypes;
sortedTypes.forEach((type) => {
if (statisticsHaveType(stats, type)) {
if (statisticsHaveType(stats, statTypeMap[type])) {
const band = drawBands && (type === "min" || type === "max");
statTypes.push(type);
statDataSets.push({
@@ -335,7 +344,6 @@ class StatisticsChart extends LitElement {
let prevDate: Date | null = null;
// Process chart data.
let initVal: number | null = null;
let prevSum: number | null = null;
stats.forEach((stat) => {
const date = new Date(stat.start);
@@ -347,11 +355,11 @@ class StatisticsChart extends LitElement {
statTypes.forEach((type) => {
let val: number | null;
if (type === "sum") {
if (initVal === null) {
initVal = val = stat.state || 0;
if (prevSum === null) {
val = 0;
prevSum = stat.sum;
} else {
val = initVal + ((stat.sum || 0) - prevSum!);
val = (stat.sum || 0) - prevSum;
}
} else {
val = stat[type];
+4
View File
@@ -221,6 +221,10 @@ class DateRangePickerElement extends WrappedElement {
.calendar-table {
padding: 0 !important;
}
.daterangepicker.ltr {
direction: ltr;
text-align: left;
}
`;
const shadowRoot = this.shadowRoot!;
shadowRoot.appendChild(style);
@@ -1,7 +1,7 @@
import "@material/mwc-button/mwc-button";
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers";
import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event";
@@ -172,8 +172,7 @@ export abstract class HaDeviceAutomationPicker<
static get styles(): CSSResultGroup {
return css`
ha-select {
width: 100%;
margin-top: 4px;
display: block;
}
`;
}
+1 -1
View File
@@ -1,7 +1,7 @@
import "@material/mwc-list/mwc-list-item";
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers";
import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event";

Some files were not shown because too many files have changed in this diff Show More