Compare commits

..

455 Commits

Author SHA1 Message Date
Paulus Schoutsen
a2c0c0474a Bumped version to 20220427.0 2022-04-26 22:13:16 -07:00
Zack Barett
27884b9a54 Move Restart to Overflow and yaml config advanced (#12446)
* Move Restart to Overflow and yaml config advanced

* Move around YAML Config page

* Move to developer tools

* Make card actions

* Update Translations
2022-04-26 22:12:44 -07:00
Paulus Schoutsen
293df61872 Add a tip for my shortcut (#12462) 2022-04-27 05:01:40 +00:00
Paulus Schoutsen
f82dada3e5 Fix icon alignment in nav list (#12463) 2022-04-26 21:58:26 -07:00
Paulus Schoutsen
e5824c4794 Fix my link for config dashboard and profile (#12461)
* Fix my link for config dashboard and profile

* add server control redirect

Co-authored-by: Zack <zackbarett@hey.com>
2022-04-27 04:58:18 +00:00
Paulus Schoutsen
186550229c Tweak menu descriptions (#12460) 2022-04-27 04:53:42 +00:00
Zack Barett
7877dd8e6b Move Zones Edit to General config + add general config page (#12452)
* Move Zones Edit to General config + add general

* Update src/translations/en.json

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

* add paper tooltip back for yaml

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2022-04-26 21:53:29 -07:00
Zack Barett
b03abc249b Fix Updates Page Toast - Move to overflow (#12453) 2022-04-26 21:52:22 -07:00
Paulus Schoutsen
fda03918b9 Move the analytics link (#12459) 2022-04-27 04:40:01 +00:00
Zack Barett
6747375a1b Move Provider Selection to Menu on top header (#12443) 2022-04-26 23:27:15 -05:00
Zack Barett
53b6e31881 Update Configuration badge color to be accent color to match (#12455) 2022-04-26 21:12:09 -07:00
Zack Barett
fa004de2d1 Fix more info input number #12396 (#12456) 2022-04-26 21:11:54 -07:00
Zack Barett
3605f7b70f Fix when creating new area in picker #11392 (#12457) 2022-04-26 21:11:38 -07:00
Zack Barett
5348c54c91 Update the hint for key C (#12458) 2022-04-26 21:11:18 -07:00
Zack Barett
684e4421bc Fix for backup overflow (#12454) 2022-04-26 21:10:35 -07:00
Zack Barett
28f5611df5 Small edits on config menu (#12440) 2022-04-26 21:07:53 -07:00
Johann Vanackere
8da73d49d7 Terms based entities search (#10991) 2022-04-26 19:39:58 -05:00
Joakim Sørensen
049ddd5f84 Add "m" keyboard shortcut to get to the create my link page (#12451) 2022-04-27 00:11:09 +02:00
Bram Kragten
8ae2d4e93a Fix integration page on mobile (#12447) 2022-04-26 14:38:59 -05:00
Philip Allgaier
824bb9ba35 Add title to backups config page (#12442) 2022-04-26 21:04:32 +02:00
Philip Allgaier
d550b1a18e Fix content display for ha-network after #12438 (#12445)
* Fix content display for `ha-network` after #12438

* Add var default
2022-04-26 20:41:19 +02:00
Bram Kragten
dea6c0e761 Add header to supervisor backups page (#12444) 2022-04-26 17:53:32 +00:00
Philip Allgaier
9caee357c0 Fix incorrect text if no backups are found (#12441) 2022-04-26 12:32:04 -05:00
Bram Kragten
35d892c418 Set border radius in config to 8px (#12437) 2022-04-26 11:50:36 -05:00
Bram Kragten
9572a2a46b Dont show tabs when less than 2 (#12439) 2022-04-26 15:39:50 +00:00
Bram Kragten
8996361b26 Fix settings row width (#12438) 2022-04-26 15:17:00 +00:00
Joakim Sørensen
02ee731602 Add join/leave beta to updates panel (#12436) 2022-04-26 16:39:37 +02:00
Joakim Sørensen
bb1e6bf35b Fix backup back path (#12435) 2022-04-26 15:29:56 +02:00
Joakim Sørensen
c1b65285c1 Redirect hassio system my links to new locations (#12429) 2022-04-26 13:15:29 +02:00
Bram Kragten
8b8d6e5fa3 Resources lovelace should just go back (#12432) 2022-04-26 11:12:14 +00:00
Joakim Sørensen
c34fe184e8 Fix log syntax highlight when fetching logs from supervisor (#12430) 2022-04-26 06:09:39 -05:00
Joakim Sørensen
7363838f86 Move unsupported and unhealthy alerts (#12431) 2022-04-26 12:24:55 +02:00
Jaroslav Hanslík
3081425ccd Typo in en.json (#12428) 2022-04-26 12:20:26 +02:00
Joakim Sørensen
95d494a54c Guard against non OS installation (#12427) 2022-04-26 12:18:43 +02:00
J. Nick Koston
145e5d7bc6 Format sensors with state class duration (#12426) 2022-04-26 02:07:11 +00:00
Zack Barett
876fd9e85a Bumped version to 20220425.0 (#12425) 2022-04-25 18:25:07 -05:00
Zack Barett
e8c30cabca Show usage stats in System Health (#12424) 2022-04-25 23:24:58 +00:00
Bram Kragten
490f84a7b1 link to updates page (#12423) 2022-04-25 15:56:34 -05:00
Artem Sorokin
ca28178b86 Fix title and description for menu step in options flow (#12420) 2022-04-25 20:26:05 +00:00
Zack Barett
2fceb0aeee Allow for checking for updates (#12422) 2022-04-25 22:15:26 +02:00
Bram Kragten
86f39d1d43 Add supervisor, OS version info to about page (#12421)
* Add supervisor, OS version info to about page

* description

* description
2022-04-25 22:14:32 +02:00
Zack Barett
1faf60444d Move Data Disk Moving to Storage (#12416) 2022-04-25 20:49:44 +02:00
Netzwerkfehler
e927091d21 Better gauge segment coloring (#11570) 2022-04-25 13:43:53 -05:00
Bram Kragten
cff2f856b3 Don't show tabs in supervisor (#12417) 2022-04-25 13:37:48 -05:00
Bram Kragten
a743e3bbba Show what updates are skipped (#12418) 2022-04-25 18:37:24 +00:00
Zack Barett
f8a52d250e Move System Health to a page (#12412) 2022-04-25 20:26:53 +02:00
Zack Barett
b70a523bdf Backup Page - Will load which is available (#12414) 2022-04-25 19:54:11 +02:00
Zack Barett
8f2ed747e6 Configuration Menu Cleanup items (#12413) 2022-04-25 19:53:02 +02:00
Zack Barett
5deccefb15 Allow Showing Skipped Updates on Updates Page (#12415) 2022-04-25 19:50:30 +02:00
Zack Barett
3f04abfa9d Add Supervisor logs to core page (#12410) 2022-04-25 15:35:03 +00:00
Zack Barett
8e55c83996 Add Hardware Page to Configuration System Menu (#12405) 2022-04-25 17:30:53 +02:00
Bram Kragten
dee59486ba Add supervisor hostname config (#12407) 2022-04-25 10:27:38 -05:00
Bram Kragten
77ef509aea Fix zones (#12409) 2022-04-25 15:13:31 +00:00
Bram Kragten
bfa7bccfa6 Add supervisor network interface settings (#12403) 2022-04-25 16:21:03 +02:00
Thomas Lovén
a8c365edc8 Fix broken cards being able to crash entire view (#11440) 2022-04-25 14:37:32 +02:00
Bram Kragten
94953ddf6c Hide supervisor only config, fix backup config page (#12401) 2022-04-25 07:09:23 -05:00
Zack Barett
6b67546daf Virtualize Media Player Grid (#11898) 2022-04-25 12:32:50 +02:00
Paulus Schoutsen
3e188d1f87 Add shorthand condition to the gallery (#12400) 2022-04-25 10:00:28 +02:00
Zack Barett
f69eb15a90 Config Menu: Addressing Comments in #12377 (#12399) 2022-04-24 20:25:47 -07:00
Paulus Schoutsen
dfe348187f Bumped version to 20220424.0 2022-04-24 15:26:42 -07:00
Zack Barett
9706c56c5c Configuration Menu Updates 3 (#12377) 2022-04-24 15:26:01 -07:00
Raman Gupta
3677c5be2c Update zwavejs controller model (#12390) 2022-04-24 14:55:31 -07:00
Zack Barett
bd339fa963 Fix Dashboard URLs (#12394) 2022-04-24 14:55:04 -07:00
Yosi Levy
28f1b6bdf4 Force LTR on time & number inputs (#12393) 2022-04-23 19:48:17 -05:00
Zack Barett
c5aac3b81d Add Empty list item for None (#12356) 2022-04-23 10:11:44 -05:00
yangqian
70836597e9 Show vacuum state in more-info dialog for StateVacuumEntity (#12391) 2022-04-23 06:32:59 +00:00
Allen Porter
958a1de2fd Add calendar event end trigger to automation editor (#12389) 2022-04-23 00:19:23 -05:00
Allen Porter
36d30266e3 Add automation editor for calendar trigger (#12343) 2022-04-22 16:53:45 -05:00
Yosi Levy
558ab9761d RTL reading orders and alignments in system log (#12388) 2022-04-22 20:19:38 +00:00
Eric Stern
269ef370e4 Accept new value when hitting ENTER to close a prompt dialog (#12360)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-04-22 14:23:34 -05:00
Kuba Wolanin
ba2958ecd2 zwave_js: Add title tag to config box heading (#12387) 2022-04-22 13:17:42 -05:00
Yosi Levy
3b8b6eb315 RTL fixes (#12367) 2022-04-22 10:27:49 -05:00
Mark Lopez
4f13db3178 Added ability to retry on initialization errors. (#12103) 2022-04-21 21:11:32 -05:00
Joakim Sørensen
ee7aa54ab4 Add entity search tip to dev-tools set state (#12355) 2022-04-21 21:06:35 -05:00
Wesley Vos
c305dd4cd5 Fix for monetary entities (#12378) 2022-04-21 21:01:09 -05:00
Franck Nijhof
6865791596 Add jinja2 editor to template triggers/conditions (#12365)
Co-authored-by: Zack <zackbarett@hey.com>
2022-04-22 01:42:28 +00:00
Franck Nijhof
2099259393 Use template selector in wait_template (#12366) 2022-04-21 20:32:25 -05:00
Zack Barett
27ca45dc70 Bumped version to 20220420.0 (#12369) 2022-04-20 22:43:40 +00:00
Zack Barett
d290c11219 Config menu updates to get it ready for nightly (#12368) 2022-04-20 22:38:35 +00:00
Zack Barett
cabe10ffdb Getting started on Configuration Changes (#12309)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-04-20 16:57:51 -05:00
Franck Nijhof
aa562c21a8 Add stop script/automation action (#12299) 2022-04-20 16:50:09 -05:00
Franck Nijhof
22175a7271 Add if/else automation/script action (#12301)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-04-20 11:27:16 -05:00
Eric Stern
1e0647c0d1 Github no longer supports the (insecure) git protocol (#12359) 2022-04-20 13:52:12 +00:00
Simon Vallières
58d94da8b3 Adding blueprint input description markdown/multi-line support (#12291) 2022-04-20 08:36:18 -05:00
Joakim Sørensen
d97763a3e8 Add clear skipped to update more-info dialog (#12361) 2022-04-20 08:17:56 -05:00
Paulus Schoutsen
aa129aa123 Bump HAWS to 7.0.3 (#12358) 2022-04-19 12:50:18 -05:00
Franck Nijhof
f648317206 Fix strict error handling in developer tools templates (#12352) 2022-04-19 07:28:07 -05:00
Raman Gupta
0685fdf7c6 Add basic frontend support for siren (#12345) 2022-04-18 11:19:01 -05:00
Franck Nijhof
6fd4cda534 Add Template selector (#12348) 2022-04-18 11:17:44 -05:00
Franck Nijhof
511368da13 Allow selecting multiple entities for state trigger (#12334)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-04-15 19:03:14 +00:00
J. Nick Koston
76e1721c58 Quickly search for entities from the Overview Dashboard (#12324) 2022-04-15 13:54:57 -05:00
Yosi Levy
bad5a389b5 RTL calendar fix - arrows fix and views fix (#12314)
* RTL calendar fix - arrows fix and views fix

* Removed path attributes
2022-04-15 13:47:46 -05:00
Paulus Schoutsen
85d1f49763 Allow tapping on the name on a picture entity card (#12332) 2022-04-15 08:55:22 -05:00
Paulus Schoutsen
7723d47ac1 Split only on first comma in media browser (#12331) 2022-04-14 17:52:49 -05:00
J. Nick Koston
30b130ca74 Use new mdi icons for smoke and co detection (#12323) 2022-04-14 15:42:54 -07:00
Joakim Sørensen
a124ec0717 Always render title field (#12319) 2022-04-13 07:20:00 -05:00
Joakim Sørensen
323d98ecf7 Decode view path URL (#12310) 2022-04-12 06:52:17 -05:00
Paulus Schoutsen
125a601ae3 Select default mode if none set (#12306) 2022-04-11 12:08:37 -05:00
Paulus Schoutsen
3c549c6b31 Update cloud text (#12305) 2022-04-11 09:47:31 -07:00
Kuba Wolanin
9c1494c74d Fix endless loading screen in zwave-js config (#12295) 2022-04-11 16:56:03 +02:00
Philip Allgaier
e751abd775 Prevent empty brackets if no manufacturer during config entry creation (#12288) 2022-04-11 09:06:29 -05:00
Joakim Sørensen
714f2447b7 Use more text selector types for add-on configuration (#12303) 2022-04-11 16:01:30 +02:00
Franck Nijhof
d900e40d04 Fix add-on security rating range (#12300) 2022-04-11 14:04:54 +02:00
Joakim Sørensen
8b82383790 Guard for partial translations (#12296) 2022-04-11 13:03:41 +02:00
Zack Barett
5a2cc2646c Merge pull request #12252 from spacegaier/issue-12246 2022-04-07 16:40:08 -05:00
Philip Allgaier
16a0902989 Adjust import 2022-04-07 22:41:37 +02:00
Philip Allgaier
8f67aa38af Fix entity and device selector with multiple: true 2022-04-07 21:39:04 +02:00
Zack Barett
34184cf2ab Merge pull request #12250 from spacegaier/issue-12248 2022-04-07 14:11:29 -05:00
Philip Allgaier
611cd2818e Exclude hidden entities from area card 2022-04-07 20:58:21 +02:00
Zack Barett
0a4e8fd5d0 Merge pull request #12244 from home-assistant/lineup-badges 2022-04-07 13:19:48 -05:00
Ludeeus
11f0361f48 Lineup sidebar badges 2022-04-07 06:54:24 +00:00
Philip Allgaier
cfa048ea4e Only show "required" indicator if we have a selector label (#12241) 2022-04-06 22:11:12 +00:00
Joakim Sørensen
bbca7b762b Use selectors for add-on network configuration (#12235)
* Use selectors for add-on network configuration

* Show container port as UOM if advanced user

* adjust
2022-04-06 22:21:06 +02:00
Erik Montnemery
1dba849567 Fix statistics chart for sum stat without state (#12238) 2022-04-06 20:54:11 +02:00
Marius
aff1ec10bf replace ToggleSwitch with new LightSwitch (#12218) 2022-04-06 16:26:34 +02:00
Joakim Sørensen
351ec08a71 Use selectors for add-on configurations (#12234) 2022-04-06 09:57:17 +02:00
Paulus Schoutsen
a1a6a2cd30 Bumped version to 20220405.0 2022-04-05 15:49:13 -07:00
Joakim Sørensen
4e82c23b29 Fixes for flow help icon (#12224) 2022-04-05 15:47:24 -07:00
Paulus Schoutsen
59595aabde Add helpers to all selectors (#12230) 2022-04-05 15:26:52 -05:00
Paulus Schoutsen
358f91c2a9 Add statistic name to adjust dialog (#12229) 2022-04-05 17:25:23 +00:00
Joakim Sørensen
e0e01e68b4 Use change instead of click when selecting home assistant in backup (#12226) 2022-04-05 10:48:45 -05:00
Paulus Schoutsen
61dc4eaaea Throttle counting updates (#12223) 2022-04-05 09:55:01 +02:00
Paulus Schoutsen
65c4d02452 Fix Safari dates (#12222) 2022-04-04 21:54:35 -07:00
Philip Allgaier
f78ce2c844 Sort "Switch as" domains and add separator (#12216) 2022-04-04 18:47:26 -05:00
Philip Allgaier
4d1ab83b30 Hide "Show as" separator if there is nothing above/below it (#12219) 2022-04-04 18:44:21 -05:00
Zack Barett
fb4b40b828 Fix Entity Settings missing (#12221) 2022-04-04 22:49:11 +00:00
Philip Allgaier
db0c4ef941 Fix "Show as" in entity registry (#12215) 2022-04-04 14:16:03 -05:00
Philip Allgaier
c5b60b826b Enable <ha-form> overflow overriding via part (#12204) 2022-04-04 08:41:12 -05:00
Philip Allgaier
718f0330a7 Fix button card behavior to toggle scenes (#12203) 2022-04-04 08:40:10 -05:00
Philip Allgaier
89e31486c5 Ensure history entity picker wraps to next line on mobile (#12201) 2022-04-04 08:39:45 -05:00
Philip Allgaier
717eec1860 Allow "none" again as secondary entity information (#12199) 2022-04-04 08:39:28 -05:00
Philip Allgaier
b6e51352e3 Fan more-info: Add margin to sections (#12202) 2022-04-04 08:38:53 -05:00
Joakim Sørensen
2ade728bc3 Make the progress bar not jump the dialog (#12212) 2022-04-04 08:20:37 +02:00
Joakim Sørensen
62f227da83 Use installed_version for update entities (#12194) 2022-04-01 19:28:39 +02:00
Bram Kragten
9557b604da Bumped version to 20220401.0 2022-04-01 18:35:08 +02:00
Zack Barett
b45c355c9f Fix for Mult enabled selectors when required (#12191) 2022-04-01 18:34:32 +02:00
Joakim Sørensen
0b47d2c687 Redirect old backup links to backup integration for non supervised (#12183) 2022-04-01 08:05:53 -07:00
Joakim Sørensen
8baa0b2a9b Hide skip when auto_update is true for updates (#12184) 2022-04-01 14:37:47 +02:00
Joakim Sørensen
c68a1d21ff Do not offer to partially backup homeassistant configuration (#12188) 2022-04-01 14:37:18 +02:00
Paulus Schoutsen
419d659311 Guard calling input select row with bad option (#12181) 2022-03-31 20:32:10 -05:00
Bram Kragten
ba8b20d877 Fix url config when not logged in to cloud (#12176) 2022-03-31 10:59:44 -05:00
Bram Kragten
8de542388f Show hidden entities on device page (#12177) 2022-03-31 10:59:20 -05:00
Raman Gupta
e6c580aadc Add zwave-js node alerts to device configuration page (#12173)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-03-31 09:06:47 -05:00
Joakim Sørensen
11696c566a Add support for my backup links (#12172) 2022-03-31 09:05:39 -05:00
Joakim Sørensen
edc15940a2 Add icon to add-on picker (#12174) 2022-03-31 15:16:19 +02:00
Joakim Sørensen
bf35ee549d Only use the state to mark updates as pending (#12171) 2022-03-31 15:15:21 +02:00
Philip Allgaier
4c3baa678c Bump caniuse-lite (#12168) 2022-03-30 17:12:22 -05:00
Philip Allgaier
0bb2767696 Add missing labels to media player volume buttons (#12170) 2022-03-30 17:11:50 -05:00
Philip Allgaier
80a4852325 Add missing label for new statistics "adjust sum" button (#12169) 2022-03-30 17:11:23 -05:00
Bram Kragten
9c3e0fc997 Merge branch 'master' into dev 2022-03-30 20:48:37 +02:00
Zack Barett
9e4bee123f Bumped version to 20220330.0 (#12164) 2022-03-30 11:33:59 -07:00
Bram Kragten
c2c09b1284 Add switch as x to entity settings (#12161)
Co-authored-by: Zack <zackbarett@hey.com>
2022-03-30 18:19:26 +00:00
Zack Barett
bad776b979 Allow Sensor Units to be updated via Entity Registry (#12143) 2022-03-30 13:03:19 -05:00
Zack Barett
396791b805 Fix for Mobile View of Entities Table (#12160) 2022-03-30 19:52:05 +02:00
Joakim Sørensen
2b1457e1cd Add panel to Backup integration (#11671)
Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2022-03-30 17:22:15 +00:00
NachtaktiverHalbaffe
b5861869e3 Add shuffle and repeat-mode of media_player to UI (#12052)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2022-03-30 17:16:27 +00:00
Zack Barett
9444228907 List Selector (#12099)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-03-30 09:14:39 -07:00
Bram Kragten
86afd883a5 Add helpers to list when searching in add integration (#12159) 2022-03-30 13:55:54 +00:00
Bram Kragten
062f21aa91 Add options to selectors gallery (#12156) 2022-03-30 12:34:37 +00:00
Joakim Sørensen
ba235ac797 Import components that are allowed to be defined in markdown (#12158) 2022-03-30 14:22:24 +02:00
Bram Kragten
505c22248b Use brand icon instead of domain icon for helpers (#12157) 2022-03-30 13:53:37 +02:00
Bram Kragten
624cb48f78 Add support for my links to create a helper config entry (#12155) 2022-03-30 13:53:28 +02:00
Zack Barett
7ab54ee5ce Update Pickers and selectors with required (#12151)
* Update Pickers and selectors with required

* Use native * for device and entity
2022-03-30 06:48:56 -05:00
blair
f5af63a50e Automation description text overflow (#12040)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-03-30 10:22:26 +00:00
Marius
ff80ab34ee Allow device_tracker entities to use state_color (#12127) 2022-03-30 11:35:37 +02:00
Joakim Sørensen
cfc1999a28 Allow ha-alert to be used in our markdown render (#12153) 2022-03-30 11:22:36 +02:00
Joakim Sørensen
7ca28469b7 Fix theme settings on design page (#12154) 2022-03-30 11:21:00 +02:00
Raman Gupta
ac670614b4 Add support for new timer properties (#11940) 2022-03-30 00:00:36 -07:00
Joakim Sørensen
e263b57296 Fetch release notes for update entities that provides it (#12148)
* Fetch release notes for update entities that provides it

* lint
2022-03-30 07:22:12 +02:00
Paulus Schoutsen
c7050e4676 Update adjust statistic dialog (#12118)
* Update text for adjust statistic dialog

* Change everything

* Import type

* Max show 5

* Revert back the API change

* Hide adjust button if no sum

* Adjustments

* Update src/panels/developer-tools/statistics/developer-tools-statistics.ts

* Render optional

Co-authored-by: Zack <zackbarett@hey.com>
2022-03-29 20:40:17 -07:00
Paulus Schoutsen
00cbd1d9e6 Add entity source API (#12149) 2022-03-29 17:09:51 -07:00
Zack Barett
2a12172eeb Bumped version to 20220329.0 (#12152) 2022-03-29 22:25:56 +00:00
Joakim Sørensen
85d3011625 Add badge to configuration sidebar to indicate pending updates (#12146) 2022-03-29 07:35:05 -05:00
Zack Barett
ca22ec6340 Add selector initial values (#12142) 2022-03-28 10:38:58 -07:00
Zack Barett
61f6e8855b Allow binary sensor device class updates (#12124) 2022-03-28 10:44:21 -05:00
Bram Kragten
a44b8981e1 break theme picker out of lovelace (#12140) 2022-03-28 08:21:16 -07:00
Zack Barett
b080bca9ce Add Area Multiple Selector option (#12138) 2022-03-28 09:07:00 -05:00
Bram Kragten
d30e8ee9d8 Make padding on settings row content consistent (#12139) 2022-03-28 08:50:07 -05:00
Bram Kragten
637e4203e5 Fix z-index map, always set icon for location selector (#12137) 2022-03-28 13:14:24 +00:00
Zack Barett
2648a53bbc Merge pull request #12135 from home-assistant/update-automation-type 2022-03-28 07:43:21 -05:00
Paulus Schoutsen
b3fa0cccb4 Add variables to automation trigger type 2022-03-27 20:33:22 -07:00
Zack Barett
dd963be723 Add Day to duration selector (#12125) 2022-03-24 17:57:20 -07:00
Paulus Schoutsen
224df896a1 Allow rendering helper text from strings.json (#12119)
* Allow rendering helper text from strings.json

* Persistent helpers

* Update src/components/ha-base-time-input.ts

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

* Update src/components/ha-base-time-input.ts

Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-03-24 17:50:38 -07:00
Pawel
a58b4fb262 Fix possibility to enable entity disabled by integration (#12121)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-03-24 20:10:49 +01:00
Brynley McDonald
27ca61ec85 Fix issue where theme select does not appear when user's theme is deleted (#12104) 2022-03-24 16:31:55 +01:00
Zack Barett
859f49f3eb Update type for backend (#12122) 2022-03-24 13:47:07 +00:00
Erik Montnemery
40d878689f Sort selectors (#12120) 2022-03-24 11:53:32 +01:00
Zack Barett
420e8fe1ff Merge pull request #12116 from home-assistant/docs-only-form 2022-03-23 17:40:40 -05:00
Erik Montnemery
df96199433 Support descriptions in flow menu steps (#12108)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2022-03-23 22:14:57 +00:00
Erik Montnemery
f493280f0a Exclude restored automations from dashboard (#12113) 2022-03-23 15:05:41 -07:00
Paulus Schoutsen
cbd030a379 Only show docs link when showing a form 2022-03-23 14:53:02 -07:00
Zack Barett
95b80accc9 Merge pull request #12085 from goyney/update-mdi-to-6-6-95 2022-03-23 15:17:31 -05:00
Erik Montnemery
c522670815 Fix loading traces for automation with custom id (#12112) 2022-03-23 13:11:46 -07:00
Joakim Sørensen
7b6d3c0e36 Use update entities for showing updates on configuration panel (#12100)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2022-03-23 13:04:29 -07:00
Michael Irigoyen
504b043159 Update lock file with MDI updates 2022-03-23 08:46:22 -05:00
Michael Irigoyen
dffc66ccc3 Merge branch 'dev' of github.com:goyney/frontend into update-mdi-to-6-6-95 2022-03-23 08:43:46 -05:00
Zack Barett
c7e9ee785d Merge pull request #12109 from home-assistant/number_selector_allow_0 2022-03-23 08:42:00 -05:00
Erik
079cc39a6e Fix selecting 0 with number selector 2022-03-23 14:24:55 +01:00
Marc Mueller
d6a1d5af79 Remove setup.py (#11593) 2022-03-23 09:22:12 +01:00
Matthias de Baat
c0dce08e19 Create user types page and rename the category (#12089)
Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2022-03-23 03:51:35 +00:00
Zack Barett
a7a347ed05 Bumped version to 20220322.0 (#12102) 2022-03-22 17:08:30 -07:00
Zack Barett
2d9b50defc Fix Duration Selector Default (#12098)
* Fix Duration Default

* USe initial form data function
2022-03-22 23:33:16 +00:00
Paulus Schoutsen
840858b18c Add statistic adjust dialog (#12101)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-03-22 22:40:00 +00:00
Zack Barett
afd2e71f6c change from hidden to not shown (#12097) 2022-03-22 15:39:22 -07:00
Zack Barett
88af0aa788 Add entity include and exclude to selector (#12078)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2022-03-22 19:58:03 +00:00
Zack Barett
49124f6f09 Update When entity can change enabled or hidden (#12096) 2022-03-22 19:53:22 +00:00
Paulus Schoutsen
73f5580555 Add support for integration type (#12077) 2022-03-22 14:47:12 -05:00
Joakim Sørensen
bdde5268c6 Add support for update entities (#12059)
* Add support for update entities

* Apply suggestions from code review

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

* Add to gallery

* implement xx%

* Adjustments for skipped

* Add progress bar

* Add UPDATE_SUPPORT_INSTALL

* Allow skipping without install support

* Add version to service call if supported

* Adjust changelog link

* Use Installing

* adjustments

* Use unavailable

Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-03-22 10:23:54 -07:00
Zack Barett
15e972c158 Stack Action Inputs in the Button Editor (#12076)
* Stack Action Inputs in the Button Editor

* update style

* Update for other editors
2022-03-22 08:57:09 -07:00
Zack Barett
0fc4c24f5a Merge pull request #12087 from DuckyCrayfish/fix-toolbar-styles 2022-03-22 10:29:11 -05:00
Zack Barett
9eba50df0c Merge pull request #11651 from home-assistant/add-docs-icon-config-flow 2022-03-22 10:23:43 -05:00
Zack Barett
0e0e07437f Update src/dialogs/config-flow/dialog-data-entry-flow.ts 2022-03-22 10:08:43 -05:00
Joakim Sørensen
6ac51ede52 Change Netlify preview URL (#12095) 2022-03-22 16:00:43 +01:00
Pawel
ccf1fb573a Fix gas energy graph units if stats added by external source (#11892) 2022-03-21 21:15:28 -07:00
Nick Iacullo
fa537968c4 Update styles for hui-editor
Update the background-color and text-color of the app-toolbar in
hui-editor to match the styles of hui-root while in edit-mode.

Previously, these properties were set using undefined css variables that
could not be changed via themes (--dark-background-color and
--dark-text-color).
2022-03-21 10:28:24 +00:00
Marc Mueller
6bf2111a3c Upload release assets (#11566)
Co-authored-by: Joakim Sørensen <hi@ludeeus.dev>
2022-03-21 08:23:05 +01:00
Michael Irigoyen
f5f8be8276 Update required version of MDI to 6.6.95 2022-03-20 23:32:21 -05:00
J. Nick Koston
ddf1cc0733 Fetch history with no_attributes for entities that do not need them (#12082) 2022-03-20 15:47:13 -10:00
Zack Barett
9c1d1cb6f6 Merge pull request #12069 from matthiasdebaat/patch-2 2022-03-18 07:32:14 -05:00
Matthias de Baat
470225abde Update logo.markdown 2022-03-18 11:26:19 +01:00
Matthias de Baat
ee230b86c1 Update gallery/src/pages/brand/logo.markdown
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-03-18 11:25:41 +01:00
Matthias de Baat
f927fc64a9 Update gallery/src/pages/brand/logo.markdown
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-03-18 11:25:34 +01:00
Zack Barett
03677c33f7 Bumped version to 20220317.0 (#12074) 2022-03-17 15:27:27 -07:00
Zack Barett
bc36a206da Merge pull request #11984 from Mariusthvdb/patch-4 2022-03-17 17:15:41 -05:00
Zack Barett
af06ab1e2d Merge pull request #12073 from home-assistant/bump-haws-701 2022-03-17 17:11:53 -05:00
Zack Barett
3e2135a485 Add radio Form Logic to Select Selector (#12063) 2022-03-17 15:04:59 -07:00
Zack Barett
2e7f8fb46f Add Date Time Selector (#12070) 2022-03-17 15:01:08 -07:00
Paulus Schoutsen
102568c4bd Update lock 2022-03-17 14:58:45 -07:00
Paulus Schoutsen
4fcdae842e Bump HAWS to 7.0.1 2022-03-17 14:50:16 -07:00
Paulus Schoutsen
ea19740f5a Ignore diagnostics not found exceptions (#12066) 2022-03-17 13:44:06 -07:00
Matthias de Baat
3e0942b631 Add files via upload 2022-03-17 14:19:28 +01:00
Matthias de Baat
0261cea796 Create new Logo page 2022-03-17 14:14:13 +01:00
Paulus Schoutsen
5247b2813f Bump HAWS to 7.0.0 (#12067) 2022-03-16 19:54:25 -10:00
Zack Barett
8a5090684e Merge pull request #12064 from home-assistant/20220316.0 2022-03-16 17:59:26 -05:00
Zack Barett
1784ba5e68 Merge pull request #12061 from home-assistant/Add-Date-Selector 2022-03-16 17:52:40 -05:00
Zack Barett
4fbe9a7b10 Merge pull request #12049 from home-assistant/hide-hidden-entities 2022-03-16 17:49:20 -05:00
Zack
1ca9c7838a Bumped version to 20220316.0 2022-03-16 17:46:32 -05:00
Zack
4fc2c3ef05 Remvoe redunency 2022-03-16 17:42:11 -05:00
Zack Barett
73ff8e28a8 Add Devices Picker (#12056) 2022-03-16 15:40:34 -07:00
Zack
dde1c5e03c Entity Status 2022-03-16 17:38:38 -05:00
Zack
01eed22592 clean up 2022-03-16 17:34:09 -05:00
Zack
94ebb63589 add to basic editor and update advanced style 2022-03-16 17:25:08 -05:00
Zack
29119db5ce Add translation 2022-03-16 17:05:52 -05:00
Paulus Schoutsen
9908162ac2 Add support for menu data entry flow option (#12055) 2022-03-16 14:14:38 -07:00
Paulus Schoutsen
1e929ae78a Revamp URL form (#12060) 2022-03-16 14:14:25 -07:00
Paulus Schoutsen
ab5df0fe6e test condition (#11925) 2022-03-16 14:13:13 -07:00
Paulus Schoutsen
d5010dda9e Add ha-form context (#12062) 2022-03-16 14:12:10 -07:00
Zack
4ac097f32b Add Date Selector 2022-03-16 14:20:45 -05:00
Zack Barett
5d3d15072f Merge pull request #12054 from home-assistant/Add-image-to-design-docs 2022-03-16 13:24:03 -05:00
Zack Barett
5c53bc4225 Add Color RGB Selector (#12039) 2022-03-15 15:34:02 -07:00
Zack
d5a307f8f4 Add icons and buttons 2022-03-15 15:00:35 -05:00
Zack
a27dd1e7f1 Add Description of chosen 2022-03-15 14:47:15 -05:00
Zack
c86ed1fb3e remove 1 2022-03-15 14:33:11 -05:00
Zack
7fa7a48072 Disabled by 2022-03-15 14:32:49 -05:00
Zack
4e0fc8ee08 Update Translations 2022-03-15 14:26:21 -05:00
Zack
5f6490e54e Add HA to public folder and show in markdown 2022-03-15 14:17:24 -05:00
Matthias de Baat
db78b046a2 Add Brand folder and Our story page (#11978)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-03-15 09:01:42 -05:00
Zack
c37fe1e7ff add to demo 2022-03-14 20:39:03 -05:00
Zack
f1ec479d41 Reviews 2022-03-14 20:37:37 -05:00
Zack
e01cb3ca82 Utilize Hide Hidden Entities 2022-03-14 14:22:45 -05:00
Zack Barett
b8d3c68a7a Add Color Temp Selector (#12041) 2022-03-14 11:07:15 -07:00
Matthias de Baat
641003bb2a Rename Lovelace Dashboard to just Dashboard (#12044)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-03-14 11:05:44 -07:00
Zack Barett
3358fc2b18 Add all cover device classes (#12042) 2022-03-14 10:45:12 -07:00
Zack Barett
f9ccfa00a2 Merge pull request #12045 from home-assistant/hot-fix-03142022 2022-03-14 11:31:11 -05:00
Zack Barett
070e11a2db Fix @changed where using ev.detail (#12043) 2022-03-14 11:13:05 -05:00
Zack Barett
dcf50e055b Fix @changed where using ev.detail (#12043) 2022-03-14 16:11:46 +00:00
Zack Barett
fc1c6cea24 Fix: Changing Blueprint Automation Name (#12036) 2022-03-14 10:35:18 -05:00
Zack Barett
1fa04baa16 Fix: Changing Blueprint Automation Name (#12036) 2022-03-14 08:33:49 -07:00
Zack
c6a103bd30 Minor Version whoops 2022-03-14 10:27:59 -05:00
jpearl
84ffa2369a Add shade to device class overrides (#11874) 2022-03-14 10:19:43 -05:00
Zack
9d1618024e Bumped version to 20220314.0 2022-03-14 07:52:06 -05:00
Zack Barett
307aa161a6 Script ID update with Alias (#12008) 2022-03-14 07:46:40 -05:00
Zack Barett
affa6a92e7 Fix: Allow for deleting Input_select options (#12007) 2022-03-14 07:46:40 -05:00
Zack Barett
1e5ec241d5 Fix For Selecting Device Class (#12010) 2022-03-14 07:46:40 -05:00
Zack Barett
27a98a32fc Fix Dashboard Editing (#12011) 2022-03-14 07:46:40 -05:00
Zack Barett
2c8ac58f97 Fix changing cost number in energy settings (#12009) 2022-03-14 07:46:40 -05:00
Charles Garwood
6b995969b1 Fix zwave_js set config dropdown default value (#11974)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2022-03-14 07:46:40 -05:00
Raman Gupta
72c107484a Fix zwave_js 'add/remove device' disabled bug (#12000)
* Fix zwave_js 'add/remove device' disabled bug

* revert extra change
2022-03-14 07:46:39 -05:00
Bram Kragten
d1085b6657 Fix theme setting (#11977) 2022-03-14 07:45:23 -05:00
Paulus Schoutsen
cc27ddb362 Bumped version to 20220312.0 2022-03-12 13:47:05 -08:00
Paulus Schoutsen
c4dc6bfb0d Bumped version to 20220301.2 2022-03-12 13:45:34 -08:00
Paulus Schoutsen
4fbcc30a37 Merge remote-tracking branch 'origin/master' into dev 2022-03-12 13:43:33 -08:00
Paulus Schoutsen
4916527e5f Bumped version to 20220301.1 2022-03-12 13:42:42 -08:00
Paulus Schoutsen
fad8a27232 HAWS 6.1 (#12016) 2022-03-12 09:56:25 -10:00
Zack Barett
a993d3a753 Script ID update with Alias (#12008) 2022-03-11 21:25:09 -08:00
Zack Barett
5dfe17a43a Fix: Allow for deleting Input_select options (#12007) 2022-03-11 17:07:56 -08:00
Zack Barett
9b6c935ffb Fix For Selecting Device Class (#12010) 2022-03-11 09:39:04 -08:00
Zack Barett
f4e28da0a3 Fix Dashboard Editing (#12011) 2022-03-11 09:38:18 -08:00
Zack Barett
294a69d7e4 Fix changing cost number in energy settings (#12009) 2022-03-11 09:37:22 -08:00
Charles Garwood
f89b8cffcf Fix zwave_js set config dropdown default value (#11974)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2022-03-10 09:21:04 -06:00
Raman Gupta
99fd3a1b6f Fix zwave_js 'add/remove device' disabled bug (#12000)
* Fix zwave_js 'add/remove device' disabled bug

* revert extra change
2022-03-10 08:45:12 -05:00
Emil Stjerneman
246e426182 #11971 Change order of alarm panel buttons (#11998) 2022-03-09 19:54:40 -06:00
Paulus Schoutsen
9f1e9b43fe Use entities-picker in entity selector (#11990) 2022-03-08 21:33:23 -06:00
Marius
8301ae262c change icon to mimic physical device
and follow comments
2022-03-08 21:40:42 +01:00
Zack Barett
d968fe41ee Update Style of Design Page (#11982) 2022-03-08 10:19:18 -08:00
Bram Kragten
db830e9014 Fix theme setting (#11977) 2022-03-08 10:13:08 -08:00
Paulus Schoutsen
fc6b594a27 Allow selecting multiple entities (#11986) 2022-03-08 10:09:45 -08:00
Marius
86dbf99ebe replace default switch icon
to  make it stand out against a power entity which uses the same mdiFlash https://github.com/home-assistant/core/issues/67620#issuecomment-1061949527

suggest the Outline version, so create a subtle difference with the on/off icons.
2022-03-08 17:41:32 +01:00
Joakim Sørensen
68e7ce1883 Add systemd_resolved unsupported reason (#11971) 2022-03-07 17:42:49 +01:00
Bram Kragten
e9003ac35e Merge pull request #11969 from home-assistant/patch-release 2022-03-07 17:08:58 +01:00
Bram Kragten
1dd5214b42 Bumped version to 20220301.1 2022-03-07 16:51:41 +01:00
Bram Kragten
96738350bb Add location selector, convert zone editor (#11902) 2022-03-07 16:51:20 +01:00
Bram Kragten
5bdecf57cf Convert file upload to mdc (#11906) 2022-03-07 16:51:02 +01:00
Bram Kragten
ec12282f8c A11y expansion panel (#11967) 2022-03-07 16:50:42 +01:00
Zack Barett
552dbca201 Fix for Statistics Editor (#11942)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-03-07 16:50:29 +01:00
Bram Kragten
0bbc0ebb3c Make min width of select configurable (#11965) 2022-03-07 16:50:14 +01:00
Bram Kragten
ac7acc5802 Fix humidifier more info mode dropdown (#11964) 2022-03-07 16:49:59 +01:00
Philip Allgaier
64e1d160d1 Correct media upload error + add file name (#11949)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-03-07 16:49:40 +01:00
Bram Kragten
8e51878b6d Convert inputs (#11907)
* Convert inputs

* Update dialog-thingtalk.ts

* imports
2022-03-07 16:49:20 +01:00
Paulus Schoutsen
7c94ced303 Guard setting up config flow for an unsupported domain (#11937) 2022-03-07 16:48:57 +01:00
Bram Kragten
a040e1d5e0 Convert lovelace config dialogs to ha-form (#11910) 2022-03-07 16:48:36 +01:00
Bram Kragten
87c7407857 Convert objects to string in config flow error (#11908) 2022-03-07 16:48:16 +01:00
Bram Kragten
d0d0c44ec7 Fix quickbar overlaying, fix click handling (#11900) 2022-03-07 16:47:56 +01:00
Bram Kragten
4cdff3faea Add location selector, convert zone editor (#11902) 2022-03-07 08:47:20 -06:00
Bram Kragten
0dac10aa23 Convert file upload to mdc (#11906) 2022-03-07 08:42:40 -06:00
Bram Kragten
4b8b14a69d A11y expansion panel (#11967) 2022-03-07 08:40:19 -06:00
Zack Barett
9d28df31bd Fix for Statistics Editor (#11942)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-03-07 15:29:00 +01:00
Bram Kragten
8258641443 Make min width of select configurable (#11965) 2022-03-07 14:55:44 +01:00
Bram Kragten
dfcb0f6ba0 Fix humidifier more info mode dropdown (#11964) 2022-03-07 07:25:38 -06:00
Philip Allgaier
2e10eb04b6 Correct media upload error + add file name (#11949)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-03-07 12:08:54 +00:00
Raman Gupta
b4b52d3872 Remove some additional old zwave code (#11941) 2022-03-07 12:49:51 +01:00
Bram Kragten
3873203721 Convert inputs (#11907)
* Convert inputs

* Update dialog-thingtalk.ts

* imports
2022-03-07 12:45:39 +01:00
Paulus Schoutsen
ccb91e0b49 Allow marking YAML editor as read only (#11960) 2022-03-07 12:39:16 +01:00
Paulus Schoutsen
bd20c15a55 Show triggered vars on click (#11924) 2022-03-04 23:24:31 -08:00
Paulus Schoutsen
0936fd9ae4 Guard setting up config flow for an unsupported domain (#11937) 2022-03-04 14:31:11 -08:00
Bram Kragten
adefc7a4e2 Convert lovelace config dialogs to ha-form (#11910) 2022-03-04 23:15:10 +01:00
Bram Kragten
8f8017ecff Remove zwave and ozw panels (#11911)
Remove zwave and ozw panels
2022-03-04 14:10:44 -08:00
Robin Wittebol
604b79696e Always show tab labels (#11919) 2022-03-03 19:46:14 +01:00
Robin Wittebol
8c445f6409 Fix datepicker triangle (#11920) 2022-03-03 19:45:03 +01:00
Bram Kragten
797c871137 Convert objects to string in config flow error (#11908) 2022-03-03 13:55:40 +01:00
Steve Repsher
24829bd903 Supervisor mobile click accessibility (#11915) 2022-03-03 10:15:22 +01:00
Bram Kragten
add92a559d Fix quickbar overlaying, fix click handling (#11900) 2022-03-02 17:50:01 +01:00
Paulus Schoutsen
7f086c0900 Merge pull request #11899 from home-assistant/dev 2022-03-01 15:06:56 -08:00
Paulus Schoutsen
17018c0f26 Bumped version to 20220301.0 2022-03-01 14:48:41 -08:00
Joakim Sørensen
cd6a478130 Better handle brands URL in media thumbnails (#11890) 2022-03-01 14:32:56 -08:00
Zack Barett
4f6d7ca5c9 Fix for Entity SElector when supplying multiple domains (#11887)
Fix for Entity SElector when supplying multiple domains
2022-02-28 16:45:33 -08:00
Joakim Sørensen
c2994343b4 Remove unused attributes from search-input (#11889) 2022-02-28 18:27:07 -06:00
Joakim Sørensen
e5f77c35d4 Remove autofocus form log panel search (#11888) 2022-03-01 00:31:09 +01:00
Steve Repsher
a9e5a5dd44 Add a few button labels (#11885)
* Add label to remove addon repository button

* Add label to delete energy device button

* Add label to quick bar button
2022-02-28 23:53:39 +01:00
Bram Kragten
1159798b8d Energy: Wait with subscribe for _config to be set (#11884) 2022-02-28 12:32:36 -06:00
Paulus Schoutsen
437de42c55 Handle resolve media and cannot play errors (#11878) 2022-02-28 12:30:49 +01:00
Bram Kragten
89e0bb3f16 Fix date input in Safari (#11871)
* Fix date input in Safari

* helper
2022-02-28 12:29:53 +01:00
Robin Wittebol
28c9631b6c Remove white border on date-range-picker triangle (#11877) 2022-02-28 12:29:07 +01:00
Paulus Schoutsen
8882624618 Merge pull request #11867 from home-assistant/dev 2022-02-26 13:41:41 -08:00
Paulus Schoutsen
a769f84755 Bumped version to 20220226.0 2022-02-26 13:28:52 -08:00
Bram Kragten
7abf9c2473 Fix condition time (#11866)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-02-26 21:18:33 +00:00
Paulus Schoutsen
298296a81f Fix iOS audio (#11863) 2022-02-26 15:08:42 -06:00
Marc Mueller
6907fa5c8e Add py.typed (#11865) 2022-02-26 13:03:12 -08:00
Zack Barett
546461b70f Fix Render Pane on Mobile (#11856) 2022-02-25 11:51:55 -08:00
Joakim Sørensen
4031009c26 Only set tip once (#11853) 2022-02-25 10:03:55 -06:00
Paulus Schoutsen
91e4557625 Guard controls in more info media player (#11851) 2022-02-25 01:31:59 -06:00
Paulus Schoutsen
f0c4b92dbb Small fixes for actions (#11850) 2022-02-24 21:48:54 -08:00
Paulus Schoutsen
ffac3d055e Merge pull request #11848 from home-assistant/dev 2022-02-24 16:37:06 -08:00
Zack Barett
04ae8c9d14 Bumped version to 20220224.0 (#11847) 2022-02-24 16:22:09 -08:00
Zack Barett
0158610d42 Finishing up the editors (#11846) 2022-02-24 23:35:28 +00:00
Bram Kragten
5ab6121581 Fix quickbar showing on ha-select (#11845) 2022-02-24 14:24:32 -08:00
Bram Kragten
3d9c31aef9 Allow to clear integration filter on mobile (#11844) 2022-02-24 14:21:25 -08:00
Paulus Schoutsen
acfeea5c92 Show browse media even if media player has no controls (#11843) 2022-02-24 14:17:33 -08:00
Zack Barett
75e8e17073 Statistics Graph Editor to Ha Form (#11820) 2022-02-24 22:49:43 +01:00
Zack Barett
976fd4b32d weather forecast editor to HA form (#11823) 2022-02-24 22:49:20 +01:00
Bram Kragten
49beafbe5f Fix dev states filter field on iOS (#11839) 2022-02-24 21:57:20 +01:00
Bram Kragten
151f8d5524 Fix time trigger (#11841) 2022-02-24 14:36:18 -06:00
Bram Kragten
48355aa98e Fix icon color in select (#11842) 2022-02-24 14:35:09 -06:00
Paulus Schoutsen
fc31929f41 Fix saving home name (#11838) 2022-02-24 18:51:56 +00:00
Paulus Schoutsen
b7c149fcc1 Fix timer entity exception (#11837) 2022-02-24 10:30:45 -08:00
Paulus Schoutsen
02d058561b Lovelace: Datetime and text to match look select (#11836) 2022-02-24 18:16:42 +00:00
Zack Barett
4e57fb1ec1 Fix for Sidebar view rendering issue (#11835) 2022-02-24 10:15:34 -08:00
Patrick ZAJDA
30f79c5a46 Ask confirmation before logging out from Home Assistant Cloud (#11833)
Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2022-02-24 10:13:19 -08:00
Zack Barett
30f7252d84 Update Media Browser Bar to show image on mobile but a bit less (#11818) 2022-02-24 11:56:20 -06:00
Bram Kragten
8af795a7ce Make automation name field wide (#11832) 2022-02-24 09:52:40 -06:00
Joakim Sørensen
8576eeae41 Add tip rotation on dashboard (#11826)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-24 09:07:32 -06:00
Paulus Schoutsen
cd740ed135 Fix cast receiver background (#11825)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-24 10:52:12 +00:00
Zack Barett
892f774792 Picture Glance to HA Form (#11821) 2022-02-23 21:40:04 -08:00
Zack Barett
aa504fe1f8 Shopping list to MWC (#11822) 2022-02-23 21:36:58 -08:00
Paulus Schoutsen
be491451d5 Add run action to dropdown (#11817) 2022-02-23 21:36:25 -08:00
Zack Barett
bad184210d Control where the tip breaks (#11819) 2022-02-23 19:42:32 -06:00
Bram Kragten
a43b3b64b3 Link to filtered logs (#11816) 2022-02-23 23:14:16 +01:00
Bram Kragten
aa831a9adf bump marked and flatmap (#11814) 2022-02-23 22:11:13 +01:00
Bram Kragten
43d4f55392 Update workbox (#11813)
* Update workbox

* dedupe
2022-02-23 22:10:16 +01:00
Bram Kragten
130c66fb24 Update yarn (#11812)
* Update yarn

* Update yarn.lock

* dedupe
2022-02-23 22:08:43 +01:00
Zack Barett
684c232c8c Sensor Card Editor to Ha Form (#11810)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-23 21:46:52 +01:00
Paulus Schoutsen
09f8f816d1 Merge pull request #11809 from home-assistant/dev (#11809)
* Fix config card rtl issues

* Remove optional field from ha-form schema type (#11538)

* Add entity id autocompletion to YAML code editors (#11099)

* Add selectors to ha-form (#11534)

* Allow translate gas total (#11547)

* Migrate combobox to mwc (#11546)

* New date picker (#11555)

* Link via device on device page (#11554)

Co-authored-by: Zack Barett <arnett.zackary@gmail.com>

* Add integration_discovery to discovery sources (#11564)

* Remember filter between navigation (#11565)

* Convert selectors to MWC (#11543)

* Covert area picker to combo-box (#11562)

* Convert entity picker to ha-combo (#11560)

* Convert entity picker to ha-combo

* Update ha-entity-picker.ts

* Handle empty better

* Clear value when no device/area/entity

* Update links on info page (#11590)

* Migrate (input) select entities to mwc (#11591)

* Convert HaFormSchemas to use selectors (#11589)

* Fix number selector (#11585)

* Convert entity-attribute picker to ha-combo-box (#11587)

* Convert icon picker to ha-combobox (#11586)

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

* Convert area-devices picker (#11588)

* Convert device automation picker to mwc (#11592)

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

* Fix clearing device in device action (#11594)

* dark mode fixes (#11595)

* Only show stable add-ons in the store if not advanced mode (#11596)

* Convert Automation Action Choose to HA Form (#11597)

* Convert Auatomation Action Choose to HA Form

* remove log

* Remove Import

* Replace checkboxes in list items with `check-list-item` (#11610)

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

* Make textarea grow on input (#11618)

* Update lit-virtualizer (#11623)

* Convert time inputs to Lit + mwc (#11609)

* Set initial focus for device, area, and entity dialogs (#11622)

* Add aria-label to table headers with no title (#11503)

* Add loadCardHelpers to cast scope (#11616)

* Update code editor to material 3 look (#11628)

* Set button role on button card and handle enter and space (#11627)

* Only load ha-selector when needed (#11630)

* Fix service control for older browsers (#11629)

* Migrate a bunch of paper-dropdowns (#11626)

* Merged too fast for Bram :) Code improv (#11632)

* Add support for opening camera media source (#11633)

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

* Create error when trying to backup wile system in freeze (#11634)

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

* Add missing type to create device automation/script heading (#11635)

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

* Generate random webhook_id and add copy button (#11568)

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

* Migrate search bar to mwc (#11637)

* fix data-table row handlers (#11638)

* Bunch of fixes and cleanup (#11636)

* State Trigger -> HA Form (#11631)

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

* Allow uploading media (#11615)

* Allow uploading media

* Update path

* Use current item we already have

* Update src/panels/media-browser/ha-panel-media-browser.ts

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

* Use alert dialog and use button for add media

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

* Add Attribute Picker as a selector - add to state trigger (#11641)

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

* Time Pattern to HA Form (#11648)

* MQTT Trigger to Ha-Form (#11643)

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

* Convert Sun to Ha Form (#11647)

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

* Geo Location Trigger to HA - Form (#11644)

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

* HA Trigger to HA Form (#11645)

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

* Make HA Form set required to false for selectors (#11649)

* Fix Lovelace Empty Menu when not advanced or admin (#11660)

* Add support for media player assumed state (#11642)

* Improve search and filters on mobile + fix close button in search field (#11662)

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

* Allow adding Zigbee/Zwave device (#11650)

* Numerical State to HA-Form (#11646)

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

* Filter fixes (#11664)

* Add WORKSPACE_DIRECTORY environment variable to devcontainer and script.core (#11477)

Co-authored-by: Joakim Sørensen <hi@ludeeus.dev>

* hotfix history view on missing state (#11663)

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

* Improve robustness of hls media player (#11672)

* Revert compute state display show empty string as unknown (#11677)

* Set initial focus for some more dialogs (#11676)

* Limit types of media that can be uploaded to local media (#11683)

* Don't show toggle always on more info (#11640)

* Add TTS to media browser (#11679)

* Omit Device info and actions for connected controller nodes (#11673)

* Script Editor to Ha Form (#11601)

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

* Another round of paper-dropdown -> mwc-select conversion (#11674)

* Another round of paper-dropdown -> mwc-select conversion

* ha-pick-language-row -> Lit

* Update hui-view-editor.ts

* Cleanup imports

* hassio

* Add explicit imports

* hassio fixes (#11688)

* Dont exclude domain for area and device (#11689)

* Try to keep the browsing stack when changing players in media panel (#11681)

* Allow uploading multiple files (#11687)

* Bumped version to 20220214.0

* Group helpers not in an area in a single card (#11690)

* Improve `stripPrefixFromEntityName` to handle colon and space separator (#11691)

* Display transmitted messages in MQTT debug info dialog (#11531)

* Latest paper-dropdown -> mwc-select conversion (#11692)

* This adds back mobile click accessibility (#11693)

* Updated text part 2 (#11686)

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

* Set initial focus for lovelace dialogs (#11667)

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

* Migrate all lovelace elements to mwc (#11695)

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

* Fix import

* Clean up some imports (#11696)

* Convert triple dots to single char in translations (#11697)

* Fixes remote icon state color (#11698)

* Convert scene action to service call (#11705)

* Convert scene action to service call

* fix describeAction

* rename to metadata

* Update script.ts

* Fix mode selection in automation editor (#11707)

* Remove duplicate gallery page (#11711)

* Add bottom padding to config links list with safe-area-inset-bottom (#11704)

* Bump hls.js to v1.1.5 (#11712)

* Make zwave_js config panel inclusion state aware (#11556)

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

* Fix mwc-select in lovelace editors (#11708)

* Add signed add-on capability and adjust max rating (#11703)

* Add support for removing config entry from a device

* Tweak

* Fix lint error

* Tweak

* Prettier

* Add play media action (#11702)

Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>

* Debounce refresh the cloud status if Google events happen (#11721)

* Remove custom MQTT delete device button (#11724)

* Apply suggestions from code review

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

* Update src/panels/config/devices/ha-config-device-page.ts

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

* Correct typing

* Prettier

* Remove useless Array.isArray check

* Remove custom Tasmota delete device button (#11725)

* Automation Conditions to conversion to ha-form or mwc (#11727)

* Set initial focus for energy dialogs (#11730)

* Entity Settings Page to MWC 3 (#11694)

* Show why relayer is reconnecting (#11732)

* Change words for trigger condition (#11733)

* Update media player more info (#11734)

* Pass hass to ha-form to enable selectors (#11739)

* Bumped version to 20220220.0

* Add link to the selector docs

* TTS form no longer showed due to import oopsie (#11742)

* Improve logo rendering for playing media in browser (#11741)

* Fix media upload on iOS (#11740)

* Handle inifinity media duration (#11749)

* Show when media is being loaded (#11750)

* Lovelace Entity Card Editor to Ha Form - Adds Theme Selector and HaFormColumn (#11731)

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

* Set initial focus for supervisor dialogs (#11710)

* Convert Automation Actions to mwc/ha-form + other automation items (#11753)

* Selector: remove text value when not required and empty (#11754)

* Convert date-range-picker to mwc (#11755)

* Radio Browser is now added during onboarding (#11756)

* Add support for the media browser My link (#11757)

* Show Home Assistant when creating partial backup (#11758)

* Fix zwave migration (#11751)

* Allow config entries to be reloaded when they are in setup_retry state (#11759)

* Area Card Editor to Ha Form (#11762)

* Fix WebRTC player stream playback when disconnected/connected (#11764)

* set theme to undefined when no theme (#11765)

* Paper input migrations (#11766)

* Only show description when set (#11772)

* Thermostat Editor to HA - Form (#11763)

* Thermostat - Ha Form

* Update hui-thermostat-card-editor.ts

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

* Alarm Card Editor to HA Form (#11760)

* Move to ha-form

* Update hui-alarm-panel-card-editor.ts

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

* Change icons for cover with device_class curtain (#11752)

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

* no need for memoize

* Include scoped custom element polyfill (#11776)

* Show triggered in automation editor (#11771)

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

* Allow changing volume media player entity (#11781)

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

* Add community section (#11779)

* Bumped version to 20220222.0

* Fix State Condition 'For' Data (#11782)

* entities card editor to MWC (#11785)

* Fix ripple corner radius for button card (#11780)

* Condition Card Editor to MWC (#11783)

* Show number of hidden items (#11786)

* Put volume slider in the middle of the button (#11788)

* Add media management dialog (#11787)

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

* Convert alarm control panel more info (#11791)

* Convert alarm control panel more info

* Update more-info-alarm_control_panel.ts

* Update src/dialogs/more-info/controls/more-info-alarm_control_panel.ts

* Apply suggestions from code review

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

* import

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

* Migrate more-info configurator (#11792)

* Migrate more-info configurator

* Update more-info-configurator.ts

* Update src/dialogs/more-info/controls/more-info-configurator.ts

* Update src/dialogs/more-info/controls/more-info-configurator.ts

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

* Import

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

* Convert more info lock (#11794)

* Add Margin to Tip (#11790)

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

* Dont render double label on number selector (#11796)

* Input conversion in dev tools (#11795)

* Gauge Editor to Ha Form (#11793)

* Stop spinning when opening media in dialog (#11800)

* Fix Entities picker (#11802)

* Migrate single textfields (#11799)

* Migrate single textfields

* Update ha-config-name-form.ts

* Update dialog-area-registry-detail.ts

* Update manual-automation-editor.ts

* Update manual-automation-editor.ts

* required to number selector fix script

* review

* change repository url and project description (#11801)

* Calendar card to HA Form (#11784)

* Graph Footer to MWC (#11803)

* History Graph Editor to ha form (#11797)

* Glance editor to ha-form (#11804)

* Grid Card to HA Form (#11798)

* Button editor to ha-form (#11808)

* Bumped version to 20220223.0

* mwc-select -> ha-select (#11806)

Co-authored-by: Yosi Levy <yosilevy@gmail.com>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: Yosi Levy <37745463+yosilevy@users.noreply.github.com>
Co-authored-by: Kuba Wolanin <hi@kubawolanin.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Zack Barett <arnett.zackary@gmail.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Zack <zackbarett@hey.com>
Co-authored-by: Joakim Sørensen <ludeeus@ludeeus.dev>
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com>
Co-authored-by: Patrick ZAJDA <patrick@zajda.fr>
Co-authored-by: Thomas Lovén <thomasloven@gmail.com>
Co-authored-by: Eric Severance <esev@esev.com>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
Co-authored-by: Shay Levy <levyshay1@gmail.com>
Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>
Co-authored-by: Joakim Sørensen <hi@ludeeus.dev>
Co-authored-by: lintaba <lintaba@gmail.com>
Co-authored-by: Allen Porter <allen@thebends.org>
Co-authored-by: kpine <keith.pine@gmail.com>
Co-authored-by: Brandon Rothweiler <brandonrothweiler@gmail.com>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
Co-authored-by: Matthias de Baat <matthias.debaat@nabucasa.com>
Co-authored-by: Philip Allgaier <mail@spacegaier.de>
Co-authored-by: Josh McCarty <josh@joshmccarty.com>
Co-authored-by: uvjustin <46082645+uvjustin@users.noreply.github.com>
Co-authored-by: Raman Gupta <7243222+raman325@users.noreply.github.com>
Co-authored-by: Pascal Winters <pascal@famwinters.com>
Co-authored-by: Robin Wittebol <robinwittebol@live.nl>
Co-authored-by: Tomasz <t.jagusz@gmail.com>
2022-02-23 11:11:41 -08:00
Bram Kragten
1719d062b3 mwc-select -> ha-select (#11806) 2022-02-23 18:59:36 +00:00
Bram Kragten
87290c4330 Merge branch 'master' into dev 2022-02-23 19:52:13 +01:00
Bram Kragten
fec0dc0032 Bumped version to 20220223.0 2022-02-23 19:51:07 +01:00
Zack Barett
70ca27c8c9 Button editor to ha-form (#11808) 2022-02-23 19:49:15 +01:00
Zack Barett
9ae1f01ad6 Grid Card to HA Form (#11798) 2022-02-23 18:51:40 +01:00
Zack Barett
0113cc3cf6 Glance editor to ha-form (#11804) 2022-02-23 09:48:18 -08:00
Zack Barett
2a98ace0b3 History Graph Editor to ha form (#11797) 2022-02-23 17:15:17 +00:00
Zack Barett
5f69a4c165 Graph Footer to MWC (#11803) 2022-02-23 17:31:33 +01:00
Zack Barett
8db22d4f88 Calendar card to HA Form (#11784) 2022-02-23 17:28:49 +01:00
Tomasz
3204dbfc4d change repository url and project description (#11801) 2022-02-23 17:27:23 +01:00
Bram Kragten
430b47fc4a Migrate single textfields (#11799)
* Migrate single textfields

* Update ha-config-name-form.ts

* Update dialog-area-registry-detail.ts

* Update manual-automation-editor.ts

* Update manual-automation-editor.ts

* required to number selector fix script

* review
2022-02-23 17:27:03 +01:00
Zack Barett
5d8b3227f3 Fix Entities picker (#11802) 2022-02-23 16:18:56 +00:00
Bram Kragten
b341ee9d38 Stop spinning when opening media in dialog (#11800) 2022-02-23 16:13:09 +01:00
Zack Barett
e6dbbc31a8 Gauge Editor to Ha Form (#11793) 2022-02-23 15:35:58 +01:00
Bram Kragten
0010bf5a8f Input conversion in dev tools (#11795) 2022-02-23 15:24:00 +01:00
Bram Kragten
6e2e80a297 Dont render double label on number selector (#11796) 2022-02-23 07:52:52 -06:00
Zack Barett
aa9ff01030 Add Margin to Tip (#11790)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-23 14:32:50 +01:00
Bram Kragten
7f8ecf57d7 Convert more info lock (#11794) 2022-02-23 07:09:13 -06:00
Bram Kragten
6be6755f6f Migrate more-info configurator (#11792)
* Migrate more-info configurator

* Update more-info-configurator.ts

* Update src/dialogs/more-info/controls/more-info-configurator.ts

* Update src/dialogs/more-info/controls/more-info-configurator.ts

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

* Import

Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-02-23 14:02:19 +01:00
Bram Kragten
64459a06c6 Convert alarm control panel more info (#11791)
* Convert alarm control panel more info

* Update more-info-alarm_control_panel.ts

* Update src/dialogs/more-info/controls/more-info-alarm_control_panel.ts

* Apply suggestions from code review

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

* import

Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-02-23 14:01:44 +01:00
Paulus Schoutsen
df35496c6e Add media management dialog (#11787)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-23 05:43:49 -06:00
Bram Kragten
aa988c758d Put volume slider in the middle of the button (#11788) 2022-02-23 04:34:06 -06:00
Paulus Schoutsen
1dd1095d19 Show number of hidden items (#11786) 2022-02-23 04:31:46 -06:00
Zack Barett
7e68393c84 Condition Card Editor to MWC (#11783) 2022-02-23 09:42:06 +01:00
Robin Wittebol
540c06c9f7 Fix ripple corner radius for button card (#11780) 2022-02-22 21:18:20 -08:00
Zack Barett
f633cc2b0d entities card editor to MWC (#11785) 2022-02-22 21:16:54 -08:00
Zack Barett
1baaf76471 Fix State Condition 'For' Data (#11782) 2022-02-22 23:22:04 +00:00
Paulus Schoutsen
8263e299a8 Bumped version to 20220222.0 2022-02-22 15:03:52 -08:00
Zack Barett
ebd6a26554 Add community section (#11779) 2022-02-22 23:03:37 +00:00
Paulus Schoutsen
5335772a7a Allow changing volume media player entity (#11781)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2022-02-22 14:51:25 -08:00
Paulus Schoutsen
f5b5414461 Show triggered in automation editor (#11771)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-22 23:03:32 +01:00
Bram Kragten
1e6f402d0f Include scoped custom element polyfill (#11776) 2022-02-22 09:32:56 -08:00
Bram Kragten
ed9d886009 no need for memoize 2022-02-22 13:38:44 +01:00
Pascal Winters
940f5c0002 Change icons for cover with device_class curtain (#11752)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-22 13:33:08 +01:00
Zack Barett
15d1b8b2ac Alarm Card Editor to HA Form (#11760)
* Move to ha-form

* Update hui-alarm-panel-card-editor.ts

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-22 11:00:13 +01:00
Zack Barett
73855e6f99 Thermostat Editor to HA - Form (#11763)
* Thermostat - Ha Form

* Update hui-thermostat-card-editor.ts

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-22 10:56:04 +01:00
Paulus Schoutsen
d230541256 Only show description when set (#11772) 2022-02-22 09:57:56 +01:00
Bram Kragten
b1f369a355 Paper input migrations (#11766) 2022-02-21 23:09:13 +01:00
Bram Kragten
e6d1e86c64 set theme to undefined when no theme (#11765) 2022-02-21 15:56:10 -06:00
Allen Porter
eb1f94c370 Fix WebRTC player stream playback when disconnected/connected (#11764) 2022-02-21 20:35:37 +00:00
Zack Barett
27750b8b5d Area Card Editor to Ha Form (#11762) 2022-02-21 13:21:21 -06:00
J. Nick Koston
564a725284 Allow config entries to be reloaded when they are in setup_retry state (#11759) 2022-02-21 10:52:59 -08:00
Bram Kragten
a5ee610af5 Fix zwave migration (#11751) 2022-02-21 10:52:09 -08:00
Joakim Sørensen
eaf97ee7f5 Show Home Assistant when creating partial backup (#11758) 2022-02-21 09:33:02 -08:00
Paulus Schoutsen
a14d75deec Add support for the media browser My link (#11757) 2022-02-21 11:21:29 -06:00
Paulus Schoutsen
72b5721c88 Radio Browser is now added during onboarding (#11756) 2022-02-21 09:12:15 -08:00
Bram Kragten
94b4b818aa Convert date-range-picker to mwc (#11755) 2022-02-21 16:48:31 +00:00
Bram Kragten
98699b640a Selector: remove text value when not required and empty (#11754) 2022-02-21 16:37:29 +00:00
Zack Barett
decc0d3e0d Convert Automation Actions to mwc/ha-form + other automation items (#11753) 2022-02-21 16:37:11 +00:00
Steve Repsher
2281f5bafa Set initial focus for supervisor dialogs (#11710) 2022-02-21 17:02:55 +01:00
Zack Barett
6cac7eeff0 Lovelace Entity Card Editor to Ha Form - Adds Theme Selector and HaFormColumn (#11731)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-21 16:53:03 +01:00
Erik Montnemery
794bc161c8 Merge pull request #11716 from emontnemery/remove_config_entry_from_device
Add support for removing config entry from a device
2022-02-21 12:36:07 +00:00
Paulus Schoutsen
28cd9b6408 Show when media is being loaded (#11750) 2022-02-21 09:55:01 +01:00
Paulus Schoutsen
9b4c6eea63 Handle inifinity media duration (#11749) 2022-02-21 04:07:10 +00:00
Paulus Schoutsen
41ec65ef3d Merge pull request #11729 from home-assistant/20220203.1 2022-02-18 11:11:24 -08:00
Bram Kragten
79e1e195a0 Fix service control for older browsers (#11629) 2022-02-18 10:51:29 -08:00
Paulus Schoutsen
dfbf7fb436 Revert compute state display show empty string as unknown (#11677) 2022-02-18 10:51:29 -08:00
lintaba
f37a5fa021 hotfix history view on missing state (#11663)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2022-02-18 10:51:29 -08:00
Paulus Schoutsen
5e2fcf928c Bumped version to 20220203.1 2022-02-18 10:50:01 -08:00
Erik
bc6ef7780c Remove useless Array.isArray check 2022-02-18 16:49:23 +01:00
Erik
b29563a254 Prettier 2022-02-18 16:41:18 +01:00
Erik
fe8a1152c4 Correct typing 2022-02-18 16:36:15 +01:00
Erik Montnemery
26689a0a85 Update src/panels/config/devices/ha-config-device-page.ts
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-18 16:21:11 +01:00
Erik Montnemery
4f6a241817 Apply suggestions from code review
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2022-02-18 15:57:57 +01:00
Erik
246724c59e Prettier 2022-02-18 09:13:18 +01:00
Erik
8f5c9295d3 Tweak 2022-02-18 08:48:53 +01:00
Erik
0abafff4c9 Fix lint error 2022-02-18 08:26:37 +01:00
Erik
f88ce269a7 Tweak 2022-02-17 17:12:17 +01:00
Erik
0dc56d7983 Add support for removing config entry from a device 2022-02-17 16:46:08 +01:00
Paulus Schoutsen
35a41b3490 Use same help icon everywhere 2022-02-11 08:35:29 -08:00
Paulus Schoutsen
f59cb661cd Add a docs icon to the config flow dialog 2022-02-10 14:27:38 -08:00
Bram Kragten
51938fb51f 20220203.0 (#11533)
* Only upload wheels to PyPI (#11514)

* Make sure we load data in update card (#11516)

* Guard load diagnostics (#11518)

* Design home - Fix GitHub Links (#11519)

* Add filtering to system log card and error log card (#11166)

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

* Handle unknown toggle state (#11522)

* Fix dialog heading aria label (#11524)

Co-authored-by: Zack Barett <arnett.zackary@gmail.com>

* Use css to hide hint in quickbar (#11527)

* Revert "Mobile click accessibility" (#11526)

* Clear old src when disconnected so we can't fetch it with the wrong t… (#11528)

* Add name of integration to diagnostics when more than 1 (#11523)

* Bumped version to 20220203.0

Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: fpro1212 <75439345+fpro1212@users.noreply.github.com>
Co-authored-by: Kuba Wolanin <hi@kubawolanin.com>
Co-authored-by: Zack Barett <arnett.zackary@gmail.com>
2022-02-03 20:52:49 +01:00
Bram Kragten
c85236e251 Merge pull request #11512 from home-assistant/dev 2022-02-02 14:47:08 +01:00
514 changed files with 20360 additions and 17891 deletions

View File

@@ -10,10 +10,18 @@ env:
NODE_VERSION: 14
NODE_OPTIONS: --max_old_space_size=6144
# Set default workflow permissions
# All scopes not mentioned here are set to no access
# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
permissions:
actions: none
jobs:
release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write # Required to upload release assets
steps:
- name: Checkout the repository
uses: actions/checkout@v2
@@ -47,6 +55,13 @@ jobs:
script/release
- name: Upload release assets
uses: softprops/action-gh-release@v0.1.14
with:
files: |
dist/*.whl
dist/*.tar.gz
wheels-init:
name: Init wheels build
needs: release

File diff suppressed because one or more lines are too long

785
.yarn/releases/yarn-3.2.0.cjs vendored Executable file

File diff suppressed because one or more lines are too long

View File

@@ -6,4 +6,4 @@ plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"
yarnPath: .yarn/releases/yarn-3.0.2.cjs
yarnPath: .yarn/releases/yarn-3.2.0.cjs

View File

@@ -2,7 +2,7 @@
This is the repository for the official [Home Assistant](https://home-assistant.io) frontend.
[![Screenshot of the frontend](https://raw.githubusercontent.com/home-assistant/home-assistant-polymer/master/docs/screenshot.png)](https://demo.home-assistant.io/)
[![Screenshot of the frontend](https://raw.githubusercontent.com/home-assistant/frontend/master/docs/screenshot.png)](https://demo.home-assistant.io/)
- [View demo of Home Assistant](https://demo.home-assistant.io/)
- [More information about Home Assistant](https://home-assistant.io)

View File

@@ -3,7 +3,7 @@
const gulp = require("gulp");
const fs = require("fs");
const path = require("path");
const marked = require("marked");
const { marked } = require("marked");
const glob = require("glob");
const yaml = require("js-yaml");

View File

@@ -7,7 +7,7 @@ const source = require("vinyl-source-stream");
const vinylBuffer = require("vinyl-buffer");
const gulp = require("gulp");
const fs = require("fs");
const foreach = require("gulp-foreach");
const flatmap = require("gulp-flatmap");
const merge = require("gulp-merge-json");
const rename = require("gulp-rename");
const transform = require("gulp-json-transform");
@@ -183,7 +183,7 @@ gulp.task("build-merged-translations", () =>
})
.pipe(transform((data, file) => lokaliseTransform(data, data, file)))
.pipe(
foreach((stream, file) => {
flatmap((stream, file) => {
// For each language generate a merged json file. It begins with the master
// translation as a failsafe for untranslated strings, and merges all parent
// tags into one file for each specific subtag

View File

@@ -3,10 +3,10 @@ const webpack = require("webpack");
const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
const paths = require("./paths.js");
const bundle = require("./bundle.js");
const log = require("fancy-log");
const WebpackBar = require("webpackbar");
const paths = require("./paths.js");
const bundle = require("./bundle.js");
class LogStartCompilePlugin {
ignoredFirst = false;
@@ -138,6 +138,8 @@ const createWebpackConfig = ({
"lit/directives/cache$": "lit/directives/cache.js",
"lit/directives/repeat$": "lit/directives/repeat.js",
"lit/polyfill-support$": "lit/polyfill-support.js",
"@lit-labs/virtualizer/layouts/grid":
"@lit-labs/virtualizer/layouts/grid.js",
},
},
output: {

View File

@@ -1,5 +1,5 @@
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { customElement, property, query } from "lit/decorators";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { LovelaceConfig } from "../../../../src/data/lovelace";
import { Lovelace } from "../../../../src/panels/lovelace/types";
@@ -20,6 +20,8 @@ class HcLovelace extends LitElement {
@property() public urlPath: string | null = null;
@query("hui-view") private _huiView?: HTMLElement;
protected render(): TemplateResult {
const index = this._viewIndex;
if (index === undefined) {
@@ -78,12 +80,12 @@ class HcLovelace extends LitElement {
this.lovelaceConfig.background;
if (configBackground) {
(this.shadowRoot!.querySelector(
"hui-view"
) as HTMLElement)!.style.setProperty(
this._huiView!.style.setProperty(
"--lovelace-background",
configBackground
);
} else {
this._huiView!.style.removeProperty("--lovelace-background");
}
}
}
@@ -116,6 +118,9 @@ class HcLovelace extends LitElement {
:host > * {
flex: 1;
}
hui-view {
background: var(--lovelace-background, var(--primary-background-color));
}
`;
}
}

View File

@@ -1,4 +1,3 @@
import "web-animations-js/web-animations-next-lite.min";
import "../../../src/resources/ha-style";
import "../../../src/resources/roboto";
import "./layout/hc-lovelace";

View File

@@ -31,7 +31,7 @@ export const mockHassioSupervisor = (hass: MockHomeAssistant) => {
version_latest: "3.6.2",
update_available: false,
repository: "a0d7b954",
icon: true,
icon: false,
logo: true,
},
{

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -23,7 +23,7 @@ if [[ "${PULL_REQUEST}" == "true" ]]; then
createStatus "pending" "Building design preview" "https://app.netlify.com/sites/home-assistant-gallery/deploys/$BUILD_ID"
gulp build-gallery
if [ $? -eq 0 ]; then
createStatus "success" "Build complete" "$DEPLOY_URL"
createStatus "success" "Build complete" "$DEPLOY_PRIME_URL"
else
createStatus "error" "Build failed" "https://app.netlify.com/sites/home-assistant-gallery/deploys/$BUILD_ID"
fi

View File

@@ -36,12 +36,17 @@ module.exports = [
category: "misc",
header: "Miscelaneous",
},
{
category: "brand",
header: "Brand",
},
{
category: "user-test",
header: "User Tests",
header: "Users",
pages: ["user-types", "configuration-menu"],
},
{
category: "design.home-assistant.io",
header: "Design Documentation",
header: "About",
},
];

View File

@@ -53,13 +53,19 @@ class DemoBlackWhiteRow extends LitElement {
firstUpdated(changedProps) {
super.firstUpdated(changedProps);
applyThemesOnElement(this.shadowRoot!.querySelector(".dark"), {
default_theme: "default",
default_dark_theme: "default",
themes: {},
darkMode: true,
theme: "default",
});
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),
{
default_theme: "default",
default_dark_theme: "default",
themes: {},
darkMode: true,
theme: "default",
},
undefined,
undefined,
true
);
}
handleSubmit(ev) {

View File

@@ -78,6 +78,9 @@ class DemoCards extends LitElement {
ha-formfield {
margin-right: 16px;
}
#container {
background-color: var(--primary-background-color);
}
`;
}

View File

@@ -12,7 +12,14 @@ class PageDescription extends HaMarkdown {
if (!PAGES[this.page].description) {
return html``;
}
return html`
<div class="heading">
<div class="title">
${PAGES[this.page].metadata.title || this.page.split("/")[1]}
</div>
<div class="subtitle">${PAGES[this.page].metadata.subtitle}</div>
</div>
${until(
PAGES[this.page]
.description()
@@ -25,9 +32,22 @@ class PageDescription extends HaMarkdown {
static styles = [
HaMarkdown.styles,
css`
.heading {
padding: 16px;
border-bottom: 1px solid var(--secondary-background-color);
}
.title {
font-size: 42px;
line-height: 56px;
padding-bottom: 8px;
}
.subtitle {
font-size: 18px;
line-height: 24px;
}
.root {
max-width: 800px;
margin: 0 auto;
margin: 16px auto;
}
.root > *:first-child {
margin-top: 0;

11
gallery/src/data/text.ts Normal file
View File

@@ -0,0 +1,11 @@
export const LONG_TEXT = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc laoreet velit ut elit volutpat, eget ultrices odio lacinia. In imperdiet malesuada est, nec sagittis metus ultricies quis. Sed nisl ex, convallis porttitor ante quis, hendrerit tristique justo. Mauris pharetra venenatis augue, eu maximus sem cursus in. Quisque sed consequat risus. Suspendisse facilisis ligula a odio consectetur condimentum. Curabitur vehicula elit nec augue mollis, et volutpat massa dictum.
Nam pellentesque auctor rutrum. Suspendisse elit est, sodales vel diam nec, porttitor faucibus massa. Ut pretium ac orci eu pharetra. Praesent in nibh at magna viverra rutrum eu vitae tortor. Etiam eget sem ex. Fusce tristique odio nec lacus mattis, vitae tempor nunc malesuada. Maecenas faucibus magna vel libero maximus egestas. Vestibulum luctus semper velit, in lobortis risus tempus non. Curabitur bibendum ornare commodo. Quisque commodo neque sit amet tincidunt lacinia. Proin elementum ante velit, eu congue nulla semper quis. Pellentesque consequat vel nunc at scelerisque. Mauris sit amet venenatis diam, blandit viverra leo. Integer commodo laoreet orci.
Curabitur ipsum tortor, sodales ut augue sed, commodo porttitor libero. Pellentesque molestie vitae mi consectetur tempor. In sed lectus consequat, lobortis neque non, semper ipsum. Etiam eget ex et nibh sagittis pulvinar lacinia ac mauris. Aenean ligula eros, viverra ac nibh at, venenatis semper quam. Sed interdum ligula sit amet massa tincidunt tincidunt. Suspendisse potenti. Aliquam egestas facilisis est, sed faucibus erat scelerisque id. Duis dolor quam, viverra vitae orci euismod, laoreet pellentesque justo. Nunc malesuada non erat at ullamcorper. Mauris eget posuere odio. Vestibulum turpis nunc, pharetra eget ante in, feugiat mollis justo. Proin porttitor, diam nec vulputate pretium, tellus arcu rhoncus turpis, a blandit nisi nulla quis arcu. Nunc ac ullamcorper ligula, nec facilisis leo.
In vitae eros sollicitudin, iaculis ex eget, egestas orci. Etiam sed pretium lorem. Nam nisi enim, consectetur sit amet semper ac, semper pharetra diam. In pulvinar neque sapien, ac ullamcorper est lacinia a. Etiam tincidunt velit sed diam malesuada, eu ornare ex consectetur. Phasellus in imperdiet tellus. Sed bibendum, dui sit amet fringilla aliquet, enim odio sollicitudin lorem, vel semper turpis mauris vel mauris. Aenean congue magna ac massa cursus, in dictum orci commodo. Pellentesque mollis velit in sollicitudin tincidunt. Vestibulum et efficitur nulla.
Quisque posuere, velit sed porttitor dapibus, neque augue fringilla felis, eu luctus nisi nisl nec ipsum. Curabitur pellentesque ac lectus eget ultricies. Vestibulum est dolor, lacinia pharetra vulputate a, facilisis a magna. Nam vitae arcu nibh. Praesent finibus blandit ante, ac gravida ex mollis eget. Donec quam est, pulvinar vitae neque ut, bibendum aliquam erat. Nullam mollis arcu at sem tincidunt, in tristique lectus facilisis. Aenean ut lacus vel nisl finibus iaculis non a turpis. Integer eget ipsum ante. Donec nunc neque, vestibulum ac magna ac, posuere scelerisque dui. Pellentesque massa nibh, rhoncus id dolor quis, placerat posuere turpis. Donec aliquet augue nisi, eu finibus dui auctor et. Vestibulum eu varius lorem. Quisque lectus ante, malesuada pretium risus eget, interdum mattis enim.
`;

View File

@@ -5,6 +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 { haStyle } from "../../src/resources/styles";
import { PAGES, SIDEBAR } from "../build/import-pages";
import { dynamicElement } from "../../src/common/dom/dynamic-element-directive";
@@ -44,6 +45,10 @@ class HaGallery extends LitElement {
for (const page of group.pages!) {
const key = `${group.category}/${page}`;
const active = this._page === key;
if (!(key in PAGES)) {
console.error("Undefined page referenced in sidebar.js:", key);
continue;
}
const title = PAGES[key].metadata.title || page;
links.push(html`
<a ?active=${active} href=${`#${group.category}/${page}`}>${title}</a>
@@ -53,10 +58,9 @@ class HaGallery extends LitElement {
sidebar.push(
group.header
? html`
<details>
<summary class="section">${group.header}</summary>
<ha-expansion-panel .header=${group.header}>
${links}
</details>
</ha-expansion-panel>
`
: links
);
@@ -92,27 +96,34 @@ class HaGallery extends LitElement {
${dynamicElement(`demo-${this._page.replace("/", "-")}`)}
</div>
<div class="page-footer">
${PAGES[this._page].description ||
Object.keys(PAGES[this._page].metadata).length > 0
? html`
<a
href=${`${GITHUB_DEMO_URL}${this._page}.markdown`}
target="_blank"
>
Edit text
</a>
`
: ""}
${PAGES[this._page].demo
? html`
<a
href=${`${GITHUB_DEMO_URL}${this._page}.ts`}
target="_blank"
>
Edit demo
</a>
`
: ""}
<div class="header">Help us to improve our documentation</div>
<div class="secondary">
Suggest an edit to this page, or provide/view feedback for this
page.
</div>
<div>
${PAGES[this._page].description ||
Object.keys(PAGES[this._page].metadata).length > 0
? html`
<a
href=${`${GITHUB_DEMO_URL}${this._page}.markdown`}
target="_blank"
>
Edit text
</a>
`
: ""}
${PAGES[this._page].demo
? html`
<a
href=${`${GITHUB_DEMO_URL}${this._page}.ts`}
target="_blank"
>
Edit demo
</a>
`
: ""}
</div>
</div>
</div>
</mwc-drawer>
@@ -186,27 +197,16 @@ class HaGallery extends LitElement {
padding: 4px;
}
.sidebar details {
margin-top: 1em;
margin-left: 1em;
}
.sidebar summary {
cursor: pointer;
font-weight: bold;
margin-bottom: 8px;
}
.sidebar a {
color: var(--primary-text-color);
display: block;
padding: 4px 12px;
padding: 12px;
text-decoration: none;
position: relative;
}
.sidebar a[active]::before {
border-radius: 4px;
border-radius: 12px;
position: absolute;
top: 0;
right: 2px;
@@ -237,14 +237,32 @@ class HaGallery extends LitElement {
.page-footer {
text-align: center;
margin: 16px 0;
padding-top: 16px;
border-top: 1px solid rgba(0, 0, 0, 0.12);
margin: 16px;
padding: 16px;
border-radius: 12px;
background-color: var(--primary-background-color);
}
.page-footer div {
margin-top: 4px;
}
.page-footer .header {
font-size: 16px;
font-weight: 500;
line-height: 28px;
text-align: center;
}
.page-footer .secondary {
line-height: 23px;
text-align: center;
}
.page-footer a {
display: inline-block;
margin: 0 8px;
text-decoration: none;
}
`,
];

View File

@@ -8,7 +8,7 @@ import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
import type { Condition } from "../../../../src/data/automation";
import type { ConditionWithShorthand } from "../../../../src/data/automation";
import "../../../../src/panels/config/automation/condition/ha-automation-condition";
import { HaDeviceCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-device";
import { HaLogicalCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-logical";
@@ -20,7 +20,7 @@ import { HaTimeCondition } from "../../../../src/panels/config/automation/condit
import { HaTriggerCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-trigger";
import { HaZoneCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-zone";
const SCHEMAS: { name: string; conditions: Condition[] }[] = [
const SCHEMAS: { name: string; conditions: ConditionWithShorthand[] }[] = [
{
name: "State",
conditions: [{ condition: "state", ...HaStateCondition.defaultConfig }],
@@ -69,6 +69,14 @@ const SCHEMAS: { name: string; conditions: Condition[] }[] = [
name: "Trigger",
conditions: [{ condition: "trigger", ...HaTriggerCondition.defaultConfig }],
},
{
name: "Shorthand",
conditions: [
{ and: HaLogicalCondition.defaultConfig.conditions },
{ or: HaLogicalCondition.defaultConfig.conditions },
{ not: HaLogicalCondition.defaultConfig.conditions },
],
},
];
@customElement("demo-automation-editor-condition")

View File

@@ -0,0 +1,34 @@
---
title: "Logo"
---
![Using our logo](/images/using-our-logo.png)
# Using our logo
As a community, we are proud of our logo. Follow these guidelines to ensure it always looks its best. Our logo follows Google's material design spec and uses the blue interface color.
[Download Logo](https://github.com/home-assistant/assets/tree/master/logo)
![Logo](/images/logo.png)
## Using the icon
Our icon is a shorter and most used version of our logo. The icon can exist without the wordmark, the wordmark should never exist without the icon.
![Logo variants](/images/logo-variants.png)
## Using the right variant
The pretty blue logo with a background shadow, pictured top left, is our primary logo. It should only be used with black, white, and non-duotone photography.
When needed you can use our logo without a shadow, as seen as the second variant.
The outlined logo should only be used on packaging.
## Exclusion zone
The logo needs some personal space. It's exclusion zone is equal to a quarter the height of the icon.
![Clearspace](/images/clearspace.png)

View File

@@ -0,0 +1,41 @@
---
title: "Our story"
---
## Open source home automation that puts local control and privacy first
Home Assistant is a free and open-source software for home automation that is designed to be the central control system for smart home devices with a focus on local control and privacy. It can be accessed via a web-based user interface, via apps for Android and iOS, or using voice commands via a supported virtual assistant like Google Assistant and Amazon Alexa.
IoT devices and services are supported by modular support for controlling proprietary ecosystems if they provide public access via an Open API for third-party integrations and protocols like Bluetooth, MQTT, Zigbee, and Z-Wave, After the Home Assistant software application is installed as a computer appliance it will act as a central control system for home automation. Information from all entities it sees can be used and controlled from within scripts trigger automations using scheduling and "blueprint" subroutines, e.g. for controlling lighting, climate, entertainment systems, and appliances.
# Open Home
The Open Home is our vision for the smart home. It defines the values that we put at the heart of every decision we make at Home Assistant. Its woven into our architecture, licensing, community, and everything else.
The Open Home is about privacy, choice, and durability.
## Privacy
Your home should be your safe space. A place where you can be your true self without having to bother about what the world thinks of you. A place where you dont need to act differently to avoid an algorithm categorizing your behavior. Privacy for the Open Home means that devices need to work locally. No one else needs to know if you turn on a light bulb or change the thermostat.
It is okay for a product to offer a cloud connection, but it should be extra and opt-in.
## Choice
Devices in your home gather data about themselves and their surroundings. Your data. Vendors shouldnt be able to limit your access to your data or limit the interoperability of your devices with the rest of your smart home.
Choice for the Open Home means that devices need to make the gathered data available through local APIs. This avoids vendor lock-in and allows users to create their own smart home with devices from different manufacturers.
## Durability
If there is one thing that technology firms are very good at, it is launching new products. However, maintaining the products and making sure they keep working is an afterthought for most. The result is that vendors can decide to no longer support your device, crippling its features or even preventing it from working at all. As we install more and more devices in our home, durability is becoming more and more important. We shouldnt have to buy everything new every couple of years because the manufacturer decided to move on.
Durability for the Open Home means that devices are designed and built to keep working. Not just this year, but for the next decade.
# Our history
The project was started as a Python application by Paulus Schoutsen in September 2013 and first published publicly on GitHub in November 2013. In July 2017, a managed operating system called Hass.io was initially introduced to make it easier use to use Home Assistant on single-board computers like the Raspberry Pi series. Its bundled "supervisor" management system allowed users to manage, backup, and update the local installation and introduced the option to extend the functionality of the software with add-ons.
An optional subscription service was introduced in December 2017 for $5/month to solve the complexities associated with secured remote access, as well as linking to Amazon Alexa and Google Assistant. Nabu Casa, Inc. was formed in September 2018 to take over the subscription service. The company's funding is based solely on revenue from the subscription service. It is used to finance the project's infrastructure and to pay for full-time employees contributing to the project.
In January 2020, branding was adjusted to make it easier to refer to different parts of the project. The main piece of software was renamed to Home Assistant Core, while the full suite of software with the embedded operating system and bundled "supervisor" management system was renamed to Home Assistant.

View File

@@ -1,5 +1,6 @@
---
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.
---
# Alert `<ha-alert>`

View File

@@ -159,13 +159,19 @@ export class DemoHaAlert extends LitElement {
firstUpdated(changedProps) {
super.firstUpdated(changedProps);
applyThemesOnElement(this.shadowRoot!.querySelector(".dark"), {
default_theme: "default",
default_dark_theme: "default",
themes: {},
darkMode: true,
theme: "default",
});
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),
{
default_theme: "default",
default_dark_theme: "default",
themes: {},
darkMode: true,
theme: "default",
},
undefined,
undefined,
true
);
}
static get styles() {

View File

@@ -3,18 +3,7 @@ import { customElement } from "lit/decorators";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-faded";
import "../../../../src/components/ha-markdown";
const LONG_TEXT = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc laoreet velit ut elit volutpat, eget ultrices odio lacinia. In imperdiet malesuada est, nec sagittis metus ultricies quis. Sed nisl ex, convallis porttitor ante quis, hendrerit tristique justo. Mauris pharetra venenatis augue, eu maximus sem cursus in. Quisque sed consequat risus. Suspendisse facilisis ligula a odio consectetur condimentum. Curabitur vehicula elit nec augue mollis, et volutpat massa dictum.
Nam pellentesque auctor rutrum. Suspendisse elit est, sodales vel diam nec, porttitor faucibus massa. Ut pretium ac orci eu pharetra. Praesent in nibh at magna viverra rutrum eu vitae tortor. Etiam eget sem ex. Fusce tristique odio nec lacus mattis, vitae tempor nunc malesuada. Maecenas faucibus magna vel libero maximus egestas. Vestibulum luctus semper velit, in lobortis risus tempus non. Curabitur bibendum ornare commodo. Quisque commodo neque sit amet tincidunt lacinia. Proin elementum ante velit, eu congue nulla semper quis. Pellentesque consequat vel nunc at scelerisque. Mauris sit amet venenatis diam, blandit viverra leo. Integer commodo laoreet orci.
Curabitur ipsum tortor, sodales ut augue sed, commodo porttitor libero. Pellentesque molestie vitae mi consectetur tempor. In sed lectus consequat, lobortis neque non, semper ipsum. Etiam eget ex et nibh sagittis pulvinar lacinia ac mauris. Aenean ligula eros, viverra ac nibh at, venenatis semper quam. Sed interdum ligula sit amet massa tincidunt tincidunt. Suspendisse potenti. Aliquam egestas facilisis est, sed faucibus erat scelerisque id. Duis dolor quam, viverra vitae orci euismod, laoreet pellentesque justo. Nunc malesuada non erat at ullamcorper. Mauris eget posuere odio. Vestibulum turpis nunc, pharetra eget ante in, feugiat mollis justo. Proin porttitor, diam nec vulputate pretium, tellus arcu rhoncus turpis, a blandit nisi nulla quis arcu. Nunc ac ullamcorper ligula, nec facilisis leo.
In vitae eros sollicitudin, iaculis ex eget, egestas orci. Etiam sed pretium lorem. Nam nisi enim, consectetur sit amet semper ac, semper pharetra diam. In pulvinar neque sapien, ac ullamcorper est lacinia a. Etiam tincidunt velit sed diam malesuada, eu ornare ex consectetur. Phasellus in imperdiet tellus. Sed bibendum, dui sit amet fringilla aliquet, enim odio sollicitudin lorem, vel semper turpis mauris vel mauris. Aenean congue magna ac massa cursus, in dictum orci commodo. Pellentesque mollis velit in sollicitudin tincidunt. Vestibulum et efficitur nulla.
Quisque posuere, velit sed porttitor dapibus, neque augue fringilla felis, eu luctus nisi nisl nec ipsum. Curabitur pellentesque ac lectus eget ultricies. Vestibulum est dolor, lacinia pharetra vulputate a, facilisis a magna. Nam vitae arcu nibh. Praesent finibus blandit ante, ac gravida ex mollis eget. Donec quam est, pulvinar vitae neque ut, bibendum aliquam erat. Nullam mollis arcu at sem tincidunt, in tristique lectus facilisis. Aenean ut lacus vel nisl finibus iaculis non a turpis. Integer eget ipsum ante. Donec nunc neque, vestibulum ac magna ac, posuere scelerisque dui. Pellentesque massa nibh, rhoncus id dolor quis, placerat posuere turpis. Donec aliquet augue nisi, eu finibus dui auctor et. Vestibulum eu varius lorem. Quisque lectus ante, malesuada pretium risus eget, interdum mattis enim.
`;
import { LONG_TEXT } from "../../data/text";
const SMALL_TEXT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";

View File

@@ -1,17 +1,109 @@
/* eslint-disable lit/no-template-arrow */
import "@material/mwc-button";
import { LitElement, TemplateResult, html } from "lit";
import { html, LitElement, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators";
import { computeInitialHaFormData } from "../../../../src/components/ha-form/compute-initial-ha-form-data";
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
import "../../../../src/components/ha-form/ha-form";
import "../../components/demo-black-white-row";
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
import { computeInitialHaFormData } from "../../../../src/components/ha-form/compute-initial-ha-form-data";
import "../../../../src/components/ha-form/ha-form";
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
import { getEntity } from "../../../../src/fake_data/entity";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import { HomeAssistant } from "../../../../src/types";
import "../../components/demo-black-white-row";
const ENTITIES = [
getEntity("alarm_control_panel", "alarm", "disarmed", {
friendly_name: "Alarm",
}),
getEntity("media_player", "livingroom", "playing", {
friendly_name: "Livingroom",
}),
getEntity("media_player", "lounge", "idle", {
friendly_name: "Lounge",
supported_features: 444983,
}),
getEntity("light", "bedroom", "on", {
friendly_name: "Bedroom",
}),
getEntity("switch", "coffee", "off", {
friendly_name: "Coffee",
}),
];
const DEVICES = [
{
area_id: "bedroom",
configuration_url: null,
config_entries: ["config_entry_1"],
connections: [],
disabled_by: null,
entry_type: null,
id: "device_1",
identifiers: [["demo", "volume1"] as [string, string]],
manufacturer: null,
model: null,
name_by_user: null,
name: "Dishwasher",
sw_version: null,
hw_version: null,
via_device_id: null,
},
{
area_id: "backyard",
configuration_url: null,
config_entries: ["config_entry_2"],
connections: [],
disabled_by: null,
entry_type: null,
id: "device_2",
identifiers: [["demo", "pwm1"] as [string, string]],
manufacturer: null,
model: null,
name_by_user: null,
name: "Lamp",
sw_version: null,
hw_version: null,
via_device_id: null,
},
{
area_id: null,
configuration_url: null,
config_entries: ["config_entry_3"],
connections: [],
disabled_by: null,
entry_type: null,
id: "device_3",
identifiers: [["demo", "pwm1"] as [string, string]],
manufacturer: null,
model: null,
name_by_user: "User name",
name: "Technical name",
sw_version: null,
hw_version: null,
via_device_id: null,
},
];
const AREAS = [
{
area_id: "backyard",
name: "Backyard",
picture: null,
},
{
area_id: "bedroom",
name: "Bedroom",
picture: null,
},
{
area_id: "livingroom",
name: "Livingroom",
picture: null,
},
];
const SCHEMAS: {
title: string;
@@ -38,6 +130,8 @@ const SCHEMAS: {
select: "Select",
icon: "Icon",
media: "Media",
location: "Location",
entities: "Entities",
},
schema: [
{ name: "addon", selector: { addon: {} } },
@@ -45,6 +139,7 @@ const SCHEMAS: {
{
name: "Attribute",
selector: { attribute: { entity_id: "" } },
context: { filter_entity: "entity" },
},
{ name: "Device", selector: { device: {} } },
{ name: "Duration", selector: { duration: {} } },
@@ -52,7 +147,9 @@ const SCHEMAS: {
{ name: "target", selector: { target: {} } },
{ name: "number", selector: { number: { min: 0, max: 10 } } },
{ name: "boolean", selector: { boolean: {} } },
{ name: "time", selector: { time: {} } },
{ name: "time", required: true, selector: { time: {} } },
{ name: "datetime", required: true, selector: { datetime: {} } },
{ name: "date", required: true, selector: { date: {} } },
{ name: "action", selector: { action: {} } },
{ name: "text", selector: { text: { multiline: false } } },
{ name: "text_multiline", selector: { text: { multiline: true } } },
@@ -75,6 +172,14 @@ const SCHEMAS: {
media: {},
},
},
{
name: "location",
selector: { location: { radius: true, icon: "mdi:home" } },
},
{
name: "entities",
selector: { entity: { multiple: true } },
},
],
},
{
@@ -315,9 +420,10 @@ class DemoHaForm extends LitElement {
const hass = provideHass(this);
hass.updateTranslations(null, "en");
hass.updateTranslations("config", "en");
hass.addEntities(ENTITIES);
mockEntityRegistry(hass);
mockDeviceRegistry(hass);
mockAreaRegistry(hass);
mockDeviceRegistry(hass, DEVICES);
mockAreaRegistry(hass, AREAS);
mockHassioSupervisor(hass);
}

View File

@@ -1,20 +1,20 @@
/* eslint-disable lit/no-template-arrow */
import "@material/mwc-button";
import { LitElement, TemplateResult, css, html } from "lit";
import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators";
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
import "../../../../src/components/ha-selector/ha-selector";
import "../../../../src/components/ha-settings-row";
import { BlueprintInput } from "../../../../src/data/blueprint";
import { showDialog } from "../../../../src/dialogs/make-dialog-manager";
import { getEntity } from "../../../../src/fake_data/entity";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import { ProvideHassElement } from "../../../../src/mixins/provide-hass-lit-mixin";
import type { HomeAssistant } from "../../../../src/types";
import "../../components/demo-black-white-row";
import { BlueprintInput } from "../../../../src/data/blueprint";
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
import { getEntity } from "../../../../src/fake_data/entity";
import { ProvideHassElement } from "../../../../src/mixins/provide-hass-lit-mixin";
import { showDialog } from "../../../../src/dialogs/make-dialog-manager";
const ENTITIES = [
getEntity("alarm_control_panel", "alarm", "disarmed", {
@@ -109,7 +109,7 @@ const AREAS = [
const SCHEMAS: {
name: string;
input: Record<string, BlueprintInput | null>;
input: Record<string, (BlueprintInput & { required?: boolean }) | null>;
}[] = [
{
name: "One of each",
@@ -146,6 +146,8 @@ const SCHEMAS: {
},
boolean: { name: "Boolean", selector: { boolean: {} } },
time: { name: "Time", selector: { time: {} } },
date: { name: "Date", selector: { date: {} } },
datetime: { name: "Date Time", selector: { datetime: {} } },
action: { name: "Action", selector: { action: {} } },
text: {
name: "Text",
@@ -162,12 +164,92 @@ const SCHEMAS: {
},
},
object: { name: "Object", selector: { object: {} } },
select_radio: {
name: "Select (Radio)",
selector: {
select: { options: ["Option 1", "Option 2"], mode: "list" },
},
},
template: { name: "Template", selector: { template: {} } },
select: {
name: "Select",
selector: { select: { options: ["Option 1", "Option 2"] } },
selector: {
select: {
options: [
"Option 1",
"Option 2",
"Option 3",
"Option 4",
"Option 5",
"Option 6",
],
},
},
},
select_custom: {
name: "Select (Custom)",
selector: {
select: {
custom_value: true,
options: [
"Option 1",
"Option 2",
"Option 3",
"Option 4",
"Option 5",
"Option 6",
],
},
},
},
icon: { name: "Icon", selector: { icon: {} } },
media: { name: "Media", selector: { media: {} } },
location: { name: "Location", selector: { location: {} } },
location_radius: {
name: "Location with radius",
selector: { location: { radius: true, icon: "mdi:home" } },
},
color_temp: {
name: "Color Temperature",
selector: { color_temp: {} },
},
color_rgb: { name: "Color", selector: { color_rgb: {} } },
},
},
{
name: "Multiples",
input: {
entity: { name: "Entity", selector: { entity: { multiple: true } } },
device: { name: "Device", selector: { device: { multiple: true } } },
area: { name: "Area", selector: { area: { multiple: true } } },
select: {
name: "Select Multiple",
selector: {
select: {
multiple: true,
custom_value: true,
options: [
"Option 1",
"Option 2",
"Option 3",
"Option 4",
"Option 5",
"Option 6",
],
},
},
},
select_checkbox: {
name: "Select Multiple (Checkbox)",
required: false,
selector: {
select: {
mode: "list",
multiple: true,
options: ["Option 1", "Option 2", "Option 3", "Option 4"],
},
},
},
},
},
];
@@ -176,6 +258,14 @@ const SCHEMAS: {
class DemoHaSelector extends LitElement implements ProvideHassElement {
@state() public hass!: HomeAssistant;
@state() private _disabled = false;
@state() private _required = false;
@state() private _helper = false;
@state() private _label = true;
private data = SCHEMAS.map(() => ({}));
constructor() {
@@ -279,7 +369,7 @@ class DemoHaSelector extends LitElement implements ProvideHassElement {
can_play: true,
can_expand: false,
children_media_class: null,
thumbnail: null,
thumbnail: "https://brands.home-assistant.io/_/image/logo.png",
},
{
title: "movie.mp4",
@@ -309,6 +399,36 @@ class DemoHaSelector extends LitElement implements ProvideHassElement {
protected render(): TemplateResult {
return html`
<div class="options">
<ha-formfield label="Labels">
<ha-switch
.name=${"label"}
.checked=${this._label}
@change=${this._handleOptionChange}
></ha-switch>
</ha-formfield>
<ha-formfield label="Required">
<ha-switch
.name=${"required"}
.checked=${this._required}
@change=${this._handleOptionChange}
></ha-switch>
</ha-formfield>
<ha-formfield label="Disabled">
<ha-switch
.name=${"disabled"}
.checked=${this._disabled}
@change=${this._handleOptionChange}
></ha-switch>
</ha-formfield>
<ha-formfield label="Helper text">
<ha-switch
.name=${"helper"}
.checked=${this._helper}
@change=${this._handleOptionChange}
></ha-switch>
</ha-formfield>
</div>
${SCHEMAS.map((info, idx) => {
const data = this.data[idx];
const valueChanged = (ev) => {
@@ -331,8 +451,12 @@ class DemoHaSelector extends LitElement implements ProvideHassElement {
.hass=${this.hass}
.selector=${value!.selector}
.key=${key}
.label=${this._label ? value!.name : undefined}
.value=${data[key] ?? value!.default}
.disabled=${this._disabled}
.required=${this._required}
@value-changed=${valueChanged}
.helper=${this._helper ? "Helper text" : undefined}
></ha-selector>
</ha-settings-row>
`
@@ -344,10 +468,21 @@ class DemoHaSelector extends LitElement implements ProvideHassElement {
`;
}
private _handleOptionChange(ev) {
this[`_${ev.target.name}`] = ev.target.checked;
}
static styles = css`
ha-selector {
width: 60;
}
.options {
max-width: 800px;
margin: 16px auto;
}
.options ha-formfield {
margin-right: 16px;
}
`;
}

View File

@@ -0,0 +1,3 @@
---
title: Tips
---

View File

@@ -0,0 +1,73 @@
import { html, css, LitElement, TemplateResult } from "lit";
import { customElement } from "lit/decorators";
import "../../../../src/components/ha-tip";
import "../../../../src/components/ha-card";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
const tips: (string | TemplateResult)[] = [
"Test tip",
"Bigger test tip, with some random text just to fill up as much space as possible without it looking like I'm really trying to to that",
html`<i>Tip</i> <b>with</b> <sub>HTML</sub>`,
];
@customElement("demo-components-ha-tip")
export class DemoHaTip extends LitElement {
protected render(): TemplateResult {
return html` ${["light", "dark"].map(
(mode) => html`
<div class=${mode}>
<ha-card header="ha-tip ${mode} demo">
<div class="card-content">
${tips.map((tip) => html`<ha-tip>${tip}</ha-tip>`)}
</div>
</ha-card>
</div>
`
)}`;
}
firstUpdated(changedProps) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),
{
default_theme: "default",
default_dark_theme: "default",
themes: {},
darkMode: true,
theme: "default",
},
undefined,
undefined,
true
);
}
static get styles() {
return css`
:host {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.dark,
.light {
display: block;
background-color: var(--primary-background-color);
padding: 0 50px;
}
ha-tip {
margin-bottom: 14px;
}
ha-card {
margin: 24px auto;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"demo-components-ha-tip": DemoHaTip;
}
}

View File

@@ -2,6 +2,8 @@
title: Editing design.home-assistant.io
---
![Home Assistant Logo](/images/logo-with-text.png)
# How to edit design.home-assistant.io
All pages are stored in [the pages folder][pages-folder] on GitHub. Pages are grouped in a folder per sidebar section. Each page can contain a `<page name>.markdown` description file, a `<page name>.ts` demo file or both. If both are defined the description is rendered first. The description can contain metadata to specify the title of the page.
@@ -41,15 +43,12 @@ import { html, css, LitElement } from "lit";
import { customElement } from "lit/decorators";
import "../../../../src/components/ha-card";
@customElement("demo-user-experience-usability")
export class DemoUserExperienceUsability extends LitElement {
protected render() {
return html`
<ha-card>
<div class="card-content">
Hello world!
</div>
<div class="card-content">Hello world!</div>
</ha-card>
`;
}

View File

@@ -9,7 +9,7 @@ const CONFIGS = [
heading: "markdown-it demo",
config: `
- type: markdown
content: >
content: >-
# h1 Heading 8-)
## h2 Heading
@@ -249,6 +249,17 @@ const CONFIGS = [
::: warning
*here be dragons*
:::
### ha-alert
You can use our [\`ha-alert\`](https://design.home-assistant.io/#components/ha-alert) component in markdown content rendered in the Home Assistant Frontend.
<ha-alert alert-type="error">This is an error alert — check it out!</ha-alert>
<ha-alert alert-type="warning">This is a warning alert — check it out!</ha-alert>
<ha-alert alert-type="info">This is an info alert — check it out!</ha-alert>
<ha-alert alert-type="success">This is a success alert — check it out!</ha-alert>
<ha-alert title="Test alert">This is an alert with a title</ha-alert>
`,
},
];

View File

@@ -29,6 +29,7 @@ const createConfigEntry = (
source: "zeroconf",
state: "loaded",
supports_options: false,
supports_remove_device: false,
supports_unload: true,
disabled_by: null,
pref_disable_new_entities: false,
@@ -187,6 +188,7 @@ const createEntityRegistryEntries = (
device_id: "mock-device-id",
area_id: null,
disabled_by: null,
hidden_by: null,
entity_category: null,
entity_id: "binary_sensor.updater",
name: null,

View File

@@ -0,0 +1,3 @@
---
title: Update
---

View File

@@ -0,0 +1,189 @@
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, query } from "lit/decorators";
import "../../../../src/components/ha-card";
import {
UPDATE_SUPPORT_BACKUP,
UPDATE_SUPPORT_PROGRESS,
UPDATE_SUPPORT_INSTALL,
UPDATE_SUPPORT_RELEASE_NOTES,
} from "../../../../src/data/update";
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";
import { LONG_TEXT } from "../../data/text";
const base_attributes = {
title: "Awesome",
installed_version: "1.2.2",
latest_version: "1.2.3",
release_url: "https://home-assistant.io",
supported_features: UPDATE_SUPPORT_INSTALL,
skipped_version: null,
in_progress: false,
release_summary:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In nec metus aliquet, porta mi ut, ultrices odio. Etiam egestas orci tellus, non semper metus blandit tincidunt. Praesent elementum turpis vel tempor pharetra. Sed quis cursus diam. Proin sem justo.",
};
const ENTITIES = [
getEntity("update", "update1", "on", {
...base_attributes,
friendly_name: "Update",
}),
getEntity("update", "update2", "on", {
...base_attributes,
title: null,
friendly_name: "Update without title",
}),
getEntity("update", "update3", "on", {
...base_attributes,
release_url: null,
friendly_name: "Update without release_url",
}),
getEntity("update", "update4", "on", {
...base_attributes,
release_summary: null,
friendly_name: "Update without release_summary",
}),
getEntity("update", "update5", "off", {
...base_attributes,
installed_version: "1.2.3",
friendly_name: "No update",
}),
getEntity("update", "update6", "off", {
...base_attributes,
skipped_version: "1.2.3",
friendly_name: "Skipped version",
}),
getEntity("update", "update7", "on", {
...base_attributes,
supported_features:
base_attributes.supported_features + UPDATE_SUPPORT_BACKUP,
friendly_name: "With backup support",
}),
getEntity("update", "update8", "on", {
...base_attributes,
in_progress: true,
friendly_name: "With true in_progress",
}),
getEntity("update", "update9", "on", {
...base_attributes,
in_progress: 25,
supported_features:
base_attributes.supported_features + UPDATE_SUPPORT_PROGRESS,
friendly_name: "With 25 in_progress",
}),
getEntity("update", "update10", "on", {
...base_attributes,
in_progress: 50,
supported_features:
base_attributes.supported_features + UPDATE_SUPPORT_PROGRESS,
friendly_name: "With 50 in_progress",
}),
getEntity("update", "update11", "on", {
...base_attributes,
in_progress: 75,
supported_features:
base_attributes.supported_features + UPDATE_SUPPORT_PROGRESS,
friendly_name: "With 75 in_progress",
}),
getEntity("update", "update12", "unavailable", {
...base_attributes,
in_progress: 50,
friendly_name: "Unavailable",
}),
getEntity("update", "update13", "on", {
...base_attributes,
supported_features: 0,
friendly_name: "No install support",
}),
getEntity("update", "update14", "off", {
...base_attributes,
installed_version: null,
friendly_name: "Update without installed_version",
}),
getEntity("update", "update15", "off", {
...base_attributes,
latest_version: null,
friendly_name: "Update without latest_version",
}),
getEntity("update", "update16", "off", {
...base_attributes,
friendly_name: "Update with release notes",
supported_features:
base_attributes.supported_features + UPDATE_SUPPORT_RELEASE_NOTES,
}),
getEntity("update", "update17", "off", {
...base_attributes,
friendly_name: "Update with release notes error",
supported_features:
base_attributes.supported_features + UPDATE_SUPPORT_RELEASE_NOTES,
}),
getEntity("update", "update18", "off", {
...base_attributes,
friendly_name: "Update with release notes loading",
supported_features:
base_attributes.supported_features + UPDATE_SUPPORT_RELEASE_NOTES,
}),
getEntity("update", "update19", "on", {
...base_attributes,
friendly_name: "Update with auto update",
auto_update: true,
}),
getEntity("update", "update20", "on", {
...base_attributes,
in_progress: true,
title: undefined,
friendly_name: "Installing without title",
}),
];
@customElement("demo-more-info-update")
class DemoMoreInfoUpdate 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);
hass.mockWS(
"update/release_notes",
(msg: { type: string; entity_id: string }) => {
if (msg.entity_id === "update.update16") {
return LONG_TEXT;
}
if (msg.entity_id === "update.update17") {
return Promise.reject({
code: "error",
message: "Could not fetch release notes",
});
}
if (msg.entity_id === "update.update18") {
return undefined;
}
return null;
}
);
}
}
declare global {
interface HTMLElementTagNameMap {
"demo-more-info-update": DemoMoreInfoUpdate;
}
}

View File

@@ -0,0 +1,17 @@
---
title: "User types"
---
We have defined three user types for Home Assistant. They are a lean segmentation of users that helps us make decisions throughout the product. User types differ from traditional personas in that the segmentation criteria arent demographic and dont personify a group into a single character with a fictitious background story.
# Outgrowers
Users that outgrow big tech smart home solutions. It just needs to work with easy setup via an app.
# Tinkerers
Technoid users in home networking and development that know how to code.
# Questioner
Users who want more advanced home automation, but need support to make it work.

View File

@@ -14,7 +14,7 @@ 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/common/search/search-input";
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";
@@ -110,8 +110,6 @@ class HassioAddonStore extends LitElement {
<div class="search">
<search-input
.hass=${this.hass}
no-label-float
no-underline
.filter=${this._filter}
@value-changed=${this._filterChanged}
></search-input>

View File

@@ -1,5 +1,4 @@
import "@material/mwc-button";
import "@material/mwc-select";
import "@material/mwc-list/mwc-list-item";
import {
css,
@@ -14,6 +13,7 @@ import { stopPropagation } from "../../../../src/common/dom/stop_propagation";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-alert";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-select";
import {
HassioAddonDetails,
HassioAddonSetOptionParams,
@@ -57,7 +57,7 @@ class HassioAddonAudio extends LitElement {
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
: ""}
${this._inputDevices &&
html`<mwc-select
html`<ha-select
.label=${this.supervisor.localize(
"addon.configuration.audio.input"
)}
@@ -74,9 +74,9 @@ class HassioAddonAudio extends LitElement {
</mwc-list-item>
`
)}
</mwc-select>`}
</ha-select>`}
${this._outputDevices &&
html`<mwc-select
html`<ha-select
.label=${this.supervisor.localize(
"addon.configuration.audio.output"
)}
@@ -93,7 +93,7 @@ class HassioAddonAudio extends LitElement {
>
`
)}
</mwc-select>`}
</ha-select>`}
</div>
<div class="card-actions">
<ha-progress-button @click=${this._saveSettings}>
@@ -119,10 +119,10 @@ class HassioAddonAudio extends LitElement {
.card-actions {
text-align: right;
}
mwc-select {
ha-select {
width: 100%;
}
mwc-select:last-child {
ha-select:last-child {
margin-top: 8px;
}
`,

View File

@@ -39,7 +39,14 @@ import type { HomeAssistant } from "../../../../src/types";
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
import { hassioStyle } from "../../resources/hassio-style";
const SUPPORTED_UI_TYPES = ["string", "select", "boolean", "integer", "float"];
const SUPPORTED_UI_TYPES = [
"string",
"select",
"boolean",
"integer",
"float",
"schema",
];
const ADDON_YAML_SCHEMA = DEFAULT_SCHEMA.extend([
new Type("!secret", {
@@ -48,6 +55,8 @@ const ADDON_YAML_SCHEMA = DEFAULT_SCHEMA.extend([
}),
]);
const MASKED_FIELDS = ["password", "secret", "token"];
@customElement("hassio-addon-config")
class HassioAddonConfig extends LitElement {
@property({ attribute: false }) public addon!: HassioAddonDetails;
@@ -75,19 +84,66 @@ class HassioAddonConfig extends LitElement {
public computeLabel = (entry: HaFormSchema): string =>
this.addon.translations[this.hass.language]?.configuration?.[entry.name]
?.name ||
this.addon.translations.en?.configuration?.[entry.name].name ||
this.addon.translations.en?.configuration?.[entry.name]?.name ||
entry.name;
private _schema = memoizeOne((schema: HaFormSchema[]): HaFormSchema[] =>
// @ts-expect-error supervisor does not implement [string, string] for select.options[]
schema.map((entry) =>
entry.type === "select"
? {
...entry,
options: entry.options.map((option) => [option, option]),
}
: entry
)
public computeHelper = (entry: HaFormSchema): string =>
this.addon.translations[this.hass.language]?.configuration?.[entry.name]
?.description ||
this.addon.translations.en?.configuration?.[entry.name]?.description ||
"";
private _convertSchema = memoizeOne(
// Convert supervisor schema to selectors
(schema: Record<string, any>): HaFormSchema[] =>
schema.map((entry) =>
entry.type === "select"
? {
name: entry.name,
required: entry.required,
selector: { select: { options: entry.options } },
}
: entry.type === "string"
? entry.multiple
? {
name: entry.name,
required: entry.required,
selector: {
select: { options: [], multiple: true, custom_value: true },
},
}
: {
name: entry.name,
required: entry.required,
selector: {
text: {
type:
entry.format || MASKED_FIELDS.includes(entry.name)
? "password"
: "text",
},
},
}
: entry.type === "boolean"
? {
name: entry.name,
required: entry.required,
selector: { boolean: {} },
}
: entry.type === "schema"
? {
name: entry.name,
required: entry.required,
selector: { object: {} },
}
: entry.type === "float" || entry.type === "integer"
? {
name: entry.name,
required: entry.required,
selector: { number: { mode: "box" } },
}
: entry
)
);
private _filteredShchema = memoizeOne(
@@ -140,7 +196,8 @@ class HassioAddonConfig extends LitElement {
.data=${this._options!}
@value-changed=${this._configChanged}
.computeLabel=${this.computeLabel}
.schema=${this._schema(
.computeHelper=${this.computeHelper}
.schema=${this._convertSchema(
this._showOptional
? this.addon.schema!
: this._filteredShchema(
@@ -197,8 +254,9 @@ class HassioAddonConfig extends LitElement {
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
this._canShowSchema = !this.addon.schema!.find(
// @ts-ignore
(entry) => !SUPPORTED_UI_TYPES.includes(entry.type) || entry.multiple
(entry) =>
// @ts-ignore
!SUPPORTED_UI_TYPES.includes(entry.type)
);
this._yamlMode = !this._canShowSchema;
}

View File

@@ -1,4 +1,3 @@
import { PaperInputElement } from "@polymer/paper-input/paper-input";
import {
css,
CSSResultGroup,
@@ -8,10 +7,13 @@ import {
TemplateResult,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-alert";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-form/ha-form";
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
import {
HassioAddonDetails,
HassioAddonSetOptionParams,
@@ -24,16 +26,6 @@ import { HomeAssistant } from "../../../../src/types";
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
import { hassioStyle } from "../../resources/hassio-style";
interface NetworkItem {
description: string;
container: string;
host: number | null;
}
interface NetworkItemInput extends PaperInputElement {
container: string;
}
@customElement("hassio-addon-network")
class HassioAddonNetwork extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@@ -42,9 +34,13 @@ class HassioAddonNetwork extends LitElement {
@property({ attribute: false }) public addon!: HassioAddonDetails;
@state() private _showOptional = false;
@state() private _configHasChanged = false;
@state() private _error?: string;
@state() private _config?: NetworkItem[];
@state() private _config?: Record<string, any>;
public connectedCallback(): void {
super.connectedCallback();
@@ -56,6 +52,10 @@ class HassioAddonNetwork extends LitElement {
return html``;
}
const hasHiddenOptions = Object.keys(this._config).find(
(entry) => this._config![entry] === null
);
return html`
<ha-card
.header=${this.supervisor.localize(
@@ -63,52 +63,49 @@ class HassioAddonNetwork extends LitElement {
)}
>
<div class="card-content">
<p>
${this.supervisor.localize(
"addon.configuration.network.introduction"
)}
</p>
${this._error
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
: ""}
<table>
<tbody>
<tr>
<th>
${this.supervisor.localize(
"addon.configuration.network.container"
)}
</th>
<th>
${this.supervisor.localize(
"addon.configuration.network.host"
)}
</th>
<th>${this.supervisor.localize("common.description")}</th>
</tr>
${this._config!.map(
(item) => html`
<tr>
<td>${item.container}</td>
<td>
<paper-input
@value-changed=${this._configChanged}
placeholder=${this.supervisor.localize(
"addon.configuration.network.disabled"
)}
.value=${item.host ? String(item.host) : ""}
.container=${item.container}
no-label-float
></paper-input>
</td>
<td>${this._computeDescription(item)}</td>
</tr>
`
)}
</tbody>
</table>
<ha-form
.data=${this._config}
@value-changed=${this._configChanged}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
.schema=${this._createSchema(
this._config,
this._showOptional,
this.hass.userData?.showAdvanced || false
)}
></ha-form>
</div>
${hasHiddenOptions
? html`<ha-formfield
class="show-optional"
.label=${this.supervisor.localize(
"addon.configuration.network.show_disabled"
)}
>
<ha-switch
@change=${this._toggleOptional}
.checked=${this._showOptional}
>
</ha-switch>
</ha-formfield>`
: ""}
<div class="card-actions">
<ha-progress-button class="warning" @click=${this._resetTapped}>
${this.supervisor.localize("common.reset_defaults")}
</ha-progress-button>
<ha-progress-button @click=${this._saveTapped}>
<ha-progress-button
@click=${this._saveTapped}
.disabled=${!this._configHasChanged}
>
${this.supervisor.localize("common.save")}
</ha-progress-button>
</div>
@@ -123,50 +120,60 @@ class HassioAddonNetwork extends LitElement {
}
}
private _computeDescription = (item: NetworkItem): string =>
this.addon.translations[this.hass.language]?.network?.[item.container]
?.description ||
this.addon.translations.en?.network?.[item.container]?.description ||
item.description;
private _createSchema = memoizeOne(
(
config: Record<string, number>,
showOptional: boolean,
advanced: boolean
): HaFormSchema[] =>
(showOptional
? Object.keys(config)
: Object.keys(config).filter((entry) => config[entry] !== null)
).map((entry) => ({
name: entry,
selector: {
number: {
mode: "box",
min: 0,
max: 65535,
unit_of_measurement: advanced ? entry : undefined,
},
},
}))
);
private _computeLabel = (_: HaFormSchema): string => "";
private _computeHelper = (item: HaFormSchema): string =>
this.addon.translations[this.hass.language]?.network?.[item.name] ||
this.addon.translations.en?.network?.[item.name] ||
this.addon.network_description?.[item.name] ||
item.name;
private _setNetworkConfig(): void {
const network = this.addon.network || {};
const description = this.addon.network_description || {};
const items: NetworkItem[] = Object.keys(network).map((key) => ({
container: key,
host: network[key],
description: description[key],
}));
this._config = items.sort((a, b) => (a.container > b.container ? 1 : -1));
this._config = this.addon.network || {};
}
private async _configChanged(ev: Event): Promise<void> {
const target = ev.target as NetworkItemInput;
this._config!.forEach((item) => {
if (
item.container === target.container &&
item.host !== parseInt(String(target.value), 10)
) {
item.host = target.value ? parseInt(String(target.value), 10) : null;
}
});
private async _configChanged(ev: CustomEvent): Promise<void> {
this._configHasChanged = true;
this._config! = ev.detail.value;
}
private async _resetTapped(ev: CustomEvent): Promise<void> {
const button = ev.currentTarget as any;
button.progress = true;
const data: HassioAddonSetOptionParams = {
network: null,
};
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
this._configHasChanged = false;
const eventdata = {
success: true,
response: undefined,
path: "option",
};
button.actionSuccess();
fireEvent(this, "hass-api-called", eventdata);
if (this.addon?.state === "started") {
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
@@ -177,19 +184,21 @@ class HassioAddonNetwork extends LitElement {
"error",
extractApiErrorMessage(err)
);
button.actionError();
}
}
button.progress = false;
private _toggleOptional() {
this._showOptional = !this._showOptional;
}
private async _saveTapped(ev: CustomEvent): Promise<void> {
const button = ev.currentTarget as any;
button.progress = true;
this._error = undefined;
const networkconfiguration = {};
this._config!.forEach((item) => {
networkconfiguration[item.container] = parseInt(String(item.host), 10);
Object.entries(this._config!).forEach(([key, value]) => {
networkconfiguration[key] = value ?? null;
});
const data: HassioAddonSetOptionParams = {
@@ -198,11 +207,13 @@ class HassioAddonNetwork extends LitElement {
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
this._configHasChanged = false;
const eventdata = {
success: true,
response: undefined,
path: "option",
};
button.actionSuccess();
fireEvent(this, "hass-api-called", eventdata);
if (this.addon?.state === "started") {
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
@@ -213,8 +224,8 @@ class HassioAddonNetwork extends LitElement {
"error",
extractApiErrorMessage(err)
);
button.actionError();
}
button.progress = false;
}
static get styles(): CSSResultGroup {
@@ -232,6 +243,9 @@ class HassioAddonNetwork extends LitElement {
display: flex;
justify-content: space-between;
}
.show-optional {
padding: 16px;
}
`,
];
}

View File

@@ -2,6 +2,7 @@ import "@material/mwc-button";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../src/components/ha-alert";
import "../../../../src/components/ha-ansi-to-html";
import "../../../../src/components/ha-card";
import {
fetchHassioAddonLogs,
@@ -11,7 +12,6 @@ import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
import { haStyle } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import "../../components/hassio-ansi-to-html";
import { hassioStyle } from "../../resources/hassio-style";
@customElement("hassio-addon-logs")
@@ -40,9 +40,9 @@ class HassioAddonLogs extends LitElement {
: ""}
<div class="card-content">
${this._content
? html`<hassio-ansi-to-html
? html`<ha-ansi-to-html
.content=${this._content}
></hassio-ansi-to-html>`
></ha-ansi-to-html>`
: ""}
</div>
<div class="card-actions">

View File

@@ -1,7 +1,7 @@
import "@material/mwc-button";
import { ActionDetail } from "@material/mwc-list";
import "@material/mwc-list/mwc-list-item";
import { mdiDelete, mdiDotsVertical, mdiPlus } from "@mdi/js";
import { mdiBackupRestore, mdiDelete, mdiDotsVertical, mdiPlus } from "@mdi/js";
import {
css,
CSSResultGroup,
@@ -166,7 +166,15 @@ export class HassioBackups extends LitElement {
}
return html`
<hass-tabs-subpage-data-table
.tabs=${supervisorTabs(this.hass)}
.tabs=${atLeastVersion(this.hass.config.version, 2022, 5)
? [
{
translationKey: "panel.backups",
path: `/hassio/backups`,
iconPath: mdiBackupRestore,
},
]
: supervisorTabs(this.hass)}
.hass=${this.hass}
.localizeFunc=${this.supervisor.localize}
.searchLabel=${this.supervisor.localize("search")}
@@ -182,7 +190,9 @@ export class HassioBackups extends LitElement {
selectable
hasFab
.mainPage=${!atLeastVersion(this.hass.config.version, 2021, 12)}
back-path="/config"
back-path=${atLeastVersion(this.hass.config.version, 2022, 5)
? "/config/system"
: "/config"}
supervisor
>
<ha-button-menu

View File

@@ -1,5 +1,4 @@
import { mdiFolderUpload } from "@mdi/js";
import "@polymer/paper-input/paper-input-container";
import { html, LitElement, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators";
import { fireEvent } from "../../../src/common/dom/fire_event";

View File

@@ -1,7 +1,7 @@
import { mdiFolder, mdiHomeAssistant, mdiPuzzle } from "@mdi/js";
import { PaperInputElement } from "@polymer/paper-input/paper-input";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { customElement, property, query } from "lit/decorators";
import { atLeastVersion } from "../../../src/common/config/version";
import { formatDate } from "../../../src/common/datetime/format_date";
import { formatDateTime } from "../../../src/common/datetime/format_date_time";
@@ -32,13 +32,6 @@ interface AddonCheckboxItem extends CheckboxItem {
const _computeFolders = (folders): CheckboxItem[] => {
const list: CheckboxItem[] = [];
if (folders.includes("homeassistant")) {
list.push({
slug: "homeassistant",
name: "Home Assistant configuration",
checked: false,
});
}
if (folders.includes("ssl")) {
list.push({ slug: "ssl", name: "SSL", checked: false });
}
@@ -92,13 +85,15 @@ export class SupervisorBackupContent extends LitElement {
@property() public confirmBackupPassword = "";
@query("paper-input, ha-radio, ha-checkbox", true) private _focusTarget;
public willUpdate(changedProps) {
super.willUpdate(changedProps);
if (!this.hasUpdated) {
this.folders = _computeFolders(
this.backup
? this.backup.folders
: ["homeassistant", "ssl", "share", "media", "addons/local"]
: ["ssl", "share", "media", "addons/local"]
);
this.addons = _computeAddons(
this.backup ? this.backup.addons : this.supervisor?.supervisor.addons
@@ -109,6 +104,10 @@ export class SupervisorBackupContent extends LitElement {
}
}
public override focus() {
this._focusTarget?.focus();
}
private _localize = (string: string) =>
this.supervisor?.localize(`backup.${string}`) ||
this.localize!(`ui.panel.page-onboarding.restore.${string}`);
@@ -169,24 +168,23 @@ export class SupervisorBackupContent extends LitElement {
: ""}
${this.backupType === "partial"
? html`<div class="partial-picker">
${this.backup && this.backup.homeassistant
? html`
<ha-formfield
.label=${html`<supervisor-formfield-label
label="Home Assistant"
.iconPath=${mdiHomeAssistant}
.version=${this.backup.homeassistant}
>
</supervisor-formfield-label>`}
>
<ha-checkbox
.checked=${this.homeAssistant}
@click=${this.toggleHomeAssistant}
>
</ha-checkbox>
</ha-formfield>
`
: ""}
<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

View File

@@ -10,6 +10,7 @@ import { HomeAssistant, Route } from "../../../src/types";
import { supervisorTabs } from "../hassio-tabs";
import "./hassio-addons";
import "./hassio-update";
import "../../../src/layouts/hass-subpage";
@customElement("hassio-dashboard")
class HassioDashboard extends LitElement {
@@ -22,6 +23,31 @@ class HassioDashboard extends LitElement {
@property({ attribute: false }) public route!: Route;
protected render(): TemplateResult {
if (atLeastVersion(this.hass.config.version, 2022, 5)) {
return html`<hass-subpage
.hass=${this.hass}
.narrow=${this.narrow}
.route=${this.route}
.header=${this.supervisor.localize("panel.addons")}
>
<hassio-addons
.hass=${this.hass}
.supervisor=${this.supervisor}
></hassio-addons>
<a href="/hassio/store">
<ha-fab
.label=${this.supervisor.localize("panel.store")}
extended
class="non-tabs"
>
<ha-svg-icon
slot="icon"
.path=${mdiStorePlus}
></ha-svg-icon> </ha-fab
></a>
</hass-subpage>`;
}
return html`
<hass-tabs-subpage
.hass=${this.hass}
@@ -74,6 +100,12 @@ class HassioDashboard extends LitElement {
.content {
margin: 0 auto;
}
ha-fab.non-tabs {
position: fixed;
right: calc(16px + env(safe-area-inset-right));
bottom: calc(16px + env(safe-area-inset-bottom));
z-index: 1;
}
`,
];
}

View File

@@ -64,6 +64,7 @@ export class DialogHassioBackupUpload
.path=${mdiClose}
slot="actionItems"
dialogAction="cancel"
dialogInitialFocus
></ha-icon-button>
</ha-header-bar>
</div>

View File

@@ -92,6 +92,7 @@ class HassioBackupDialog
.backup=${this._backup}
.onboarding=${this._dialogParams.onboarding || false}
.localize=${this._dialogParams.localize}
dialogInitialFocus
>
</supervisor-backup-content>`}
${this._error

View File

@@ -61,6 +61,7 @@ class HassioCreateBackupDialog extends LitElement {
: html`<supervisor-backup-content
.hass=${this.hass}
.supervisor=${this._dialogParams.supervisor}
dialogInitialFocus
>
</supervisor-backup-content>`}
${this._error

View File

@@ -1,11 +1,11 @@
import "@material/mwc-list/mwc-list-item";
import "@material/mwc-select";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/ha-circular-progress";
import "../../../../src/components/ha-markdown";
import "../../../../src/components/ha-select";
import {
extractApiErrorMessage,
ignoreSupervisorError,
@@ -89,11 +89,12 @@ class HassioDatadiskDialog extends LitElement {
)}
<br /><br />
<mwc-select
<ha-select
.label=${this.dialogParams.supervisor.localize(
"dialog.datadisk_move.select_device"
)}
@selected=${this._select_device}
dialogInitialFocus
>
${this.devices.map(
(device) =>
@@ -101,7 +102,7 @@ class HassioDatadiskDialog extends LitElement {
>${device}</mwc-list-item
>`
)}
</mwc-select>
</ha-select>
`
: this.devices === undefined
? this.dialogParams.supervisor.localize(
@@ -111,7 +112,11 @@ class HassioDatadiskDialog extends LitElement {
"dialog.datadisk_move.no_devices"
)}
<mwc-button slot="secondaryAction" @click=${this.closeDialog}>
<mwc-button
slot="secondaryAction"
@click=${this.closeDialog}
dialogInitialFocus
>
${this.dialogParams.supervisor.localize(
"dialog.datadisk_move.cancel"
)}
@@ -156,7 +161,7 @@ class HassioDatadiskDialog extends LitElement {
haStyle,
haStyleDialog,
css`
mwc-select {
ha-select {
width: 100%;
}
ha-circular-progress {

View File

@@ -3,7 +3,7 @@ import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/common/search/search-input";
import "../../../../src/components/search-input";
import { stringCompare } from "../../../../src/common/string/compare";
import "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-expansion-panel";
@@ -80,8 +80,6 @@ class HassioHardwareDialog extends LitElement {
></ha-icon-button>
<search-input
.hass=${this.hass}
autofocus
no-label-float
.filter=${this._filter}
@value-changed=${this._handleSearchChange}
.label=${this._dialogParams.supervisor.localize(

View File

@@ -37,7 +37,10 @@ class HassioMarkdownDialog extends LitElement {
@closed=${this.closeDialog}
.heading=${createCloseHeading(this.hass, this.title)}
>
<ha-markdown .content=${this.content || ""}></ha-markdown>
<ha-markdown
.content=${this.content || ""}
dialogInitialFocus
></ha-markdown>
</ha-dialog>
`;
}

View File

@@ -119,6 +119,7 @@ export class DialogHassioNetwork
html`<mwc-tab
.id=${device.interface}
.label=${device.interface}
dialogInitialFocus
>
</mwc-tab>`
)}
@@ -315,6 +316,7 @@ export class DialogHassioNetwork
value="auto"
name="${version}method"
.checked=${this._interface![version]?.method === "auto"}
dialogInitialFocus
>
</ha-radio>
</ha-formfield>

View File

@@ -80,6 +80,7 @@ class HassioRegistriesDialog extends LitElement {
.schema=${SCHEMA}
@value-changed=${this._valueChanged}
.computeLabel=${this._computeLabel}
dialogInitialFocus
></ha-form>
<div class="action">
<mwc-button
@@ -124,7 +125,7 @@ class HassioRegistriesDialog extends LitElement {
</ha-alert>
`}
<div class="action">
<mwc-button @click=${this._addRegistry}>
<mwc-button @click=${this._addRegistry} dialogInitialFocus>
${this.supervisor.localize(
"dialog.registries.add_new_registry"
)}

View File

@@ -106,6 +106,9 @@ class HassioRepositoriesDialog extends LitElement {
</paper-item-body>
<div class="delete">
<ha-icon-button
.label=${this._dialogParams!.supervisor.localize(
"dialog.repositories.remove"
)}
.disabled=${usedRepositories.includes(repo.slug)}
.slug=${repo.slug}
.path=${usedRepositories.includes(repo.slug)
@@ -139,6 +142,7 @@ class HassioRepositoriesDialog extends LitElement {
"dialog.repositories.add"
)}
@keydown=${this._handleKeyAdd}
dialogInitialFocus
></paper-input>
<mwc-button @click=${this._addRepository}>
${this._processing

View File

@@ -1,9 +1,12 @@
// Compat needs to be first import
import "../../src/resources/compatibility";
import { setCancelSyntheticClickEvents } from "@polymer/polymer/lib/utils/settings";
import "../../src/resources/roboto";
import "../../src/resources/safari-14-attachshadow-patch";
import "./hassio-main";
setCancelSyntheticClickEvents(false);
const styleEl = document.createElement("style");
styleEl.innerHTML = `
body {

View File

@@ -121,7 +121,8 @@ export class HassioMain extends SupervisorBaseElement {
this.parentElement,
this.hass.themes,
themeName,
themeSettings
themeSettings,
true
);
}
}

View File

@@ -8,24 +8,27 @@ import { atLeastVersion } from "../../src/common/config/version";
import type { PageNavigation } from "../../src/layouts/hass-tabs-subpage";
import { HomeAssistant } from "../../src/types";
export const supervisorTabs = (hass: HomeAssistant): PageNavigation[] => [
{
translationKey: atLeastVersion(hass.config.version, 2021, 12)
? "panel.addons"
: "panel.dashboard",
path: `/hassio/dashboard`,
iconPath: atLeastVersion(hass.config.version, 2021, 12)
? mdiPuzzle
: mdiViewDashboard,
},
{
translationKey: "panel.backups",
path: `/hassio/backups`,
iconPath: mdiBackupRestore,
},
{
translationKey: "panel.system",
path: `/hassio/system`,
iconPath: mdiCogs,
},
];
export const supervisorTabs = (hass: HomeAssistant): PageNavigation[] =>
atLeastVersion(hass.config.version, 2022, 5)
? []
: [
{
translationKey: atLeastVersion(hass.config.version, 2021, 12)
? "panel.addons"
: "panel.dashboard",
path: `/hassio/dashboard`,
iconPath: atLeastVersion(hass.config.version, 2021, 12)
? mdiPuzzle
: mdiViewDashboard,
},
{
translationKey: "panel.backups",
path: `/hassio/backups`,
iconPath: mdiBackupRestore,
},
{
translationKey: "panel.system",
path: `/hassio/system`,
iconPath: mdiCogs,
},
];

View File

@@ -23,6 +23,10 @@ import {
showAlertDialog,
showConfirmationDialog,
} from "../../../src/dialogs/generic/show-dialog-box";
import {
UNHEALTHY_REASON_URL,
UNSUPPORTED_REASON_URL,
} from "../../../src/panels/config/system-health/ha-config-system-health";
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant } from "../../../src/types";
import { bytesToString } from "../../../src/util/bytes-to-string";
@@ -30,11 +34,6 @@ import { documentationUrl } from "../../../src/util/documentation-url";
import "../components/supervisor-metric";
import { hassioStyle } from "../resources/hassio-style";
const UNSUPPORTED_REASON_URL = {};
const UNHEALTHY_REASON_URL = {
privileged: "/more-info/unsupported/privileged",
};
@customElement("hassio-supervisor-info")
class HassioSupervisorInfo extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;

View File

@@ -1,16 +1,17 @@
import "../../../src/components/ha-ansi-to-html";
import "@material/mwc-button";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-alert";
import "../../../src/components/ha-card";
import "../../../src/components/ha-select";
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
import { fetchHassioLogs } from "../../../src/data/hassio/supervisor";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import "../../../src/layouts/hass-loading-screen";
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant } from "../../../src/types";
import "../components/hassio-ansi-to-html";
import { hassioStyle } from "../resources/hassio-style";
interface LogProvider {
@@ -70,7 +71,7 @@ class HassioSupervisorLog extends LitElement {
: ""}
${this.hass.userData?.showAdvanced
? html`
<mwc-select
<ha-select
.label=${this.supervisor.localize("system.log.log_provider")}
@selected=${this._setLogProvider}
.value=${this._selectedLogProvider}
@@ -82,14 +83,14 @@ class HassioSupervisorLog extends LitElement {
</mwc-list-item>
`
)}
</mwc-select>
</ha-select>
`
: ""}
<div class="card-content" id="content">
${this._content
? html`<hassio-ansi-to-html .content=${this._content}>
</hassio-ansi-to-html>`
? html`<ha-ansi-to-html .content=${this._content}>
</ha-ansi-to-html>`
: html`<hass-loading-screen no-toolbar></hass-loading-screen>`}
</div>
<div class="card-actions">
@@ -145,7 +146,7 @@ class HassioSupervisorLog extends LitElement {
pre {
white-space: pre-wrap;
}
mwc-select {
ha-select {
width: 100%;
margin-bottom: 4px;
}

View File

@@ -45,7 +45,6 @@ import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
import "../../../src/layouts/hass-loading-screen";
import "../../../src/layouts/hass-subpage";
import "../../../src/layouts/hass-tabs-subpage";
import { SUPERVISOR_UPDATE_NAMES } from "../../../src/panels/config/dashboard/ha-config-updates";
import { HomeAssistant, Route } from "../../../src/types";
import { addonArchIsSupported, extractChangelog } from "../util/addon";
@@ -55,6 +54,12 @@ declare global {
}
}
const SUPERVISOR_UPDATE_NAMES = {
core: "Home Assistant Core",
os: "Home Assistant Operating System",
supervisor: "Home Assistant Supervisor",
};
type updateType = "os" | "supervisor" | "core" | "addon";
const changelogUrl = (

View File

@@ -1,8 +1,8 @@
{
"description": "A frontend for Home Assistant using the Polymer framework",
"description": "A frontend for Home Assistant",
"repository": {
"type": "git",
"url": "https://github.com/home-assistant/home-assistant-polymer"
"url": "https://github.com/home-assistant/frontend"
},
"name": "home-assistant-frontend",
"version": "1.0.0",
@@ -46,6 +46,7 @@
"@fullcalendar/daygrid": "5.9.0",
"@fullcalendar/interaction": "5.9.0",
"@fullcalendar/list": "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",
"@material/data-table": "14.0.0-canary.261f2db59.0",
@@ -71,14 +72,13 @@
"@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.5.95",
"@mdi/svg": "6.5.95",
"@mdi/js": "6.6.95",
"@mdi/svg": "6.6.95",
"@polymer/app-layout": "^3.1.0",
"@polymer/iron-flex-layout": "^3.0.1",
"@polymer/iron-icon": "^3.0.1",
"@polymer/iron-input": "^3.0.1",
"@polymer/iron-resizable-behavior": "^3.0.1",
"@polymer/paper-dropdown-menu": "^3.2.0",
"@polymer/paper-input": "^3.2.1",
"@polymer/paper-item": "^3.0.1",
"@polymer/paper-listbox": "^3.0.1",
@@ -95,6 +95,7 @@
"@vibrant/core": "^3.2.1-alpha.1",
"@vibrant/quantizer-mmcq": "^3.2.1-alpha.1",
"@vue/web-component-wrapper": "^1.2.0",
"@webcomponents/scoped-custom-element-registry": "^0.0.5",
"@webcomponents/webcomponentsjs": "^2.2.10",
"app-datepicker": "^5.0.1",
"chart.js": "^3.3.2",
@@ -105,9 +106,10 @@
"deep-clone-simple": "^1.1.1",
"deep-freeze": "^0.0.1",
"fuse.js": "^6.0.0",
"fuzzysort": "^1.2.1",
"google-timezones-json": "^1.0.2",
"hls.js": "^1.1.5",
"home-assistant-js-websocket": "^6.0.1",
"home-assistant-js-websocket": "^7.0.3",
"idb-keyval": "^5.1.3",
"intl-messageformat": "^9.9.1",
"js-yaml": "^4.1.0",
@@ -115,7 +117,7 @@
"leaflet-draw": "^1.0.4",
"lit": "^2.1.2",
"lit-vaadin-helpers": "^0.3.0",
"marked": "^3.0.2",
"marked": "^4.0.12",
"memoize-one": "^5.2.1",
"node-vibrant": "3.2.1-alpha.1",
"proxy-polyfill": "^0.3.2",
@@ -134,13 +136,12 @@
"vis-network": "^8.5.4",
"vue": "^2.6.12",
"vue2-daterange-picker": "^0.5.1",
"web-animations-js": "^2.3.2",
"workbox-cacheable-response": "^6.1.5",
"workbox-core": "^6.1.5",
"workbox-expiration": "^6.1.5",
"workbox-precaching": "^6.1.5",
"workbox-routing": "^6.1.5",
"workbox-strategies": "^6.1.5",
"workbox-cacheable-response": "^6.4.2",
"workbox-core": "^6.4.2",
"workbox-expiration": "^6.4.2",
"workbox-precaching": "^6.4.2",
"workbox-routing": "^6.4.2",
"workbox-strategies": "^6.4.2",
"xss": "^1.0.9"
},
"devDependencies": {
@@ -169,7 +170,7 @@
"@types/js-yaml": "^4",
"@types/leaflet": "^1",
"@types/leaflet-draw": "^1",
"@types/marked": "^2",
"@types/marked": "^4",
"@types/mocha": "^8",
"@types/qrcode": "^1.4.2",
"@types/sortablejs": "^1",
@@ -196,7 +197,7 @@
"fs-extra": "^7.0.1",
"glob": "^7.2.0",
"gulp": "^4.0.2",
"gulp-foreach": "^0.1.0",
"gulp-flatmap": "^1.0.2",
"gulp-json-transform": "^0.4.6",
"gulp-merge-json": "^1.3.1",
"gulp-rename": "^2.0.0",
@@ -233,7 +234,7 @@
"webpack-dev-server": "^4.3.0",
"webpack-manifest-plugin": "^4.0.2",
"webpackbar": "^5.0.0-3",
"workbox-build": "^6.1.5"
"workbox-build": "^6.4.2"
},
"_comment": "Polymer 3.2 contained a bug, fixed in https://github.com/Polymer/polymer/pull/5569, add as patch",
"resolutions": {
@@ -253,5 +254,6 @@
"prettier": {
"trailingComma": "es5",
"arrowParens": "always"
}
},
"packageManager": "yarn@3.2.0"
}

View File

@@ -2,6 +2,6 @@
from pathlib import Path
def where():
def where() -> Path:
"""Return path to the frontend."""
return Path(__file__).parent

0
public/py.typed Normal file
View File

View File

@@ -15,7 +15,7 @@ if [ -z $(which hass) ]; then
echo "Installing Home Asstant core from dev."
python3 -m pip install --upgrade \
colorlog \
git+git://github.com/home-assistant/home-assistant.git@dev
git+https://github.com/home-assistant/home-assistant.git@dev
fi
if [ ! -d "${WD}/config" ]; then

View File

@@ -1,6 +1,6 @@
[metadata]
name = home-assistant-frontend
version = 20220220.0
version = 20220427.0
author = The Home Assistant Authors
author_email = hello@home-assistant.io
license = Apache-2.0
@@ -19,3 +19,8 @@ python_requires = >= 3.4.0
[options.packages.find]
include =
hass_frontend*
[mypy]
python_version = 3.4
show_error_codes = True
strict = True

View File

@@ -1,7 +0,0 @@
"""
Entry point for setuptools. Required for editable installs.
TODO: Remove file after updating to pip 21.3
"""
from setuptools import setup
setup()

View File

@@ -101,13 +101,19 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
this._fetchAuthProviders();
if (matchMedia("(prefers-color-scheme: dark)").matches) {
applyThemesOnElement(document.documentElement, {
default_theme: "default",
default_dark_theme: null,
themes: {},
darkMode: true,
theme: "default",
});
applyThemesOnElement(
document.documentElement,
{
default_theme: "default",
default_dark_theme: null,
themes: {},
darkMode: true,
theme: "default",
},
undefined,
undefined,
true
);
}
if (!this.redirectUri) {

View File

@@ -187,6 +187,7 @@ export const DOMAINS_WITH_MORE_INFO = [
"scene",
"sun",
"timer",
"update",
"vacuum",
"water_heater",
"weather",
@@ -200,6 +201,7 @@ export const DOMAINS_HIDE_DEFAULT_MORE_INFO = [
"input_text",
"number",
"scene",
"update",
"select",
];

View File

@@ -3,9 +3,9 @@ import type { ForDict } from "../../data/automation";
export const createDurationData = (
duration: string | number | ForDict | undefined
): HaDurationData => {
): HaDurationData | undefined => {
if (duration === undefined) {
return {};
return undefined;
}
if (typeof duration !== "object") {
if (typeof duration === "string" || isNaN(duration)) {

View File

@@ -0,0 +1,16 @@
import secondsToDuration from "./seconds_to_duration";
const DAY_IN_SECONDS = 86400;
const HOUR_IN_SECONDS = 3600;
const MINUTE_IN_SECONDS = 60;
export const UNIT_TO_SECOND_CONVERT = {
s: 1,
min: MINUTE_IN_SECONDS,
h: HOUR_IN_SECONDS,
d: DAY_IN_SECONDS,
};
export const formatDuration = (duration: string, units: string): string =>
secondsToDuration(parseFloat(duration) * UNIT_TO_SECOND_CONVERT[units]) ||
"0";

View File

@@ -31,11 +31,12 @@ export const applyThemesOnElement = (
element,
themes: HomeAssistant["themes"],
selectedTheme?: string,
themeSettings?: Partial<HomeAssistant["selectedTheme"]>
themeSettings?: Partial<HomeAssistant["selectedTheme"]>,
main?: boolean
) => {
// If there is no explicitly desired theme provided, we automatically
// If there is no explicitly desired theme provided, and the element is the main element we automatically
// use the active one from `themes`.
const themeToApply = selectedTheme || themes.theme;
const themeToApply = selectedTheme || (main ? themes.theme : undefined);
// If there is no explicitly desired dark mode provided, we automatically
// use the active one from `themes`.
@@ -47,7 +48,7 @@ export const applyThemesOnElement = (
let cacheKey = themeToApply;
let themeRules: Partial<ThemeVars> = {};
if (darkMode) {
if (themeToApply && darkMode) {
cacheKey = `${cacheKey}__dark`;
themeRules = { ...darkStyles };
}

View File

@@ -12,7 +12,7 @@ export const isNavigationClick = (e: MouseEvent) => {
const anchor = e
.composedPath()
.filter((n) => (n as HTMLElement).tagName === "A")[0] as
.find((n) => (n as HTMLElement).tagName === "A") as
| HTMLAnchorElement
| undefined;
if (

View File

@@ -29,8 +29,11 @@ import {
mdiPowerPlug,
mdiPowerPlugOff,
mdiRadioboxBlank,
mdiSmoke,
mdiSnowflake,
mdiSmokeDetector,
mdiSmokeDetectorAlert,
mdiSmokeDetectorVariant,
mdiSmokeDetectorVariantAlert,
mdiSquare,
mdiSquareOutline,
mdiStop,
@@ -52,6 +55,8 @@ export const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {
return is_off ? mdiBattery : mdiBatteryOutline;
case "battery_charging":
return is_off ? mdiBattery : mdiBatteryCharging;
case "carbon_monoxide":
return is_off ? mdiSmokeDetector : mdiSmokeDetectorAlert;
case "cold":
return is_off ? mdiThermometer : mdiSnowflake;
case "connectivity":
@@ -68,7 +73,7 @@ export const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {
case "tamper":
return is_off ? mdiCheckCircle : mdiAlertCircle;
case "smoke":
return is_off ? mdiCheckCircle : mdiSmoke;
return is_off ? mdiSmokeDetectorVariant : mdiSmokeDetectorVariantAlert;
case "heat":
return is_off ? mdiThermometer : mdiFire;
case "light":

View File

@@ -1,12 +1,19 @@
import { HassEntity } from "home-assistant-js-websocket";
import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
import { FrontendLocaleData } from "../../data/translation";
import {
updateIsInstalling,
UpdateEntity,
UPDATE_SUPPORT_PROGRESS,
} from "../../data/update";
import { formatDate } from "../datetime/format_date";
import { formatDateTime } from "../datetime/format_date_time";
import { formatTime } from "../datetime/format_time";
import { formatNumber, isNumericState } from "../number/format_number";
import { LocalizeFunc } from "../translations/localize";
import { computeStateDomain } from "./compute_state_domain";
import { supportsFeature } from "./supports-feature";
import { formatDuration, UNIT_TO_SECOND_CONVERT } from "../datetime/duration";
export const computeStateDisplay = (
localize: LocalizeFunc,
@@ -22,11 +29,27 @@ export const computeStateDisplay = (
// Entities with a `unit_of_measurement` or `state_class` are numeric values and should use `formatNumber`
if (isNumericState(stateObj)) {
// state is duration
if (
stateObj.attributes.device_class === "duration" &&
stateObj.attributes.unit_of_measurement &&
UNIT_TO_SECOND_CONVERT[stateObj.attributes.unit_of_measurement]
) {
try {
return formatDuration(
compareState,
stateObj.attributes.unit_of_measurement
);
} catch (_err) {
// fallback to default
}
}
if (stateObj.attributes.device_class === "monetary") {
try {
return formatNumber(compareState, locale, {
style: "currency",
currency: stateObj.attributes.unit_of_measurement,
minimumFractionDigits: 2,
});
} catch (_err) {
// fallback to default
@@ -130,6 +153,28 @@ export const computeStateDisplay = (
}
}
if (domain === "update") {
// When updating, and entity does not support % show "Installing"
// When updating, and entity does support % show "Installing (xx%)"
// When update available, show the version
// When the latest version is skipped, show the latest version
// When update is not available, show "Up-to-date"
// When update is not available and there is no latest_version show "Unavailable"
return compareState === "on"
? updateIsInstalling(stateObj as UpdateEntity)
? supportsFeature(stateObj, UPDATE_SUPPORT_PROGRESS)
? localize("ui.card.update.installing_with_progress", {
progress: stateObj.attributes.in_progress,
})
: localize("ui.card.update.installing")
: stateObj.attributes.latest_version
: stateObj.attributes.skipped_version ===
stateObj.attributes.latest_version
? stateObj.attributes.latest_version ??
localize("state.default.unavailable")
: localize("ui.card.update.up_to_date");
}
return (
// Return device class translation
(stateObj.attributes.device_class &&

View File

@@ -1,4 +1,4 @@
import { HassEntity } from "home-assistant-js-websocket";
import type { HassEntity } from "home-assistant-js-websocket";
import { computeDomain } from "./compute_domain";
export const computeStateDomain = (stateObj: HassEntity) =>

View File

@@ -120,6 +120,7 @@ export const computeOpenIcon = (stateObj: HassEntity): string => {
case "awning":
case "door":
case "gate":
case "curtain":
return mdiArrowExpandHorizontal;
default:
return mdiArrowUp;
@@ -131,6 +132,7 @@ export const computeCloseIcon = (stateObj: HassEntity): string => {
case "awning":
case "door":
case "gate":
case "curtain":
return mdiArrowCollapseHorizontal;
default:
return mdiArrowDown;

View File

@@ -8,9 +8,9 @@ import {
mdiCalendar,
mdiCast,
mdiCastConnected,
mdiCheckCircleOutline,
mdiClock,
mdiEmoticonDead,
mdiFlash,
mdiCloseCircleOutline,
mdiGestureTapButton,
mdiLanConnect,
mdiLanDisconnect,
@@ -18,20 +18,18 @@ import {
mdiLockAlert,
mdiLockClock,
mdiLockOpen,
mdiPackage,
mdiPackageDown,
mdiPackageUp,
mdiPowerPlug,
mdiPowerPlugOff,
mdiRestart,
mdiSleep,
mdiTimerSand,
mdiToggleSwitch,
mdiToggleSwitchOff,
mdiCheckCircleOutline,
mdiCloseCircleOutline,
mdiToggleSwitchVariant,
mdiToggleSwitchVariantOff,
mdiWeatherNight,
mdiZWave,
} from "@mdi/js";
import { HassEntity } from "home-assistant-js-websocket";
import { updateIsInstalling, UpdateEntity } from "../../data/update";
/**
* Return the icon to be used for a domain.
*
@@ -110,21 +108,11 @@ export const domainIcon = (
case "outlet":
return compareState === "on" ? mdiPowerPlug : mdiPowerPlugOff;
case "switch":
return compareState === "on" ? mdiToggleSwitch : mdiToggleSwitchOff;
return compareState === "on"
? mdiToggleSwitchVariant
: mdiToggleSwitchVariantOff;
default:
return mdiFlash;
}
case "zwave":
switch (compareState) {
case "dead":
return mdiEmoticonDead;
case "sleeping":
return mdiSleep;
case "initializing":
return mdiTimerSand;
default:
return mdiZWave;
return mdiToggleSwitchVariant;
}
case "sensor": {
@@ -149,6 +137,13 @@ export const domainIcon = (
return stateObj?.state === "above_horizon"
? FIXED_DOMAIN_ICONS[domain]
: mdiWeatherNight;
case "update":
return compareState === "on"
? updateIsInstalling(stateObj as UpdateEntity)
? mdiPackageDown
: mdiPackageUp
: mdiPackage;
}
if (domain in FIXED_DOMAIN_ICONS) {

View File

@@ -1,244 +0,0 @@
// MIT License
// Copyright (c) 2015 - present Microsoft Corporation
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// Names from https://blog.codinghorror.com/ascii-pronunciation-rules-for-programmers/
/**
* An inlined enum containing useful character codes (to be used with String.charCodeAt).
* Please leave the const keyword such that it gets inlined when compiled to JavaScript!
*/
export enum CharCode {
Null = 0,
/**
* The `\b` character.
*/
Backspace = 8,
/**
* The `\t` character.
*/
Tab = 9,
/**
* The `\n` character.
*/
LineFeed = 10,
/**
* The `\r` character.
*/
CarriageReturn = 13,
Space = 32,
/**
* The `!` character.
*/
ExclamationMark = 33,
/**
* The `"` character.
*/
DoubleQuote = 34,
/**
* The `#` character.
*/
Hash = 35,
/**
* The `$` character.
*/
DollarSign = 36,
/**
* The `%` character.
*/
PercentSign = 37,
/**
* The `&` character.
*/
Ampersand = 38,
/**
* The `'` character.
*/
SingleQuote = 39,
/**
* The `(` character.
*/
OpenParen = 40,
/**
* The `)` character.
*/
CloseParen = 41,
/**
* The `*` character.
*/
Asterisk = 42,
/**
* The `+` character.
*/
Plus = 43,
/**
* The `,` character.
*/
Comma = 44,
/**
* The `-` character.
*/
Dash = 45,
/**
* The `.` character.
*/
Period = 46,
/**
* The `/` character.
*/
Slash = 47,
Digit0 = 48,
Digit1 = 49,
Digit2 = 50,
Digit3 = 51,
Digit4 = 52,
Digit5 = 53,
Digit6 = 54,
Digit7 = 55,
Digit8 = 56,
Digit9 = 57,
/**
* The `:` character.
*/
Colon = 58,
/**
* The `;` character.
*/
Semicolon = 59,
/**
* The `<` character.
*/
LessThan = 60,
/**
* The `=` character.
*/
Equals = 61,
/**
* The `>` character.
*/
GreaterThan = 62,
/**
* The `?` character.
*/
QuestionMark = 63,
/**
* The `@` character.
*/
AtSign = 64,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
/**
* The `[` character.
*/
OpenSquareBracket = 91,
/**
* The `\` character.
*/
Backslash = 92,
/**
* The `]` character.
*/
CloseSquareBracket = 93,
/**
* The `^` character.
*/
Caret = 94,
/**
* The `_` character.
*/
Underline = 95,
/**
* The ``(`)`` character.
*/
BackTick = 96,
a = 97,
b = 98,
c = 99,
d = 100,
e = 101,
f = 102,
g = 103,
h = 104,
i = 105,
j = 106,
k = 107,
l = 108,
m = 109,
n = 110,
o = 111,
p = 112,
q = 113,
r = 114,
s = 115,
t = 116,
u = 117,
v = 118,
w = 119,
x = 120,
y = 121,
z = 122,
/**
* The `{` character.
*/
OpenCurlyBrace = 123,
/**
* The `|` character.
*/
Pipe = 124,
/**
* The `}` character.
*/
CloseCurlyBrace = 125,
/**
* The `~` character.
*/
Tilde = 126,
}

View File

@@ -1,551 +0,0 @@
/* eslint-disable no-console */
// MIT License
// Copyright (c) 2015 - present Microsoft Corporation
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import { CharCode } from "./char-code";
const _debug = false;
export interface Match {
start: number;
end: number;
}
const _maxLen = 128;
function initTable() {
const table: number[][] = [];
const row: number[] = [];
for (let i = 0; i <= _maxLen; i++) {
row[i] = 0;
}
for (let i = 0; i <= _maxLen; i++) {
table.push(row.slice(0));
}
return table;
}
function isSeparatorAtPos(value: string, index: number): boolean {
if (index < 0 || index >= value.length) {
return false;
}
const code = value.codePointAt(index);
switch (code) {
case CharCode.Underline:
case CharCode.Dash:
case CharCode.Period:
case CharCode.Space:
case CharCode.Slash:
case CharCode.Backslash:
case CharCode.SingleQuote:
case CharCode.DoubleQuote:
case CharCode.Colon:
case CharCode.DollarSign:
case CharCode.LessThan:
case CharCode.OpenParen:
case CharCode.OpenSquareBracket:
return true;
case undefined:
return false;
default:
if (isEmojiImprecise(code)) {
return true;
}
return false;
}
}
function isWhitespaceAtPos(value: string, index: number): boolean {
if (index < 0 || index >= value.length) {
return false;
}
const code = value.charCodeAt(index);
switch (code) {
case CharCode.Space:
case CharCode.Tab:
return true;
default:
return false;
}
}
function isUpperCaseAtPos(pos: number, word: string, wordLow: string): boolean {
return word[pos] !== wordLow[pos];
}
export function isPatternInWord(
patternLow: string,
patternPos: number,
patternLen: number,
wordLow: string,
wordPos: number,
wordLen: number,
fillMinWordPosArr = false
): boolean {
while (patternPos < patternLen && wordPos < wordLen) {
if (patternLow[patternPos] === wordLow[wordPos]) {
if (fillMinWordPosArr) {
// Remember the min word position for each pattern position
_minWordMatchPos[patternPos] = wordPos;
}
patternPos += 1;
}
wordPos += 1;
}
return patternPos === patternLen; // pattern must be exhausted
}
enum Arrow {
Diag = 1,
Left = 2,
LeftLeft = 3,
}
/**
* An array representing a fuzzy match.
*
* 0. the score
* 1. the offset at which matching started
* 2. `<match_pos_N>`
* 3. `<match_pos_1>`
* 4. `<match_pos_0>` etc
*/
// export type FuzzyScore = [score: number, wordStart: number, ...matches: number[]];// [number, number, number];
export type FuzzyScore = Array<number>;
export function fuzzyScore(
pattern: string,
patternLow: string,
patternStart: number,
word: string,
wordLow: string,
wordStart: number,
firstMatchCanBeWeak: boolean
): FuzzyScore | undefined {
const patternLen = pattern.length > _maxLen ? _maxLen : pattern.length;
const wordLen = word.length > _maxLen ? _maxLen : word.length;
if (
patternStart >= patternLen ||
wordStart >= wordLen ||
patternLen - patternStart > wordLen - wordStart
) {
return undefined;
}
// Run a simple check if the characters of pattern occur
// (in order) at all in word. If that isn't the case we
// stop because no match will be possible
if (
!isPatternInWord(
patternLow,
patternStart,
patternLen,
wordLow,
wordStart,
wordLen,
true
)
) {
return undefined;
}
// Find the max matching word position for each pattern position
// NOTE: the min matching word position was filled in above, in the `isPatternInWord` call
_fillInMaxWordMatchPos(
patternLen,
wordLen,
patternStart,
wordStart,
patternLow,
wordLow
);
let row: number;
let column = 1;
let patternPos: number;
let wordPos: number;
const hasStrongFirstMatch = [false];
// There will be a match, fill in tables
for (
row = 1, patternPos = patternStart;
patternPos < patternLen;
row++, patternPos++
) {
// Reduce search space to possible matching word positions and to possible access from next row
const minWordMatchPos = _minWordMatchPos[patternPos];
const maxWordMatchPos = _maxWordMatchPos[patternPos];
const nextMaxWordMatchPos =
patternPos + 1 < patternLen ? _maxWordMatchPos[patternPos + 1] : wordLen;
for (
column = minWordMatchPos - wordStart + 1, wordPos = minWordMatchPos;
wordPos < nextMaxWordMatchPos;
column++, wordPos++
) {
let score = Number.MIN_SAFE_INTEGER;
let canComeDiag = false;
if (wordPos <= maxWordMatchPos) {
score = _doScore(
pattern,
patternLow,
patternPos,
patternStart,
word,
wordLow,
wordPos,
wordLen,
wordStart,
_diag[row - 1][column - 1] === 0,
hasStrongFirstMatch
);
}
let diagScore = 0;
if (score !== Number.MAX_SAFE_INTEGER) {
canComeDiag = true;
diagScore = score + _table[row - 1][column - 1];
}
const canComeLeft = wordPos > minWordMatchPos;
const leftScore = canComeLeft
? _table[row][column - 1] + (_diag[row][column - 1] > 0 ? -5 : 0)
: 0; // penalty for a gap start
const canComeLeftLeft =
wordPos > minWordMatchPos + 1 && _diag[row][column - 1] > 0;
const leftLeftScore = canComeLeftLeft
? _table[row][column - 2] + (_diag[row][column - 2] > 0 ? -5 : 0)
: 0; // penalty for a gap start
if (
canComeLeftLeft &&
(!canComeLeft || leftLeftScore >= leftScore) &&
(!canComeDiag || leftLeftScore >= diagScore)
) {
// always prefer choosing left left to jump over a diagonal because that means a match is earlier in the word
_table[row][column] = leftLeftScore;
_arrows[row][column] = Arrow.LeftLeft;
_diag[row][column] = 0;
} else if (canComeLeft && (!canComeDiag || leftScore >= diagScore)) {
// always prefer choosing left since that means a match is earlier in the word
_table[row][column] = leftScore;
_arrows[row][column] = Arrow.Left;
_diag[row][column] = 0;
} else if (canComeDiag) {
_table[row][column] = diagScore;
_arrows[row][column] = Arrow.Diag;
_diag[row][column] = _diag[row - 1][column - 1] + 1;
} else {
throw new Error(`not possible`);
}
}
}
if (_debug) {
printTables(pattern, patternStart, word, wordStart);
}
if (!hasStrongFirstMatch[0] && !firstMatchCanBeWeak) {
return undefined;
}
row--;
column--;
const result: FuzzyScore = [_table[row][column], wordStart];
let backwardsDiagLength = 0;
let maxMatchColumn = 0;
while (row >= 1) {
// Find the column where we go diagonally up
let diagColumn = column;
do {
const arrow = _arrows[row][diagColumn];
if (arrow === Arrow.LeftLeft) {
diagColumn -= 2;
} else if (arrow === Arrow.Left) {
diagColumn -= 1;
} else {
// found the diagonal
break;
}
} while (diagColumn >= 1);
// Overturn the "forwards" decision if keeping the "backwards" diagonal would give a better match
if (
backwardsDiagLength > 1 && // only if we would have a contiguous match of 3 characters
patternLow[patternStart + row - 1] === wordLow[wordStart + column - 1] && // only if we can do a contiguous match diagonally
!isUpperCaseAtPos(diagColumn + wordStart - 1, word, wordLow) && // only if the forwards chose diagonal is not an uppercase
backwardsDiagLength + 1 > _diag[row][diagColumn] // only if our contiguous match would be longer than the "forwards" contiguous match
) {
diagColumn = column;
}
if (diagColumn === column) {
// this is a contiguous match
backwardsDiagLength++;
} else {
backwardsDiagLength = 1;
}
if (!maxMatchColumn) {
// remember the last matched column
maxMatchColumn = diagColumn;
}
row--;
column = diagColumn - 1;
result.push(column);
}
if (wordLen === patternLen) {
// the word matches the pattern with all characters!
// giving the score a total match boost (to come up ahead other words)
result[0] += 2;
}
// Add 1 penalty for each skipped character in the word
const skippedCharsCount = maxMatchColumn - patternLen;
result[0] -= skippedCharsCount;
return result;
}
function _doScore(
pattern: string,
patternLow: string,
patternPos: number,
patternStart: number,
word: string,
wordLow: string,
wordPos: number,
wordLen: number,
wordStart: number,
newMatchStart: boolean,
outFirstMatchStrong: boolean[]
): number {
if (patternLow[patternPos] !== wordLow[wordPos]) {
return Number.MIN_SAFE_INTEGER;
}
let score = 1;
let isGapLocation = false;
if (wordPos === patternPos - patternStart) {
// common prefix: `foobar <-> foobaz`
// ^^^^^
score = pattern[patternPos] === word[wordPos] ? 7 : 5;
} else if (
isUpperCaseAtPos(wordPos, word, wordLow) &&
(wordPos === 0 || !isUpperCaseAtPos(wordPos - 1, word, wordLow))
) {
// hitting upper-case: `foo <-> forOthers`
// ^^ ^
score = pattern[patternPos] === word[wordPos] ? 7 : 5;
isGapLocation = true;
} else if (
isSeparatorAtPos(wordLow, wordPos) &&
(wordPos === 0 || !isSeparatorAtPos(wordLow, wordPos - 1))
) {
// hitting a separator: `. <-> foo.bar`
// ^
score = 5;
} else if (
isSeparatorAtPos(wordLow, wordPos - 1) ||
isWhitespaceAtPos(wordLow, wordPos - 1)
) {
// post separator: `foo <-> bar_foo`
// ^^^
score = 5;
isGapLocation = true;
}
if (score > 1 && patternPos === patternStart) {
outFirstMatchStrong[0] = true;
}
if (!isGapLocation) {
isGapLocation =
isUpperCaseAtPos(wordPos, word, wordLow) ||
isSeparatorAtPos(wordLow, wordPos - 1) ||
isWhitespaceAtPos(wordLow, wordPos - 1);
}
//
if (patternPos === patternStart) {
// first character in pattern
if (wordPos > wordStart) {
// the first pattern character would match a word character that is not at the word start
// so introduce a penalty to account for the gap preceding this match
score -= isGapLocation ? 3 : 5;
}
} else if (newMatchStart) {
// this would be the beginning of a new match (i.e. there would be a gap before this location)
score += isGapLocation ? 2 : 0;
} else {
// this is part of a contiguous match, so give it a slight bonus, but do so only if it would not be a prefered gap location
score += isGapLocation ? 0 : 1;
}
if (wordPos + 1 === wordLen) {
// we always penalize gaps, but this gives unfair advantages to a match that would match the last character in the word
// so pretend there is a gap after the last character in the word to normalize things
score -= isGapLocation ? 3 : 5;
}
return score;
}
function printTable(
table: number[][],
pattern: string,
patternLen: number,
word: string,
wordLen: number
): string {
function pad(s: string, n: number, _pad = " ") {
while (s.length < n) {
s = _pad + s;
}
return s;
}
let ret = ` | |${word
.split("")
.map((c) => pad(c, 3))
.join("|")}\n`;
for (let i = 0; i <= patternLen; i++) {
if (i === 0) {
ret += " |";
} else {
ret += `${pattern[i - 1]}|`;
}
ret +=
table[i]
.slice(0, wordLen + 1)
.map((n) => pad(n.toString(), 3))
.join("|") + "\n";
}
return ret;
}
function printTables(
pattern: string,
patternStart: number,
word: string,
wordStart: number
): void {
pattern = pattern.substr(patternStart);
word = word.substr(wordStart);
console.log(printTable(_table, pattern, pattern.length, word, word.length));
console.log(printTable(_arrows, pattern, pattern.length, word, word.length));
console.log(printTable(_diag, pattern, pattern.length, word, word.length));
}
const _minWordMatchPos = initArr(2 * _maxLen); // min word position for a certain pattern position
const _maxWordMatchPos = initArr(2 * _maxLen); // max word position for a certain pattern position
const _diag = initTable(); // the length of a contiguous diagonal match
const _table = initTable();
const _arrows = <Arrow[][]>initTable();
function initArr(maxLen: number) {
const row: number[] = [];
for (let i = 0; i <= maxLen; i++) {
row[i] = 0;
}
return row;
}
function _fillInMaxWordMatchPos(
patternLen: number,
wordLen: number,
patternStart: number,
wordStart: number,
patternLow: string,
wordLow: string
) {
let patternPos = patternLen - 1;
let wordPos = wordLen - 1;
while (patternPos >= patternStart && wordPos >= wordStart) {
if (patternLow[patternPos] === wordLow[wordPos]) {
_maxWordMatchPos[patternPos] = wordPos;
patternPos--;
}
wordPos--;
}
}
export interface FuzzyScorer {
(
pattern: string,
lowPattern: string,
patternPos: number,
word: string,
lowWord: string,
wordPos: number,
firstMatchCanBeWeak: boolean
): FuzzyScore | undefined;
}
export function createMatches(score: undefined | FuzzyScore): Match[] {
if (typeof score === "undefined") {
return [];
}
const res: Match[] = [];
const wordPos = score[1];
for (let i = score.length - 1; i > 1; i--) {
const pos = score[i] + wordPos;
const last = res[res.length - 1];
if (last && last.end === pos) {
last.end = pos + 1;
} else {
res.push({ start: pos, end: pos + 1 });
}
}
return res;
}
/**
* A fast function (therefore imprecise) to check if code points are emojis.
* Generated using https://github.com/alexdima/unicode-utils/blob/master/generate-emoji-test.js
*/
export function isEmojiImprecise(x: number): boolean {
return (
(x >= 0x1f1e6 && x <= 0x1f1ff) ||
x === 8986 ||
x === 8987 ||
x === 9200 ||
x === 9203 ||
(x >= 9728 && x <= 10175) ||
x === 11088 ||
x === 11093 ||
(x >= 127744 && x <= 128591) ||
(x >= 128640 && x <= 128764) ||
(x >= 128992 && x <= 129003) ||
(x >= 129280 && x <= 129535) ||
(x >= 129648 && x <= 129750)
);
}

View File

@@ -1,52 +1,4 @@
import { fuzzyScore } from "./filter";
/**
* Determine whether a sequence of letters exists in another string,
* in that order, allowing for skipping. Ex: "chdr" exists in "chandelier")
*
* @param {string} filter - Sequence of letters to check for
* @param {ScorableTextItem} item - Item against whose strings will be checked
*
* @return {number} Score representing how well the word matches the filter. Return of 0 means no match.
*/
export const fuzzySequentialMatch = (
filter: string,
item: ScorableTextItem
) => {
let topScore = Number.NEGATIVE_INFINITY;
for (const word of item.strings) {
const scores = fuzzyScore(
filter,
filter.toLowerCase(),
0,
word,
word.toLowerCase(),
0,
true
);
if (!scores) {
continue;
}
// The VS Code implementation of filter returns a 0 for a weak match.
// But if .filter() sees a "0", it considers that a failed match and will remove it.
// So, we set score to 1 in these cases so the match will be included, and mostly respect correct ordering.
const score = scores[0] === 0 ? 1 : scores[0];
if (score > topScore) {
topScore = score;
}
}
if (topScore === Number.NEGATIVE_INFINITY) {
return undefined;
}
return topScore;
};
import fuzzysort from "fuzzysort";
/**
* An interface that objects must extend in order to use the fuzzy sequence matcher
@@ -66,18 +18,48 @@ export interface ScorableTextItem {
strings: string[];
}
type FuzzyFilterSort = <T extends ScorableTextItem>(
export type FuzzyFilterSort = <T extends ScorableTextItem>(
filter: string,
items: T[]
) => T[];
export const fuzzyFilterSort: FuzzyFilterSort = (filter, items) =>
items
export function fuzzyMatcher(search: string | null): (string) => boolean {
const scorer = fuzzyScorer(search);
return (value: string) => scorer([value]) !== Number.NEGATIVE_INFINITY;
}
export function fuzzyScorer(
search: string | null
): (values: string[]) => number {
const searchTerms = (search || "").match(/("[^"]+"|[^"\s]+)/g);
if (!searchTerms) {
return () => 0;
}
return (values) =>
searchTerms
.map((term) => {
const resultsForTerm = fuzzysort.go(term, values, {
allowTypo: true,
});
if (resultsForTerm.length > 0) {
return Math.max(...resultsForTerm.map((result) => result.score));
}
return Number.NEGATIVE_INFINITY;
})
.reduce((partial, current) => partial + current, 0);
}
export const fuzzySortFilterSort: FuzzyFilterSort = (filter, items) => {
const scorer = fuzzyScorer(filter);
return items
.map((item) => {
item.score = fuzzySequentialMatch(filter, item);
item.score = scorer(item.strings);
return item;
})
.filter((item) => item.score !== undefined)
.filter((item) => item.score !== undefined && item.score > -100000)
.sort(({ score: scoreA = 0 }, { score: scoreB = 0 }) =>
scoreA > scoreB ? -1 : scoreA < scoreB ? 1 : 0
);
};
export const defaultFuzzyFilterSort = fuzzySortFilterSort;

View File

@@ -0,0 +1,4 @@
const regexp =
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
export const isIPAddress = (input: string): boolean => regexp.test(input);

View File

@@ -7,6 +7,7 @@ export const iconColorCSS = css`
ha-state-icon[data-domain="calendar"][data-state="on"],
ha-state-icon[data-domain="camera"][data-state="streaming"],
ha-state-icon[data-domain="cover"][data-state="open"],
ha-state-icon[data-domain="device_tracker"][data-state="home"],
ha-state-icon[data-domain="fan"][data-state="on"],
ha-state-icon[data-domain="humidifier"][data-state="on"],
ha-state-icon[data-domain="light"][data-state="on"],
@@ -70,9 +71,6 @@ export const iconColorCSS = css`
}
ha-state-icon[data-domain="plant"][data-state="problem"],
ha-state-icon[data-domain="zwave"][data-state="dead"] {
color: var(--state-icon-error-color);
}
/* Color the icon if unavailable */
ha-state-icon[data-state="unavailable"] {

View File

@@ -11,7 +11,7 @@ export const debounce = <T extends any[]>(
immediate = false
) => {
let timeout: number | undefined;
return (...args: T): void => {
const debouncedFunc = (...args: T): void => {
const later = () => {
timeout = undefined;
if (!immediate) {
@@ -25,4 +25,8 @@ export const debounce = <T extends any[]>(
func(...args);
}
};
debouncedFunc.cancel = () => {
clearTimeout(timeout);
};
return debouncedFunc;
};

View File

@@ -1,4 +1,4 @@
export const promiseTimeout = (ms: number, promise: Promise<any>) => {
export const promiseTimeout = (ms: number, promise: Promise<any> | any) => {
const timeout = new Promise((_resolve, reject) => {
setTimeout(() => {
reject(`Timed out in ${ms} ms.`);

View File

@@ -0,0 +1,18 @@
import { HomeAssistant } from "../../types";
export const subscribePollingCollection = (
hass: HomeAssistant,
updateData: (hass: HomeAssistant) => void,
interval: number
) => {
let timeout;
const fetchData = async () => {
try {
await updateData(hass);
} finally {
timeout = setTimeout(() => fetchData(), interval);
}
};
fetchData();
return () => clearTimeout(timeout);
};

View File

@@ -0,0 +1,53 @@
import { HomeAssistant } from "../../types";
interface ResultCache<T> {
[entityId: string]: Promise<T> | undefined;
}
/**
* Call a function with result caching per entity.
* @param cacheKey key to store the cache on hass object
* @param cacheTime time to cache the results
* @param func function to fetch the data
* @param hass Home Assistant object
* @param entityId entity to fetch data for
* @param args extra arguments to pass to the function to fetch the data
* @returns
*/
export const timeCacheEntityPromiseFunc = async <T>(
cacheKey: string,
cacheTime: number,
func: (hass: HomeAssistant, entityId: string, ...args: any[]) => Promise<T>,
hass: HomeAssistant,
entityId: string,
...args: any[]
): Promise<T> => {
let cache: ResultCache<T> | undefined = (hass as any)[cacheKey];
if (!cache) {
cache = hass[cacheKey] = {};
}
const lastResult = cache[entityId];
if (lastResult) {
return lastResult;
}
const result = func(hass, entityId, ...args);
cache[entityId] = result;
result.then(
// When successful, set timer to clear cache
() =>
setTimeout(() => {
cache![entityId] = undefined;
}, cacheTime),
// On failure, clear cache right away
() => {
cache![entityId] = undefined;
}
);
return result;
};

View File

@@ -1,43 +1,80 @@
import { HomeAssistant } from "../../types";
interface ResultCache<T> {
[entityId: string]: Promise<T> | undefined;
interface CacheResult<T> {
result: T;
cacheKey: any;
}
/**
* Caches a result of a promise for X time. Allows optional extra validation
* check to invalidate the cache.
* @param cacheKey the key to store the cache
* @param cacheTime the time to cache the result
* @param func the function to fetch the data
* @param generateCacheKey optional function to generate a cache key based on current hass + cached result. Cache is invalid if generates a different cache key.
* @param hass Home Assistant object
* @param args extra arguments to pass to the function to fetch the data
* @returns
*/
export const timeCachePromiseFunc = async <T>(
cacheKey: string,
cacheTime: number,
func: (hass: HomeAssistant, entityId: string, ...args: any[]) => Promise<T>,
func: (hass: HomeAssistant, ...args: any[]) => Promise<T>,
generateCacheKey:
| ((hass: HomeAssistant, lastResult: T) => unknown)
| undefined,
hass: HomeAssistant,
entityId: string,
...args: any[]
): Promise<T> => {
let cache: ResultCache<T> | undefined = (hass as any)[cacheKey];
const anyHass = hass as any;
const lastResult: Promise<CacheResult<T>> | CacheResult<T> | undefined =
anyHass[cacheKey];
if (!cache) {
cache = hass[cacheKey] = {};
}
const checkCachedResult = (result: CacheResult<T>): T | Promise<T> => {
if (
!generateCacheKey ||
generateCacheKey(hass, result.result) === result.cacheKey
) {
return result.result;
}
const lastResult = cache[entityId];
anyHass[cacheKey] = undefined;
return timeCachePromiseFunc(
cacheKey,
cacheTime,
func,
generateCacheKey,
hass,
...args
);
};
// If we have a cached result, return it if it's still valid
if (lastResult) {
return lastResult;
return lastResult instanceof Promise
? lastResult.then(checkCachedResult)
: checkCachedResult(lastResult);
}
const result = func(hass, entityId, ...args);
cache[entityId] = result;
const resultPromise = func(hass, ...args);
anyHass[cacheKey] = resultPromise;
result.then(
resultPromise.then(
// When successful, set timer to clear cache
() =>
(result) => {
anyHass[cacheKey] = {
result,
cacheKey: generateCacheKey?.(hass, result),
};
setTimeout(() => {
cache![entityId] = undefined;
}, cacheTime),
anyHass[cacheKey] = undefined;
}, cacheTime);
},
// On failure, clear cache right away
() => {
cache![entityId] = undefined;
anyHass[cacheKey] = undefined;
}
);
return result;
return resultPromise;
};

View File

@@ -1,8 +1,9 @@
import "@material/mwc-button";
import type { Button } from "@material/mwc-button";
import { mdiAlertOctagram, mdiCheckBold } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, query } from "lit/decorators";
import { customElement, property, state } from "lit/decorators";
import "../ha-circular-progress";
import "../ha-svg-icon";
@customElement("ha-progress-button")
export class HaProgressButton extends LitElement {
@@ -12,38 +13,53 @@ export class HaProgressButton extends LitElement {
@property({ type: Boolean }) public raised = false;
@query("mwc-button", true) private _button?: Button;
@state() private _result?: "success" | "error";
public render(): TemplateResult {
const overlay = this._result || this.progress;
return html`
<mwc-button
?raised=${this.raised}
.disabled=${this.disabled || this.progress}
@click=${this._buttonTapped}
class=${this._result || ""}
>
<slot></slot>
</mwc-button>
${this.progress
? html`<div class="progress">
<ha-circular-progress size="small" active></ha-circular-progress>
</div>`
: ""}
${!overlay
? ""
: html`
<div class="progress">
${this._result === "success"
? html`<ha-svg-icon .path=${mdiCheckBold}></ha-svg-icon>`
: this._result === "error"
? html`<ha-svg-icon .path=${mdiAlertOctagram}></ha-svg-icon>`
: this.progress
? html`
<ha-circular-progress
size="small"
active
></ha-circular-progress>
`
: ""}
</div>
`}
`;
}
public actionSuccess(): void {
this._tempClass("success");
this._setResult("success");
}
public actionError(): void {
this._tempClass("error");
this._setResult("error");
}
private _tempClass(className: string): void {
this._button!.classList.add(className);
private _setResult(result: "success" | "error"): void {
this._result = result;
setTimeout(() => {
this._button!.classList.remove(className);
}, 1000);
this._result = undefined;
}, 2000);
}
private _buttonTapped(ev: Event): void {
@@ -69,6 +85,7 @@ export class HaProgressButton extends LitElement {
background-color: var(--success-color);
transition: none;
border-radius: 4px;
pointer-events: none;
}
mwc-button[raised].success {
@@ -81,6 +98,7 @@ export class HaProgressButton extends LitElement {
background-color: var(--error-color);
transition: none;
border-radius: 4px;
pointer-events: none;
}
mwc-button[raised].error {
@@ -89,13 +107,21 @@ export class HaProgressButton extends LitElement {
}
.progress {
bottom: 0;
margin-top: 4px;
bottom: 4px;
position: absolute;
text-align: center;
top: 0;
top: 4px;
width: 100%;
}
ha-svg-icon {
color: white;
}
mwc-button.success slot,
mwc-button.error slot {
visibility: hidden;
}
`;
}
}

View File

@@ -347,8 +347,8 @@ class StatisticsChart extends LitElement {
statTypes.forEach((type) => {
let val: number | null;
if (type === "sum") {
if (!initVal) {
initVal = val = stat.state;
if (initVal === null) {
initVal = val = stat.state || 0;
prevSum = stat.sum;
} else {
val = initVal + ((stat.sum || 0) - prevSum!);

View File

@@ -1,165 +1,167 @@
export const currencies = [
"AED",
"AFN",
"ALL",
"AMD",
"ANG",
"AOA",
"ARS",
"AUD",
"AWG",
"AZN",
"BAM",
"BBD",
"BDT",
"BGN",
"BHD",
"BIF",
"BMD",
"BND",
"BOB",
"BRL",
"BSD",
"BTN",
"BWP",
"BYN",
"BYR",
"BZD",
"CAD",
"CDF",
"CHF",
"CLP",
"CNY",
"COP",
"CRC",
"CUP",
"CVE",
"CZK",
"DJF",
"DKK",
"DOP",
"DZD",
"EGP",
"ERN",
"ETB",
"EUR",
"FJD",
"FKP",
"GBP",
"GEL",
"GHS",
"GIP",
"GMD",
"GNF",
"GTQ",
"GYD",
"HKD",
"HNL",
"HRK",
"HTG",
"HUF",
"IDR",
"ILS",
"INR",
"IQD",
"IRR",
"ISK",
"JMD",
"JOD",
"JPY",
"KES",
"KGS",
"KHR",
"KMF",
"KPW",
"KRW",
"KWD",
"KYD",
"KZT",
"LAK",
"LBP",
"LKR",
"LRD",
"LSL",
"LTL",
"LYD",
"MAD",
"MDL",
"MGA",
"MKD",
"MMK",
"MNT",
"MOP",
"MRO",
"MUR",
"MVR",
"MWK",
"MXN",
"MYR",
"MZN",
"NAD",
"NGN",
"NIO",
"NOK",
"NPR",
"NZD",
"OMR",
"PAB",
"PEN",
"PGK",
"PHP",
"PKR",
"PLN",
"PYG",
"QAR",
"RON",
"RSD",
"RUB",
"RWF",
"SAR",
"SBD",
"SCR",
"SDG",
"SEK",
"SGD",
"SHP",
"SLL",
"SOS",
"SRD",
"SSP",
"STD",
"SYP",
"SZL",
"THB",
"TJS",
"TMT",
"TND",
"TOP",
"TRY",
"TTD",
"TWD",
"TZS",
"UAH",
"UGX",
"USD",
"UYU",
"UZS",
"VEF",
"VND",
"VUV",
"WST",
"XAF",
"XCD",
"XOF",
"XPF",
"YER",
"ZAR",
"ZMK",
"ZWL",
];
export const createCurrencyListEl = () => {
const list = document.createElement("datalist");
list.id = "currencies";
for (const currency of [
"AED",
"AFN",
"ALL",
"AMD",
"ANG",
"AOA",
"ARS",
"AUD",
"AWG",
"AZN",
"BAM",
"BBD",
"BDT",
"BGN",
"BHD",
"BIF",
"BMD",
"BND",
"BOB",
"BRL",
"BSD",
"BTN",
"BWP",
"BYN",
"BYR",
"BZD",
"CAD",
"CDF",
"CHF",
"CLP",
"CNY",
"COP",
"CRC",
"CUP",
"CVE",
"CZK",
"DJF",
"DKK",
"DOP",
"DZD",
"EGP",
"ERN",
"ETB",
"EUR",
"FJD",
"FKP",
"GBP",
"GEL",
"GHS",
"GIP",
"GMD",
"GNF",
"GTQ",
"GYD",
"HKD",
"HNL",
"HRK",
"HTG",
"HUF",
"IDR",
"ILS",
"INR",
"IQD",
"IRR",
"ISK",
"JMD",
"JOD",
"JPY",
"KES",
"KGS",
"KHR",
"KMF",
"KPW",
"KRW",
"KWD",
"KYD",
"KZT",
"LAK",
"LBP",
"LKR",
"LRD",
"LSL",
"LTL",
"LYD",
"MAD",
"MDL",
"MGA",
"MKD",
"MMK",
"MNT",
"MOP",
"MRO",
"MUR",
"MVR",
"MWK",
"MXN",
"MYR",
"MZN",
"NAD",
"NGN",
"NIO",
"NOK",
"NPR",
"NZD",
"OMR",
"PAB",
"PEN",
"PGK",
"PHP",
"PKR",
"PLN",
"PYG",
"QAR",
"RON",
"RSD",
"RUB",
"RWF",
"SAR",
"SBD",
"SCR",
"SDG",
"SEK",
"SGD",
"SHP",
"SLL",
"SOS",
"SRD",
"SSP",
"STD",
"SYP",
"SZL",
"THB",
"TJS",
"TMT",
"TND",
"TOP",
"TRY",
"TTD",
"TWD",
"TZS",
"UAH",
"UGX",
"USD",
"UYU",
"UZS",
"VEF",
"VND",
"VUV",
"WST",
"XAF",
"XCD",
"XOF",
"XPF",
"YER",
"ZAR",
"ZMK",
"ZWL",
]) {
for (const currency of currencies) {
const option = document.createElement("option");
option.value = currency;
option.innerHTML = currency;

View File

@@ -21,7 +21,7 @@ import { styleMap } from "lit/directives/style-map";
import memoizeOne from "memoize-one";
import { restoreScroll } from "../../common/decorators/restore-scroll";
import { fireEvent } from "../../common/dom/fire_event";
import "../../common/search/search-input";
import "../search-input";
import { debounce } from "../../common/util/debounce";
import { nextRender } from "../../common/util/render-status";
import { haStyleScrollbar } from "../../resources/styles";

View File

@@ -7,25 +7,26 @@ import type {
SortableColumnContainer,
SortingDirection,
} from "./ha-data-table";
import { fuzzyMatcher } from "../../common/string/filter/sequence-matching";
const filterData = (
data: DataTableRowData[],
columns: SortableColumnContainer,
filter: string
) => {
filter = filter.toUpperCase();
const matcher = fuzzyMatcher(filter);
return data.filter((row) =>
Object.entries(columns).some((columnEntry) => {
const [key, column] = columnEntry;
if (column.filterable) {
if (
String(
column.filterKey
? row[column.valueColumn || key][column.filterKey]
: row[column.valueColumn || key]
matcher(
String(
column.filterKey
? row[column.valueColumn || key][column.filterKey]
: row[column.valueColumn || key]
)
)
.toUpperCase()
.includes(filter)
) {
return true;
}

View File

@@ -115,6 +115,9 @@ class DateRangePickerElement extends WrappedElement {
color: var(--primary-text-color);
min-width: initial !important;
}
.daterangepicker:before {
display: none;
}
.daterangepicker:after {
border-bottom: 6px solid var(--card-background-color);
}

View File

@@ -1,5 +1,4 @@
import "@material/mwc-list/mwc-list-item";
import "@material/mwc-select/mwc-select";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { property, state } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event";
@@ -8,6 +7,7 @@ import {
deviceAutomationsEqual,
} from "../../data/device_automation";
import { HomeAssistant } from "../../types";
import "../ha-select";
const NO_AUTOMATION_KEY = "NO_AUTOMATION";
const UNKNOWN_AUTOMATION_KEY = "UNKNOWN_AUTOMATION";
@@ -90,7 +90,7 @@ export abstract class HaDeviceAutomationPicker<
}
const value = this._value;
return html`
<mwc-select
<ha-select
.label=${this.label}
.value=${value}
@selected=${this._automationChanged}
@@ -113,7 +113,7 @@ export abstract class HaDeviceAutomationPicker<
</mwc-list-item>
`
)}
</mwc-select>
</ha-select>
`;
}
@@ -167,7 +167,7 @@ export abstract class HaDeviceAutomationPicker<
static get styles(): CSSResultGroup {
return css`
mwc-select {
ha-select {
width: 100%;
margin-top: 4px;
}

View File

@@ -52,6 +52,8 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
@property() public value?: string;
@property() public helper?: string;
@property() public devices?: DeviceRegistryEntry[];
@property() public areas?: AreaRegistryEntry[];
@@ -86,6 +88,8 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
@property({ type: Boolean }) public disabled?: boolean;
@property({ type: Boolean }) public required?: boolean;
@state() private _opened?: boolean;
@query("ha-combo-box", true) public comboBox!: HaComboBox;
@@ -267,8 +271,10 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
? this.hass.localize("ui.components.device-picker.device")
: this.label}
.value=${this._value}
.helper=${this.helper}
.renderer=${rowRenderer}
.disabled=${this.disabled}
.required=${this.required}
item-value-path="id"
item-label-path="name"
@opened-changed=${this._openedChanged}

View File

@@ -1,9 +1,10 @@
import { html, LitElement, TemplateResult } from "lit";
import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event";
import { PolymerChangedEvent } from "../../polymer-types";
import { HomeAssistant } from "../../types";
import "./ha-device-picker";
import type { HaDevicePickerDeviceFilterFunc } from "./ha-device-picker";
@customElement("ha-devices-picker")
class HaDevicesPicker extends LitElement {
@@ -11,6 +12,12 @@ class HaDevicesPicker extends LitElement {
@property() public value?: string[];
@property() public helper?: string;
@property({ type: Boolean }) public disabled?: boolean;
@property({ type: Boolean }) public required?: boolean;
/**
* Show entities from specific domains.
* @type {string}
@@ -35,6 +42,8 @@ class HaDevicesPicker extends LitElement {
@property({ attribute: "pick-device-label" }) public pickDeviceLabel?: string;
@property() public deviceFilter?: HaDevicePickerDeviceFilterFunc;
protected render(): TemplateResult {
if (!this.hass) {
return html``;
@@ -49,11 +58,13 @@ class HaDevicesPicker extends LitElement {
allow-custom-entity
.curValue=${entityId}
.hass=${this.hass}
.deviceFilter=${this.deviceFilter}
.includeDomains=${this.includeDomains}
.excludeDomains=${this.excludeDomains}
.includeDeviceClasses=${this.includeDeviceClasses}
.value=${entityId}
.label=${this.pickedDeviceLabel}
.disabled=${this.disabled}
@value-changed=${this._deviceChanged}
></ha-device-picker>
</div>
@@ -61,11 +72,16 @@ class HaDevicesPicker extends LitElement {
)}
<div>
<ha-device-picker
allow-custom-entity
.hass=${this.hass}
.helper=${this.helper}
.deviceFilter=${this.deviceFilter}
.includeDomains=${this.includeDomains}
.excludeDomains=${this.excludeDomains}
.includeDeviceClasses=${this.includeDeviceClasses}
.label=${this.pickDeviceLabel}
.disabled=${this.disabled}
.required=${this.required && !currentDevices.length}
@value-changed=${this._addDevice}
></ha-device-picker>
</div>
@@ -116,6 +132,12 @@ class HaDevicesPicker extends LitElement {
this._updateDevices([...currentDevices, toAdd]);
}
static override styles = css`
div {
margin-top: 8px;
}
`;
}
declare global {

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