Compare commits

..
Author SHA1 Message Date
Joakim Sørensen 09f4922ad3 change 2021-06-15 15:44:59 +00:00
Joakim Sørensen 36831d26e4 fix typing 2021-06-15 09:51:27 +00:00
Joakim Sørensen 5829660894 Better event handling 2021-06-15 09:48:19 +00:00
Joakim Sørensen 4e3fbc1169 Add applying update "screen" 2021-06-14 18:18:54 +00:00
GitHub Action 38640c99e3 Translation update 2021-06-14 00:48:26 +00:00
GitHub Action d6df8bddea Translation update 2021-06-13 00:48:28 +00:00
GitHub Action ddfc4bd98e Translation update 2021-06-12 00:48:12 +00:00
3d6674325c Fix the issue that logbook card doesn't translate context.user_id to name if it's a user's id. (#9383)
Co-authored-by: Bram Kragten <[email protected]>
2021-06-10 14:51:24 +02:00
Bram KragtenandGitHub 194829f5b1 Generalize map (#9331)
* Generalize map

* Fix path opacity

* Add fitZones
2021-06-10 14:22:44 +02:00
GitHub Action 11a77253f4 Translation update 2021-06-10 00:49:02 +00:00
GitHub Action 67be2343f8 Translation update 2021-06-09 00:48:19 +00:00
e9b1b3d853 Fix issues with restoring snapshot during onboarding (#9385)
Co-authored-by: Bram Kragten <[email protected]>
2021-06-08 17:57:53 +02:00
8a33d174d7 FIx selecting service/url path action after choosing default action (#9376)
Co-authored-by: Joakim Sørensen <[email protected]>
2021-06-08 14:24:58 +02:00
Joakim SørensenandGitHub 226d6216b7 Build wheels for 3.9-alpine3.13 (#9390) 2021-06-08 13:07:02 +02:00
GitHub Action 1925bb01be Translation update 2021-06-08 00:49:18 +00:00
Bram Kragten 82a4806e01 Change line logic 2021-06-07 10:45:57 +02:00
ce419fae7b Add password confirmation to snapshot creation (#9349)
* Add password confirmation to snapshot creation

* Remove confirm_password before sending

* change layout

* style changes

* Adjust styling

Co-authored-by: Bram Kragten <[email protected]>
2021-06-07 10:45:20 +02:00
c68b76e2da Add hardware dialog (#9348)
Co-authored-by: Bram Kragten <[email protected]>
2021-06-07 10:16:33 +02:00
Joakim SørensenandGitHub 342020b420 Fix downloads on mobile (#9375) 2021-06-07 10:15:43 +02:00
GitHub Action 1e6e99e3c7 Translation update 2021-06-07 00:49:13 +00:00
GitHub Action 2e9aafc377 Translation update 2021-06-06 00:49:09 +00:00
dependabot[bot]andGitHub 299c863f49 Bump ws from 6.2.1 to 6.2.2 (#9372) 2021-06-05 23:52:13 +02:00
Bram KragtenandGitHub c2792a28ba Move attributes down in more info person and timer (#9368) 2021-06-05 12:52:27 +02:00
GitHub Action 635a027a8e Translation update 2021-06-05 02:40:15 +00:00
Will AdlerandGitHub a45b8ca8e7 Add period to end of sentence (#9361) 2021-06-04 08:57:03 +02:00
GitHub Action 1e6e945a07 Translation update 2021-06-04 02:52:56 +00:00
Bram KragtenandGitHub f71157c24d Remove tsc from pre commit (#9359) 2021-06-03 22:57:03 +02:00
Bram Kragten e87a2b36cf Bumped version to 20210603.0 2021-06-03 22:51:53 +02:00
Bram KragtenandGitHub 5418474f64 Polyfill globalThis in latest build (#9352) 2021-06-03 22:50:33 +02:00
Philip AllgaierandGitHub 8836ba6ceb Pick the correct backend-selected active theme (#9357) 2021-06-03 22:48:52 +02:00
Bram KragtenandGitHub 509c5b497a Disable babel compact option (#9335) 2021-06-03 12:34:30 -07:00
Joakim SørensenandGitHub e00bcc9f48 Better exit navigation for my-ingress (#9342) 2021-06-03 10:01:12 -07:00
Joakim SørensenandGitHub bdef9fd040 Add missing media folder to snapshot (#9341) 2021-06-03 10:21:04 +02:00
GitHub Action c956491ec5 Translation update 2021-06-03 03:48:04 +00:00
Bram KragtenandGitHub 68bc549d6a Use HLS light build (#9338)
* Use HLS light build

* Bump hls, backBufferLength
2021-06-02 18:34:18 +02:00
Bram KragtenandGitHub 9c64eafc21 Fix ZHA visualization (#9337) 2021-06-02 18:33:55 +02:00
Bram KragtenandGitHub b05e86d442 Fix noUnderline in search input (#9339) 2021-06-02 18:33:44 +02:00
Bram Kragten fe5f9576c6 Fix dev 2021-06-02 10:11:29 +02:00
1b282b65b7 Add QR code to long lived access tokens dialog (#8948)
* Add QR code to long lived access tokens dialog

* Apply suggestions from code review

Co-authored-by: Bram Kragten <[email protected]>

* Further changes from code review

Co-authored-by: Bram Kragten <[email protected]>
2021-06-02 09:59:22 +02:00
GitHub Action e49664bad3 Translation update 2021-06-02 04:10:37 +00:00
Bram Kragten 2a30b55a43 Bumped version to 20210601.1 2021-06-01 21:30:51 +02:00
9d0b20adce Add support for system options v2 (#9332)
* Add support for system options v2

* Update src/dialogs/config-entry-system-options/dialog-config-entry-system-options.ts

Co-authored-by: Bram Kragten <[email protected]>

* Update dialog-config-entry-system-options.ts

Co-authored-by: Bram Kragten <[email protected]>
2021-06-01 12:22:25 -07:00
Bram KragtenandGitHub acd5e1c081 Fix back button too wide on mobile (#9333) 2021-06-01 12:12:00 -07:00
Bram KragtenandGitHub cc1c5e45b2 Display error when enabling/disabling config entries (#9325) 2021-06-01 21:03:00 +02:00
Bram KragtenandGitHub 038199c447 Change the type of debounce, use arrow functions (#9328) 2021-06-01 11:53:45 -07:00
Bram KragtenandGitHub 8a1eab7ceb Cleanup virtualizer styles (#9327) 2021-06-01 11:51:30 -07:00
bc5bd35448 Filter adapters with information from the Supervisor (#9322)
Co-authored-by: Bram Kragten <[email protected]>
2021-06-01 20:12:54 +02:00
Bram KragtenandGitHub 1795fd56b7 Don't rotate chart axis labels (#9329) 2021-06-01 10:28:03 -07:00
Bram Kragten 4a7c33edad Bumped version to 20210601.0 2021-06-01 11:40:37 +02:00
rianadonandGitHub 797f60d725 Show pressure units in weather details card (#9295) 2021-06-01 11:40:04 +02:00
Bram KragtenandGitHub 2427d68aa1 Use local version 0.7 of lit-virtualizer (#9321) 2021-06-01 11:39:15 +02:00
GitHub Action 00c6b0f8ed Translation update 2021-06-01 04:14:44 +00:00
Paulus Schoutsen 7b8d4ab3d6 Update translations 2021-05-31 15:50:47 -07:00
Paulus Schoutsen 07a1a805f6 Bumped version to 20210531.1 2021-05-31 15:44:59 -07:00
Paulus SchoutsenandGitHub d8bab6aba9 Add support for disable polling system option (#9316) 2021-05-31 15:40:50 -07:00
Bram KragtenandGitHub a930e2dc75 Fix store auth disappearing (#9312) 2021-05-31 15:35:51 -07:00
J. Nick KostonandGitHub 2eb35668fa Seperate addresses in network configuration (#9319) 2021-05-31 15:31:33 -07:00
GitHub Action 07f4e5ac5c Translation update 2021-05-31 03:47:12 +00:00
Paulus Schoutsen db82a90414 Bumped version to 20210531.0 2021-05-30 20:17:09 -07:00
Bram KragtenandGitHub 51a693badf Convert ha-store-auth-card to Lit/TS/ha-card (#9300) 2021-05-30 20:16:45 -07:00
Bram KragtenandGitHub 2aa8f5b352 Dev states: replace pattern in word by wildcard search (#9288) 2021-05-30 20:11:53 -07:00
Bram KragtenandGitHub 93b3b8f985 Fix editor structs (#9286) 2021-05-30 20:08:46 -07:00
Bram KragtenandGitHub 92c8bd80b5 Catch translation errors (#9299) 2021-05-30 17:02:03 +02:00
Philip AllgaierandGitHub 528af0157d Move entity attribution out of attribute expansion panel (#9296) 2021-05-30 16:06:22 +02:00
Bram Kragten 10a77b6278 Update translations 2021-05-30 16:02:03 +02:00
GitHub Action 03bbf6a582 Translation update 2021-05-30 03:38:49 +00:00
GitHub Action 63fcb649d2 Translation update 2021-05-29 03:21:09 +00:00
Bram KragtenandGitHub 4f60a92b92 Fix default themes (#9290)
* Fix default themes

* Simplify pick theme row
2021-05-28 20:02:28 -07:00
Bram KragtenandGitHub 0419c1a41f Fix icon loading (#9289) 2021-05-28 19:54:28 -07:00
2d5ae78521 Add selection to snapshot table for mass deletion (#9284)
Co-authored-by: Bram Kragten <[email protected]>
2021-05-28 15:49:40 +02:00
Joakim SørensenandGitHub 959134df02 Better secrets support in add-on configuration (#9275) 2021-05-28 14:37:16 +02:00
Bram Kragten a9f9fc4ce2 Bumped version to 20210528.0 2021-05-28 12:26:38 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
cfb370a3c8 Bump dns-packet from 1.3.1 to 1.3.4 (#9281)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-28 12:25:46 +02:00
Bram KragtenandGitHub 353435c8d5 Fix icon db loading (#9280) 2021-05-28 11:54:20 +02:00
Bram KragtenandGitHub c8c85d096b Show less ticks in charts (#9279) 2021-05-28 10:16:37 +02:00
GitHub Action 19c9c8f227 Translation update 2021-05-28 03:03:41 +00:00
Bram KragtenandGitHub 6ea2a29eea Hide attribute measurement and editable attributes (#9272) 2021-05-27 11:48:27 +02:00
Joakim SørensenandGitHub 59f3f819a6 Revert name change from selectedTheme to selectedThemeSettings (#9273) 2021-05-27 10:21:58 +02:00
GitHub Action 93e8f52880 Translation update 2021-05-27 02:45:51 +00:00
Joakim SørensenandGitHub 02810efcc4 Replace Hass_io_ prefix for snapshot downloads (#9270) 2021-05-26 21:56:27 +02:00
Bram KragtenandGitHub 4b9be7ce16 Fix entity filtering in dev states (#9268) 2021-05-26 17:27:45 +02:00
Bram Kragten f3ec09e480 Bumped version to 20210526.0 2021-05-26 16:58:31 +02:00
Bram KragtenandGitHub 8291a84e3e Hide network config when not loaded (#9265) 2021-05-26 07:53:54 -07:00
b0e1f0f73a Add network configuration (#9210)
Co-authored-by: Bram Kragten <[email protected]>
2021-05-26 16:44:15 +02:00
Bram KragtenandGitHub a66b966e7d Fix a bunch of updates triggering updated (#9260) 2021-05-26 16:29:50 +02:00
Philip AllgaierandGitHub 5f56040c64 Add friendly_name to dev tools "Entity" column + fuzzy search (#7582) 2021-05-26 15:29:51 +02:00
Bram KragtenandGitHub eaccd22267 Fix chartjs deprecation warnings (#9261) 2021-05-26 15:05:01 +02:00
Bram KragtenandGitHub 27845a7345 Fix logbook height (#9258) 2021-05-26 12:44:10 +02:00
Bram KragtenandGitHub f7ef8180e4 Guard for undefined item in quick bar (#9259) 2021-05-26 12:43:59 +02:00
Bram KragtenandGitHub 5958eb9a55 Minor dependency bumps (#9249) 2021-05-26 12:04:39 +02:00
Bram Kragten 3ef2912b60 Fix typo in translation key 2021-05-26 11:19:09 +02:00
Joakim SørensenandGitHub fa9c6a765a Replace closing with closed in dialogs (#9257) 2021-05-26 11:10:27 +02:00
Bram KragtenandGitHub c4a8899780 Bump idb-keyval (#9248)
https://github.com/jakearchibald/idb-keyval#updating-from-3x
2021-05-26 10:22:38 +02:00
Bram KragtenandGitHub 3cc4628d03 Bump test dependencies (#9244) 2021-05-26 10:02:02 +02:00
GitHub Action b6c5223221 Translation update 2021-05-26 02:25:19 +00:00
Philip AllgaierandGitHub cbd6d4251c Prevent shrinking of percent value in supervisor metrics (#9033) 2021-05-26 00:24:30 +02:00
Bram KragtenandGitHub fdcbb5b432 Bump js-yaml (#9245) 2021-05-26 00:13:58 +02:00
Bram KragtenandGitHub de09e31815 Fix resetting theme, only fallback to light when theme doesnt support… (#9253) 2021-05-26 00:11:17 +02:00
Philip AllgaierandGitHub f55e911313 Prevent formatting for unknown attribute (#9252) 2021-05-26 00:08:41 +02:00
Bram KragtenandGitHub 465a91dbf3 Fix circulair progress producing scrollbars (#9247) 2021-05-25 23:59:24 +02:00
Bram KragtenandGitHub 835a7833ae Bump memoize one (#9243) 2021-05-25 23:53:58 +02:00
Bram KragtenandGitHub 179717d40c Fix rollup build (#9246) 2021-05-25 23:51:31 +02:00
Philip AllgaierandGitHub 3d4d789f7f Detect and format date & timestamp attributes (#9074) 2021-05-25 22:39:21 +02:00
Bram KragtenandGitHub d97fb19f05 Ingress: Wait for dialog to close before navigating (#9250) 2021-05-25 22:11:52 +02:00
0dd3757df2 Refresh snapshot create/restore dialogs (#9223)
Co-authored-by: Bram Kragten <[email protected]>
2021-05-25 21:29:32 +02:00
Philip AllgaierandGitHub c32a4546f3 Translate NC account connection state (#9167) 2021-05-25 18:12:56 +02:00
1bb025ccd0 Add log level changed message when user changes Z-Wave JS log level (#9238)
Co-authored-by: Bram Kragten <[email protected]>
2021-05-25 17:59:00 +02:00
2b8033a97f Prevent cutting off of attributes in more-info light (#9219)
* Prevent cutting off of attributes in more-info light

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

Co-authored-by: Bram Kragten <[email protected]>
2021-05-25 17:58:20 +02:00
Joakim SørensenandGitHub 21a3a8c594 Navigate cleanup (#9202) 2021-05-25 17:46:36 +02:00
1026e90296 Put attributes in more-info into a foldable section (#9220)
Co-authored-by: Bram Kragten <[email protected]>
2021-05-25 17:44:02 +02:00
Bram KragtenandGitHub 0eca602e61 Use comboBoxRenderer from lit-vaadin-helpers (#9201) 2021-05-25 13:27:49 +02:00
Philip AllgaierandGitHub 7f75ca81f1 Add support for custom themes to use dark mode (#8347) 2021-05-25 13:26:35 +02:00
Bram KragtenandGitHub 8af05e2726 Optimise data table and device dashboard (#9217) 2021-05-25 13:12:44 +02:00
Bram KragtenandGitHub 0a478ee1da Fix tabs styling (#9241) 2021-05-25 12:05:20 +02:00
GitHub Action a4bdc5a05f Translation update 2021-05-25 02:00:53 +00:00
d425767dae Ensure timer row uses correct state translation keys (#9143)
* Ensure timer row uses correct state translation keys

* Changes from review

* Update src/panels/lovelace/entity-rows/hui-timer-entity-row.ts

Co-authored-by: Bram Kragten <[email protected]>

* Move logic to data/timer

Co-authored-by: Bram Kragten <[email protected]>
2021-05-24 23:27:00 +02:00
Philip AllgaierandGitHub c78382c119 Make it clear that those are the installed add-ons (#9228) 2021-05-24 23:20:22 +02:00
Philip AllgaierandGitHub ee15ddfbc3 Show correct number of disabled integrations (#9232) 2021-05-24 22:47:28 +02:00
Philip AllgaierandGitHub 0af14eb77e Add refresh button to state dev tools (#9231) 2021-05-24 22:37:29 +02:00
GitHub Action 583cc4bc8a Translation update 2021-05-24 02:01:00 +00:00
GitHub Action 2ee92f48e6 Translation update 2021-05-23 02:04:38 +00:00
Franck NijhofandGitHub d05e02ab3e Add the Supervisor as an ignorable discovery source (#9229) 2021-05-22 19:26:27 +02:00
Joakim SørensenandGitHub abb9f8e233 Remove padding when narrow (#9209) 2021-05-22 06:12:51 -07:00
GitHub Action f873ef9b59 Translation update 2021-05-22 01:52:23 +00:00
Philip AllgaierandGitHub 1255b56522 Add missing translations to voice command dialog (#9221) 2021-05-21 10:11:31 +02:00
Bram KragtenandGitHub fd9bb4d8cc Make chrome work-around work in iframes (#9200) 2021-05-21 09:09:31 +02:00
GitHub Action 9328576b55 Translation update 2021-05-21 01:53:57 +00:00
70a1edd1dd Allow users to select time format for UI rendering (#9042)
Co-authored-by: Bram Kragten <[email protected]>
2021-05-20 16:23:53 +02:00
Brynley McDonaldandGitHub 87e4c209f4 Add icon to Entities card schema (#9208) 2021-05-20 15:29:32 +02:00
Bram Kragten 3d0a5642cc Only apply on Safari 14.0, and not 14.0.1 2021-05-20 14:23:50 +02:00
GitHub Action e211d812ad Translation update 2021-05-20 01:50:44 +00:00
GitHub Action 0dcf673b87 Translation update 2021-05-19 01:50:13 +00:00
Paulus Schoutsen cb14e1f20c Bumped version to 20210518.0 2021-05-18 15:12:08 -07:00
Bram KragtenandGitHub 52087c0e30 Fix _initialize (#9206)
* Fix _initialize

* Update ha-demo.ts
2021-05-18 15:11:24 -07:00
1b9286db76 Fix lit warnings (#9204)
Co-authored-by: Bram Kragten <[email protected]>
2021-05-18 15:01:43 -07:00
Bram KragtenandGitHub bc92c0b052 Upgrade to Lit 2 (#9199) 2021-05-18 07:37:53 -07:00
Joakim SørensenandGitHub 245bb639f2 Fix URL to jinja template docs (#9198) 2021-05-18 10:22:03 +02:00
GitHub Action 8d81ed58c8 Translation update 2021-05-18 01:57:40 +00:00
Paulus Schoutsen 7890ca85a8 Bumped version to 20210517.0 2021-05-17 16:06:19 -07:00
Paulus SchoutsenandGitHub 07bab7b264 Drop app-route (#9196) 2021-05-17 16:05:58 -07:00
Paulus SchoutsenandGitHub 5730c14dc1 Make hassio backwards compat (#9195) 2021-05-17 23:59:46 +02:00
Paulus SchoutsenandGitHub f8e8b5ad18 Trace fixes (#9192)
* Show sub-conditions

* Better show errors in timeline

* Add rendered nodes

* Fix some rendering issues with sub-conditions in timeline

* Improve condition rendering
2021-05-17 20:19:47 +02:00
Charles GarwoodandGitHub fd2728c02c Fix Z-Wave JS add node wizard and add interview status (#9145) 2021-05-17 17:15:01 +02:00
Bram KragtenandGitHub 7e2bf920e1 Correct types for script automation editors (#9184) 2021-05-17 07:57:43 -07:00
Bram KragtenandGitHub 1f65328f2d Make slider default for number selector (#9190) 2021-05-17 07:55:12 -07:00
Bram KragtenandGitHub 4f731baa00 Add guard for non color lights (#9186) 2021-05-17 16:24:39 +02:00
Bram KragtenandGitHub 5abb3dd8c1 Use default behaviour for service target (#8650) 2021-05-17 14:12:16 +02:00
GitHub Action 0a672c55c5 Translation update 2021-05-17 01:54:21 +00:00
GitHub Action a6b2299c74 Translation update 2021-05-16 01:59:23 +00:00
Paulus SchoutsenandGitHub 37cc6709d4 If we have a link, make it a link (#9181) 2021-05-15 12:25:28 +02:00
Paulus SchoutsenandGitHub f4ffbe67e2 Remove shadowroot from ha-markdown-element (#9187) 2021-05-15 12:23:33 +02:00
GitHub Action 9f32d72a41 Translation update 2021-05-15 01:51:54 +00:00
Bram Kragten 64a117d8ac Fix yarn.lock 2021-05-14 22:32:41 +02:00
Matt Emerick-LawandGitHub ebf0bdc840 Add duplicate scene functionality (#9175) 2021-05-14 21:44:03 +02:00
cc0a120bf6 Switch update and openChangelog button (#9174)
Co-authored-by: Bram Kragten <[email protected]>
2021-05-14 16:55:38 +02:00
Bram KragtenandGitHub fe2fe7468f Bump lodash (#9135) 2021-05-14 11:50:50 +02:00
Joakim SørensenandGitHub b12a10ccb5 Add snapshot contents as secondary info for partial snapshots (#9166) 2021-05-14 11:49:52 +02:00
2ad2a4b198 Bump lokalize deps + support object format for args (#9155)
Co-authored-by: Paulus Schoutsen <[email protected]>
2021-05-13 22:47:47 -07:00
GitHub Action 6a62f05657 Translation update 2021-05-14 01:54:56 +00:00
GitHub Action 4910f60ec4 Translation update 2021-05-13 01:54:52 +00:00
Bram KragtenandGitHub d35168e88f Bump chart.js (#9160)
Replaces #9159
2021-05-12 17:09:21 -07:00
GitHub Action 01b3d2aca9 Translation update 2021-05-12 01:47:33 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
29e8d1cff0 Bump hosted-git-info from 2.7.1 to 2.8.9 (#9162)
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.7.1 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.7.1...v2.8.9)

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-11 11:24:05 +02:00
MichaelandGitHub 4e1d10cc08 Improve UX for counter and input_number helpers (#9061) 2021-05-11 10:52:44 +02:00
GitHub Action 3575d94ca1 Translation update 2021-05-11 01:46:41 +00:00
Bram KragtenandGitHub d91546b532 Bump home-assistant-js-websocket (#9156) 2021-05-11 00:46:59 +02:00
Bram KragtenandGitHub 9f554f4917 Silence babel warnings (#9158) 2021-05-10 22:57:42 +02:00
Bram KragtenandGitHub d4720a9244 Align state info in center (#9153) 2021-05-10 22:22:54 +02:00
Philip AllgaierandGitHub 5c466712db Fix missing customElement import after Lit 2.0 bump (#9157) 2021-05-10 22:11:08 +02:00
6dc7e852ae Use hass-tabs-subpage-data-table for supervisor snapshots (#9103)
* Use hass-tabs-subpage-data-table for supervisor snapshots

* comments

* type

* cleanup

* change translations

* Update hassio/src/dialogs/snapshot/dialog-hassio-create-snapshot.ts

Co-authored-by: Bram Kragten <[email protected]>

* reset

* fix after rebase

* internalProperty -> state

Co-authored-by: Bram Kragten <[email protected]>
2021-05-10 18:17:16 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
785f614bd9 Bump lodash from 4.17.15 to 4.17.21 (#9154)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-10 16:12:38 +02:00
uvjustinandGitHub 0a8e27249d Bump hls.js from v1.0.1 to v1.0.3 (#9147) 2021-05-10 11:06:16 +02:00
GitHub Action 15ee87ee67 Translation update 2021-05-10 01:45:53 +00:00
GitHub Action 12612a16df Translation update 2021-05-09 01:44:02 +00:00
Philip AllgaierandGitHub 4f449e2600 Adjust token relative_date wording (#9138) 2021-05-08 17:30:31 +02:00
7f49f039fd Close new automation dialog before moving to next step (#9071)
* Close new automatin dialog before next step

* Update dialog-thingtalk.ts

* Fix

Co-authored-by: Bram Kragten <[email protected]>
2021-05-08 13:53:07 +02:00
Bram KragtenandGitHub 88dc65bc4e Dont require manifest for the overflow menu (#9129) 2021-05-08 13:08:28 +02:00
Paulus SchoutsenandGitHub 6edebe18ad Use grid for sensor cards on 2nd view of teaching birds demo (#9132) 2021-05-08 13:07:58 +02:00
GitHub Action 38b3a9205d Translation update 2021-05-08 01:42:37 +00:00
Joakim SørensenandGitHub 4b796b4929 Add supervisor_ingress support to my (#9087) 2021-05-07 15:08:57 -07:00
Bram KragtenandGitHub 83cabcac28 Add tsc and eslint to pre-commit (#9131) 2021-05-07 15:07:05 -07:00
d308c5d9b9 Add manual limit selection to graph header/footer (#9126)
Co-authored-by: Paulus Schoutsen <[email protected]>
2021-05-07 15:06:11 -07:00
Bram KragtenandGitHub 9f032a61a9 Add compatibility for Lit 2.0 (#8878) 2021-05-07 13:16:14 -07:00
Bram KragtenandGitHub 0f58214ba1 Bump leaflet + fix location editor (#9118) 2021-05-07 13:11:30 -07:00
c48a60cce6 Bump superstruct (#9119)
Co-authored-by: Philip Allgaier <[email protected]>
2021-05-07 13:10:35 -07:00
Bram KragtenandGitHub cd3ffceeff Fix for when the value doesnt get changed by the backend when we send it (#9105) 2021-05-07 14:33:33 +02:00
Bram KragtenandGitHub 9be4a00169 Update UI when service schema change (#9120) 2021-05-07 11:28:37 +02:00
Bram KragtenandGitHub a9c7a39a47 Fix positioning of preload checkbox (#9115) 2021-05-07 11:16:25 +02:00
Philip AllgaierandGitHub abcdd60a21 Convert GPS to uppercase in attribute name (#9124) 2021-05-07 11:14:03 +02:00
Philip AllgaierandGitHub a94f85a100 Fix alignment of Entities card header toggle (#9123) 2021-05-07 11:13:48 +02:00
GitHub Action 9755bf723f Translation update 2021-05-07 01:42:34 +00:00
Philip AllgaierandGitHub a71ebcf47e Bump js-xss to 1.0.9 (#9121) 2021-05-06 19:51:08 +02:00
GitHub Action 72695631cd Translation update 2021-05-06 01:39:12 +00:00
Bram KragtenandGitHub 2af211b543 Guard for undefined values in attribute filtering (#9089) 2021-05-05 10:32:24 +02:00
6e5e2625d6 Show supervisor addon configuration error (#8950)
Co-authored-by: Bram Kragten <[email protected]>
2021-05-05 10:26:11 +02:00
Joakim SørensenandGitHub 23c1c2f5eb Bump wheels to 3.8-alpine3.12 (#9098) 2021-05-05 08:19:58 +02:00
GitHub Action da85ee5d01 Translation update 2021-05-05 01:39:25 +00:00
Joakim SørensenandGitHub d408e8653c Return instead of trhow (#9094) 2021-05-04 23:03:57 +02:00
Bram Kragten cc76ccc3c9 Bumped version to 20210504.0 2021-05-04 23:01:56 +02:00
Bram KragtenandGitHub 105a00d3e4 Use hs color when outside of wheel (#9088) 2021-05-04 22:51:28 +02:00
Philip AllgaierandGitHub 2c08cba8cc Draw a <hr> above the attributes in more-info (#9090) 2021-05-04 22:04:27 +02:00
Philip AllgaierandGitHub 344b11a204 Prevent not needed <hr> in more-info-light (#9080) 2021-05-04 14:18:02 +02:00
GitHub Action 1ff5bf0fd5 Translation update 2021-05-04 01:43:58 +00:00
Bram Kragten c29cf7f77c Bumped version to 20210503.0 2021-05-03 15:47:44 +02:00
Bram KragtenandGitHub 193cb46d60 Config flow: Show next when not last step (#9078) 2021-05-03 15:47:03 +02:00
Bram KragtenandGitHub 9dc864d486 Break word if possible instead if break anywhere (#9076) 2021-05-02 20:42:04 -07:00
Bram KragtenandGitHub cee166839a Bump Lit element (#9068) 2021-05-02 20:41:00 -07:00
GitHub Action 1a60a3c728 Translation update 2021-05-03 01:49:21 +00:00
5d946778cb Show setting for auto connect seperately if currently connected (#9072)
Co-authored-by: Philip Allgaier <[email protected]>
Co-authored-by: Bram Kragten <[email protected]>
2021-05-02 14:45:53 +02:00
Paulus SchoutsenandGitHub ac5f85820f Integration Card: Fix Safari header break and deal with long errors (#9070) 2021-05-02 10:54:40 +02:00
GitHub Action 716e100a28 Translation update 2021-05-02 01:53:59 +00:00
Charles GarwoodandGitHub 7b8cb16c12 Add "subscribed to log" message on Z-Wave JS log subscription (#9062) 2021-05-01 14:31:59 +02:00
Philip AllgaierandGitHub 00d46424a3 Translate new setup time info header + add blank before unit (#9067) 2021-05-01 14:31:43 +02:00
Philip AllgaierandGitHub 2a5f940744 Ensure weather icon is centered in forecast (#9065) 2021-05-01 14:31:01 +02:00
Paulus SchoutsenandGitHub 13cc016b36 Fix some hassio things (#9059) 2021-05-01 14:30:33 +02:00
GitHub Action a8d49c27c8 Translation update 2021-05-01 01:48:36 +00:00
Bram Kragten a8522e91b5 Bumped version to 20210430.0 2021-04-30 21:17:22 +02:00
Bram KragtenandGitHub 5754f4463d Bump babel and eslint (#9049) 2021-04-30 12:15:31 -07:00
Bram KragtenandGitHub d4118ade0f Bump lit-html (#9053)
Adds support for Lit 2.0 directives
2021-04-30 12:12:20 -07:00
Bram KragtenandGitHub 6d80f15a98 Bump codemirror (#9052) 2021-04-30 11:34:58 -07:00
Bram KragtenandGitHub f8aa472409 Only show warning when google is enabled (#9054) 2021-04-30 11:34:45 -07:00
Bram KragtenandGitHub df22fd00ca Check if temperature available in forecast (#9055) 2021-04-30 11:34:31 -07:00
David F. MulcaheyandGitHub ce2743a982 Move ZHA config panel section translations to backend (#9018) 2021-04-30 18:59:06 +02:00
Paulus SchoutsenandGitHub 92b32458ad Fix grid card size when square (#9056) 2021-04-30 18:57:20 +02:00
Joakim SørensenandGitHub d57e8a45d3 Break primary anywhere (#9050) 2021-04-30 15:02:01 +02:00
Joakim SørensenandGitHub 551d3ffdf3 Use haStyleScrollbar for integration card lists (#9051) 2021-04-30 15:01:31 +02:00
GitHub Action 7add6eb736 Translation update 2021-04-30 01:45:22 +00:00
rmogstadandGitHub a28616d535 Fix browser language detection for region specific languages (#8982) (#9026) 2021-04-30 01:11:03 +02:00
Paulus SchoutsenandGitHub a288fd370f Fix gallery element definitions (#9046) 2021-04-30 01:10:29 +02:00
Paulus Schoutsen acd335e249 Set columns to 4 in demo 2021-04-29 14:06:52 -07:00
Bram Kragten da0bfa1945 Bumped version to 20210429.0 2021-04-29 21:56:36 +02:00
Bram KragtenandGitHub 3c61d709b5 Fix RGBWW colors (#9039) 2021-04-29 21:53:22 +02:00
Joakim SørensenandGitHub ffc92a7b63 Fix overlap on integration card (#9037) 2021-04-29 12:36:07 -07:00
Paulus SchoutsenandGitHub af0c7b5a50 Fix grid card size (#9044)
* Fix grid card size

* Remove console

* Rename
2021-04-29 12:31:46 -07:00
1904c4d057 Fix race in theme setting (#9027)
Co-authored-by: Paulus Schoutsen <[email protected]>
2021-04-29 21:04:31 +02:00
Bram KragtenandGitHub 542f169b36 Fix saving Lovelace config (#9041) 2021-04-29 09:05:58 -07:00
Bram KragtenandGitHub 65a30bf60c Fix onboarding dark styles (#9040) 2021-04-29 08:55:45 -07:00
Bram KragtenandGitHub 2e51da32f0 Handle when choose is not an array (#9028) 2021-04-29 08:53:58 -07:00
Philip AllgaierandGitHub 0562242043 Format "IP" and "MAC" attribute names (#9034) 2021-04-29 15:55:51 +02:00
GitHub Action debcdefc21 Translation update 2021-04-29 00:48:48 +00:00
Paulus Schoutsen 0de3f3a332 Merge remote-tracking branch 'origin/master' into dev 2021-04-28 10:29:18 -07:00
Paulus Schoutsen 4fcb4d449e Bumped version to 20210428.0 2021-04-28 10:28:50 -07:00
Bram KragtenandGitHub 408fe25abd Update workbox, add expiration on cache (#9020) 2021-04-28 10:26:30 -07:00
Paulus SchoutsenandGitHub 236e5e0b25 Show subtrace steps when selecting a node (#9023)
* Show subtrace steps when selecting a node

* Limit logic to just child conditions
2021-04-28 10:23:30 -07:00
ebe0caba83 MVP Z-Wave JS Log Viewer (#9008)
* Add element to subscribe to ZJS logs

* set log level and adjust styling

* review comments

* add ZWaveJS to function names

* use flexbox

* Review comments

* import

Co-authored-by: Paulus Schoutsen <[email protected]>
Co-authored-by: Bram Kragten <[email protected]>
2021-04-28 13:00:13 -04:00
Philip AllgaierandGitHub 9d33c0cfaf Fix unit support in gauge editor (#9021) 2021-04-28 18:19:51 +02:00
7962130a0c Show entities on area page (#8980)
Co-authored-by: Philip Allgaier <[email protected]>
2021-04-28 17:01:43 +02:00
9690434cac Reconfigure ZHA device take 2 (#8990)
Co-authored-by: Bram Kragten <[email protected]>
2021-04-28 12:30:09 +02:00
GitHub Action 7304544c37 Translation update 2021-04-28 00:48:54 +00:00
Bram Kragten 5a3408c242 Bumped version to 20210427.0 2021-04-28 00:22:22 +02:00
Bram KragtenandGitHub 16996f25af Update demo lights (#9011) 2021-04-28 00:21:23 +02:00
0c12586019 Display cumulative setup seconds on the config info page (#8720)
Co-authored-by: Bram Kragten <[email protected]>
Co-authored-by: Philip Allgaier <[email protected]>
2021-04-27 23:38:29 +02:00
Joakim SørensenandGitHub 93a1adaa56 Remove analytics translations (#9002) 2021-04-27 22:44:28 +02:00
Charles GarwoodandGitHub 83e65e2cc6 Add UI for Z-Wave JS Device Reinterview (#8957) 2021-04-27 13:30:15 -07:00
Bram KragtenandGitHub 36586b798e Use supported_color_modes to determine what UI elements to show (#8961) 2021-04-27 10:43:25 -07:00
Paulus SchoutsenandGitHub 20c351949f Strategy: Update name -> type (#9006) 2021-04-27 10:04:52 -07:00
Bram KragtenandGitHub b63bd92d81 Bump codemirror with iOS fix (#8992) 2021-04-27 16:29:20 +02:00
GitHub Action 9f3bb7f4d6 Translation update 2021-04-27 00:48:52 +00:00
Charles GarwoodandGitHub 73bb346c00 Show feedback for setting Z-Wave JS config parameters (#8956) 2021-04-27 01:20:23 +02:00
33703a3b53 Add link to integration docs from service control (#8290)
* Add link to integration help to dev tool services

* Adjust to new service control

* Update src/translations/en.json

Co-authored-by: Bram Kragten <[email protected]>

* Make icon less noticable + correct translation

Co-authored-by: Bram Kragten <[email protected]>
2021-04-27 00:28:22 +02:00
Charles GarwoodandGitHub b7a4f97eca Add opt-in toggle for zwave-js telemetry to config panel (#8958) 2021-04-27 00:19:48 +02:00
Bram KragtenandGitHub dd4efe0f51 Apply dark style on init when prefers-color-scheme: dark (#8997) 2021-04-26 14:54:47 -07:00
Bram KragtenandGitHub 7e0522c3b3 Don't do migration of service data in public prop (#8949)
Fixes #8879
2021-04-26 14:52:18 -07:00
Franck NijhofandGitHub e682abfb75 Tweak inputs for GitHub issue form (#8999) 2021-04-26 23:48:21 +02:00
Paulus SchoutsenandGitHub 24e202a3d7 Use translations for config entry reason (#8981) 2021-04-26 17:50:23 +02:00
ac9a881ab5 Fix ZHA network visualization page navigation (#8994)
* Fix ZHA visualization page navigation

* Update src/panels/config/integrations/integration-panels/zha/zha-network-visualization-page.ts

Co-authored-by: Bram Kragten <[email protected]>

Co-authored-by: Bram Kragten <[email protected]>
2021-04-26 10:48:11 -04:00
Joakim SørensenandGitHub 4d287a1f83 Use top.history in dialogs and navigate (#8995) 2021-04-26 16:41:30 +02:00
Paulus SchoutsenandGitHub b8d6b1ebdd Fetch manifests for discovered flows (#8987) 2021-04-26 07:33:00 -07:00
David F. MulcaheyandGitHub 8ca1b9320d Initial custom configuration for ZHA (#8737) 2021-04-26 16:25:02 +02:00
Philip AllgaierandGitHub cba3992d2b Make "Events" dev tools use screen space better (#7449) 2021-04-26 12:09:50 +02:00
96d6e337be Document last step (#8979)
Co-authored-by: Philip Allgaier <[email protected]>
2021-04-26 12:02:56 +02:00
GitHub Action 959f7ae046 Translation update 2021-04-25 00:48:30 +00:00
GitHub Action 9572a58764 Translation update 2021-04-24 00:48:31 +00:00
Paulus Schoutsen 393ae9e5dc Bumped version to 20210423.0 2021-04-23 15:23:32 -07:00
63e10314bd Sketch out strategies (#8959)
Co-authored-by: Zack Arnett <[email protected]>
2021-04-23 09:36:45 -07:00
Paulus SchoutsenandGitHub b599417a37 Improve rendering status text on integration cards (#8973) 2021-04-23 09:30:17 +02:00
Philip AllgaierandGitHub 899eab4e5c Ensure 0 does not get formatted to empty string (#8971) 2021-04-23 09:29:03 +02:00
Paulus SchoutsenandGitHub 3f21c87a3d Allow config entries to show the reason (#8974) 2021-04-23 09:25:09 +02:00
GitHub Action c296a60bab Translation update 2021-04-23 00:48:28 +00:00
Paulus SchoutsenandGitHub 5f78f18cb4 Fix rendering of a choose without any action taken (#8952) 2021-04-22 21:01:09 +02:00
Paulus SchoutsenandGitHub 0b8d356865 Clean up HUI-VIEW (#8967) 2021-04-22 09:46:15 -07:00
Bram KragtenandGitHub e8d1318a5b Bump codemirror (#8953)
Fixes #8557
2021-04-21 19:22:56 +02:00
GitHub Action 07ce07c4a5 Translation update 2021-04-21 00:48:45 +00:00
Franck NijhofandGitHub a07220f383 Update GitHub issue form (#8954) 2021-04-20 12:37:59 +02:00
J. Nick KostonandGitHub f21ed24a49 Make error optional in connection lost service check (#8937) 2021-04-20 10:58:39 +02:00
GitHub Action e3c38b93f4 Translation update 2021-04-20 00:48:22 +00:00
Aaron GodfreyandGitHub b398727413 Allow falsey values for attribute value in a picture-elements card element. (#8943) 2021-04-19 18:51:55 +02:00
9bc2ab29a1 Version bump hls.js to v1.0.1 (#8951)
Co-authored-by: Bram Kragten <[email protected]>
2021-04-19 17:25:19 +02:00
GitHub Action 51f1ff26f1 Translation update 2021-04-19 00:48:51 +00:00
Bram KragtenandGitHub 97d5e6512d Fix link to config panels (#8936) 2021-04-17 22:12:07 -07:00
GitHub Action b76c67fc9b Translation update 2021-04-18 00:48:53 +00:00
Paulus SchoutsenandGitHub b96a70cd55 Make the integration header banner smaller (#8935) 2021-04-16 23:51:48 -07:00
Paulus SchoutsenandGitHub 982ab93cdb Do not vertically align integration icon (#8934) 2021-04-16 23:16:20 -07:00
Paulus SchoutsenandGitHub c7f4e1152d Pass manifest to config flow card (#8933) 2021-04-16 23:02:29 -07:00
J. Nick KostonandGitHub 519988326b Do not throw warnings when a service calls disconnects the websocket (#8932) 2021-04-16 20:59:10 -07:00
GitHub Action b518f4b03c Translation update 2021-04-17 00:48:32 +00:00
Paulus Schoutsen 5493fdfcb7 Bumped version to 20210416.0 2021-04-16 12:27:18 -07:00
Paulus SchoutsenandGitHub 179767e9f8 Align layout of all cards (#8931)
* Align layout of all cards

* Make ignore card have normal button
2021-04-16 12:27:01 -07:00
Paulus SchoutsenandGitHub 25b3bb1285 Fixes for integration cards (#8930) 2021-04-16 20:22:22 +02:00
Bram KragtenandGitHub 841c8ab1f1 Update script editor (#8919) 2021-04-16 08:57:07 -07:00
Philip AllgaierandGitHub 1ce17e2847 Remove non effective CSS for CM6 search panel input (#8921) 2021-04-16 16:29:36 +02:00
Philip AllgaierandGitHub a09b206b0e Added missing <ul> to beta join dialog (#8927) 2021-04-16 16:06:52 +02:00
Carlos Garcia SauraandGitHub bb4617c53b Correct two swapped supervisor beta join action/confirm texts (#8922) 2021-04-16 14:54:39 +02:00
Philip AllgaierandGitHub cfd18bfb74 Corrected "not loaded" state string (#8925) 2021-04-16 14:45:40 +02:00
Philip AllgaierandGitHub e225d6f546 Correct wording from "component" to "integration" on new integration page (#8924) 2021-04-16 14:41:38 +02:00
Paulus SchoutsenandGitHub 60fe48d355 Show config entry state on card (#8911) 2021-04-16 13:16:59 +02:00
GitHub Action 2dcd0d2b0a Translation update 2021-04-16 00:48:38 +00:00
Bram KragtenandGitHub 8e11aa9130 Fix activate scene button + allow removing icon (#8916) 2021-04-15 13:02:09 +02:00
Philip AllgaierandGitHub f6e223c18d Use const everywhere for "group.default_view" (#8918) 2021-04-15 09:54:32 +02:00
Bram KragtenandGitHub 9d29b55bee Add z-index to add user dialog (#8917) 2021-04-15 09:46:19 +02:00
GitHub Action 92aa8580db Translation update 2021-04-15 00:48:36 +00:00
DonnieandGitHub 538028a003 Refactor sequence matching to accept item rather than word array (#8866)
* Refactor sequence matching to require an item rather than array of words to filter against

* change 'words' to 'strings'. Add tsdoc description for ScorableTextItem

* Replace type checking with 'as' to clean up code
2021-04-14 15:29:10 -07:00
Carlos Garcia SauraandGitHub c53575a74f Set standard name for Cancel button, to align translations (#8914) 2021-04-14 23:09:31 +02:00
193016a46a Fix time selector + base am/pm on user language (#8908)
Co-authored-by: Paulus Schoutsen <[email protected]>
2021-04-14 21:51:29 +02:00
Bram KragtenandGitHub aaa50b4d1d Don't add toast to history (#8915) 2021-04-14 12:01:42 -07:00
Bram KragtenandGitHub a43120320e Bump typescript to 4.2.4 (#8876) 2021-04-14 12:00:24 -07:00
b8bb0c038d Highlight if log comes from custom component (#8912)
Co-authored-by: Joakim Sørensen <[email protected]>
2021-04-14 11:59:00 -07:00
GitHub Action dc79fc2919 Translation update 2021-04-14 00:48:24 +00:00
Philip AllgaierandGitHub 30787fef60 Hide new light color mode attributes in more-info (#8895) 2021-04-13 20:23:58 +02:00
J. Nick KostonandGitHub 445ae156ef Unsubscribe when dismissing during wrap up (#8909) 2021-04-13 20:18:37 +02:00
62a0cfb0f6 Fix computing cards (#8894)
Co-authored-by: Bram Kragten <[email protected]>
2021-04-13 16:25:48 +02:00
LJUandGitHub 96bc3ef99a Improve spelling (#8901) 2021-04-13 15:49:53 +02:00
GitHub Action 1d3b95d24f Translation update 2021-04-13 00:49:02 +00:00
Bram KragtenandGitHub 56fe4b07f3 Show toast with call service error (#8904) 2021-04-12 17:10:25 -07:00
Jakub DąbrowskiandGitHub ea60f7005b Fix saving entities of the device in scene editor (#8884) 2021-04-12 23:04:35 +02:00
Philip AllgaierandGitHub 9eb59062aa Increase supervisor metric value span width to account for blank (#8885) 2021-04-12 23:02:09 +02:00
Bram KragtenandGitHub d00927c31f Update codemirror (#8903) 2021-04-12 22:04:58 +02:00
Charles GarwoodandGitHub c03017208d Remove link/text about ZHA/Z-Wave config panels moving to integration page (#8867) 2021-04-12 20:17:31 +02:00
GitHub Action 73f945458a Translation update 2021-04-12 00:48:46 +00:00
GitHub Action db12234611 Translation update 2021-04-11 00:48:30 +00:00
GitHub Action ed1cd4632f Translation update 2021-04-10 00:48:37 +00:00
Bram Kragten 17d3755152 Bumped version to 20210407.3 2021-04-09 20:05:32 +02:00
Paulus SchoutsenandBram Kragten d7c0c2ea72 Fix failed conditions reason (#8870) 2021-04-09 20:05:17 +02:00
7c823c98ae Add units to Z-Wave JS Node Config inputs (#8869)
Co-authored-by: Paulus Schoutsen <[email protected]>
2021-04-09 20:04:56 +02:00
Bram Kragten 97508a6f31 Update value of date input (#8865) 2021-04-09 20:04:29 +02:00
Paulus SchoutsenandBram Kragten 2507a41b6e Pass narrow (#8864) 2021-04-09 20:04:03 +02:00
Paulus SchoutsenandGitHub 9833accc79 Fix failed conditions reason (#8870) 2021-04-08 23:01:12 -07:00
GitHub Action d46123771a Translation update 2021-04-09 00:48:50 +00:00
87fe84b1ac Add units to Z-Wave JS Node Config inputs (#8869)
Co-authored-by: Paulus Schoutsen <[email protected]>
2021-04-08 16:32:47 -07:00
Bram KragtenandGitHub 21140f437e Update value of date input (#8865) 2021-04-08 16:31:46 -07:00
Paulus SchoutsenandGitHub ba9e410393 Pass narrow (#8864) 2021-04-08 22:59:24 +02:00
Paulus SchoutsenandBram Kragten 9b628546c1 Remove owner guard from analytics (#8842) 2021-04-08 21:00:00 +02:00
Bram Kragten d0837fada8 Bumped version to 20210407.2 2021-04-08 20:56:03 +02:00
Paulus SchoutsenandBram Kragten 520647d72f Add logbook note (#8843)
Co-authored-by: Bram Kragten <[email protected]>
2021-04-08 20:55:10 +02:00
Bram KragtenandPaulus Schoutsen 51c888845c Handle choose being null (#8859)
Co-authored-by: Paulus Schoutsen <[email protected]>
2021-04-08 20:54:51 +02:00
Bram Kragten e4606219bc Check if logbook component loaded when fetching trace (#8861) 2021-04-08 20:54:34 +02:00
Philip AllgaierandBram Kragten 716335df2c Use number format setting for attribute rows (#8844) 2021-04-08 20:54:14 +02:00
Philip AllgaierandBram Kragten ad4f90c502 Mention unique ID requirement in trace button tooltip (#8853) 2021-04-08 20:53:57 +02:00
DonnieandBram Kragten a1bdfa7560 Fix spinner regression and remove unnecessary twoline config (#8847) 2021-04-08 20:53:43 +02:00
587fb2a170 Add logbook note (#8843)
Co-authored-by: Bram Kragten <[email protected]>
2021-04-08 20:52:37 +02:00
7d801ff84c Handle choose being null (#8859)
Co-authored-by: Paulus Schoutsen <[email protected]>
2021-04-08 20:48:49 +02:00
Bram KragtenandGitHub d69accd9a5 Add dev import buttons for debugging traces (#8860) 2021-04-08 11:32:31 -07:00
1127750c5e Show which integrations are being setup at startup (#8834)
Co-authored-by: Bram Kragten <[email protected]>
2021-04-08 07:30:47 -10:00
Bram KragtenandGitHub 7758bd89c1 Check if logbook component loaded when fetching trace (#8861) 2021-04-08 09:04:08 -07:00
Philip AllgaierandGitHub de7264327a Do not use "media_play_pause" but atomic services instead (#8845) 2021-04-08 16:47:04 +02:00
Philip AllgaierandGitHub c3f0932794 Use number format setting for attribute rows (#8844) 2021-04-08 10:52:10 +02:00
Philip AllgaierandGitHub 367907e037 Mention unique ID requirement in trace button tooltip (#8853) 2021-04-08 09:47:25 +02:00
DonnieandGitHub 2d15bd651e Fix spinner regression and remove unnecessary twoline config (#8847) 2021-04-07 21:18:55 -07:00
GitHub Action 4b1d7863f8 Translation update 2021-04-08 00:48:34 +00:00
Paulus SchoutsenandGitHub e425d768dd Remove owner guard from analytics (#8842) 2021-04-07 18:41:39 +02:00
Joakim SørensenandGitHub 34ca807044 Merge pull request #8841 from home-assistant/dev 2021-04-07 16:36:31 +02:00
Bram Kragten 9075146b47 Bumped version to 20210407.1 2021-04-07 16:21:07 +02:00
Bram KragtenandGitHub 26c4591baa Keep root state when replacing, fix subpages for menu button on mobile (#8837) 2021-04-07 12:25:17 +02:00
Bram KragtenandGitHub 2aac8c55e7 Guard for trace component not loaded (#8838) 2021-04-07 12:21:19 +02:00
Bram KragtenandGitHub 8af55efdb3 Merge pull request #8836 from home-assistant/dev 2021-04-07 10:43:35 +02:00
Bram Kragten 9d6e07ff96 Bumped version to 20210407.0 2021-04-07 10:07:35 +02:00
Bram Kragten 8f58eee6af Update hui-timer-entity-row.ts 2021-04-07 10:07:17 +02:00
Paulus SchoutsenandGitHub 8dd3d78f21 Tweak the analytics screens (#8833) 2021-04-07 03:48:10 +02:00
GitHub Action 48161fd02f Translation update 2021-04-07 00:48:35 +00:00
Joakim SørensenandGitHub b61410826d Add AppArmor reason (#8829) 2021-04-07 02:05:27 +02:00
Jaroslav HanslíkandGitHub 2f0188b280 Fixed generic entity row for climate entities (#8369) 2021-04-06 22:31:47 +02:00
Bram KragtenandGitHub 3a4fffdb0b Remove dynamic height/width calcs on graph nodes (#8832) 2021-04-06 22:31:22 +02:00
Paulus SchoutsenandGitHub 6393072e68 Merge pull request #8826 from home-assistant/dev 2021-04-06 09:49:27 -07:00
Bram KragtenandGitHub 109910d18f Add spacer for default of choose (#8827) 2021-04-06 09:32:30 -07:00
Paulus Schoutsen 8874aaabe9 Bumped version to 20210406.0 2021-04-06 16:13:04 +00:00
Bram KragtenandGitHub cafbea9c42 Update quick bar (#8823) 2021-04-06 09:05:29 -07:00
Bram KragtenandGitHub 4843ee80a7 Use checkmark only in chosen choose (#8824) 2021-04-06 09:03:04 -07:00
4511c8f30c Don't show back button when no history (#8822)
* Don't show back button when no history

* Update src/translations/en.json

Co-authored-by: Philip Allgaier <[email protected]>

Co-authored-by: Philip Allgaier <[email protected]>
2021-04-06 08:59:08 -07:00
Thomas LovénandGitHub 4cf1e52ac0 Select one branch at a time in choose script graphs (#8812) 2021-04-06 14:38:42 +02:00
Bram KragtenandGitHub b501b7f47c Change date picker (#8821) 2021-04-06 05:36:12 -07:00
Philip AllgaierandGitHub cc275f9877 Prevent unwanted line breaks in picture-glance tooltips (#8819) 2021-04-06 14:19:24 +02:00
Philip AllgaierandGitHub 7aae55cde7 Allow manually entering entity IDs in service target entity picker (#8820) 2021-04-06 14:18:55 +02:00
GitHub Action 85eaa219c6 Translation update 2021-04-06 00:48:51 +00:00
DonnieandGitHub 7d5ecb8ba4 Update fuzzy scorer from VSCode (#8793) 2021-04-05 12:15:09 -07:00
GitHub Action 1fd142d337 Translation update 2021-04-05 00:48:55 +00:00
Josh McCartyandGitHub d75c6aecbe Format input number (#8811) 2021-04-04 20:47:08 +02:00
Bram KragtenandGitHub dffe0f656d Update styling trace tabs (#8807) 2021-04-03 23:19:06 -07:00
GitHub Action 890639436b Translation update 2021-04-04 00:48:42 +00:00
Charles GarwoodandGitHub 99f66d7c5d Fix zwave_js config panel manual entry inputs (#8806) 2021-04-03 16:08:41 +02:00
GitHub Action 05faa52425 Translation update 2021-04-03 00:48:30 +00:00
Bram KragtenandGitHub 9e1a8b646b Merge pull request #8803 from home-assistant/dev
20210402.1
2021-04-02 21:15:13 +02:00
Bram Kragten 8f6ec03446 Bumped version to 20210402.1 2021-04-02 20:48:57 +02:00
Bram KragtenandGitHub c56b4fade3 Add filtering by related entity + fixes (#8801) 2021-04-02 20:35:28 +02:00
Bram KragtenandGitHub 61aaaabcb5 Add close button to import blueprint dialog (#8802) 2021-04-02 20:19:35 +02:00
Bram KragtenandGitHub d57cf93580 Fix disabled icon button color (#8800)
Fixes #8797
2021-04-02 20:18:56 +02:00
Paulus SchoutsenandGitHub 82ad5c103d Handle configurations that don't wrap their action sequences in arrays (#8798) 2021-04-02 14:45:34 +02:00
GitHub Action a0b5bc5456 Translation update 2021-04-02 00:48:47 +00:00
Paulus SchoutsenandGitHub c810e541ea Merge pull request #8795 from home-assistant/dev 2021-04-01 15:33:43 -07:00
Bram KragtenandGitHub 05ea3b8187 Make version number based on UTC time (#8796) 2021-04-01 15:33:11 -07:00
Bram Kragten 8301dffb21 Bumped version to 20210402.0 2021-04-02 00:14:02 +02:00
Bram KragtenandGitHub 01be5243de Option flows dont have result (#8787) 2021-04-01 15:11:15 -07:00
Paulus SchoutsenandGitHub 334196799a Improve keyboard nav (#8794) 2021-04-02 00:10:17 +02:00
c11bbcf442 Add blueprint config to trace (#8751)
Co-authored-by: Paulus Schoutsen <[email protected]>
2021-04-01 23:37:46 +02:00
8e3a7576ea Align has template functions (#8784)
Co-authored-by: Paulus Schoutsen <[email protected]>
2021-04-01 13:49:59 -07:00
deca6f03ba Improve ensureArray and use it in tracing (#8785)
* Improve ensureArray and use it in tracing

* Fix typing

Co-authored-by: Paulus Schoutsen <[email protected]>
2021-04-01 13:33:47 -07:00
Paulus SchoutsenandGitHub 401064d3c8 Render script execution state (#8789) 2021-04-01 11:29:08 -07:00
Paulus SchoutsenandGitHub b6f59d3c98 Fix the automation picker icons (#8790) 2021-04-01 11:28:56 -07:00
Bram KragtenandGitHub 1fb3663398 Add sortable last trigger column to automation and script overview (#8783) 2021-04-01 09:02:58 -07:00
Paulus SchoutsenandGitHub 5c1604e959 Fix showing choose actions if default path chosen and other things (#8779) 2021-04-01 10:28:37 +02:00
GitHub Action 17b1f3e465 Translation update 2021-04-01 00:48:39 +00:00
Bram KragtenandGitHub 9a68bdeec1 Handle errors in trace (#8775) 2021-03-31 09:35:30 -07:00
Bram KragtenandGitHub 9b947ef734 Add top level logbook entries tab (#8776) 2021-03-31 09:15:06 -07:00
Bram KragtenandGitHub 66432608ed Merge pull request #8774 from home-assistant/dev 2021-03-31 17:27:43 +02:00
Bram KragtenandGitHub d8153ac8fc Merge branch 'master' into dev 2021-03-31 17:02:45 +02:00
Bram Kragten 27d9f82f7d Bumped version to 20210331.0 2021-03-31 16:59:29 +02:00
Bram KragtenandGitHub 5b55bcd879 Use logbook for trace logbook items (#8773) 2021-03-31 16:57:48 +02:00
Bram Kragten 5cfd28881b Update cloud-google-pref.ts 2021-03-31 16:53:18 +02:00
Philip AllgaierandGitHub bc54a42e01 Fix typo in analytics info text (#8772) 2021-03-31 15:55:29 +02:00
Bram KragtenandGitHub 03f9964c59 Fix max being undefined in automation (#8771) 2021-03-31 15:36:09 +02:00
f159219d2c Add Lovelace edit mode URL param (#8574)
Co-authored-by: Bram Kragten <[email protected]>
2021-03-31 15:10:55 +02:00
e714f32737 Refactoring automation trace graphs (#8763)
Co-authored-by: Paulus Schoutsen <[email protected]>
Co-authored-by: Bram Kragten <[email protected]>
2021-03-31 15:09:00 +02:00
Philip AllgaierandGitHub 20858db96d Use service name in action confirmation popup (#8493) 2021-03-31 14:12:06 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
89b82bb778 Bump y18n from 3.2.1 to 3.2.2 (#8765)
Bumps [y18n](https://github.com/yargs/y18n) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-31 11:16:55 +02:00
David F. MulcaheyandGitHub 2c886d739f Add feedback dialog for ZHA device reconfiguration (#8742)
* Add feedback dialog for ZHA device reconfiguration

* review comments

* fix scope
2021-03-31 11:16:35 +02:00
GitHub Action 1ccf4e49bc Translation update 2021-03-31 00:48:38 +00:00
Joakim SørensenandGitHub 7d63e3e088 Hide system generated integration options (#8764) 2021-03-30 23:09:08 +02:00
Joakim SørensenandGitHub 828523f281 Adjust documentation link (#8762) 2021-03-30 21:52:15 +02:00
Philip AllgaierandGitHub afe3831f25 Make log levels translatable (#8761) 2021-03-30 20:19:50 +02:00
Philip AllgaierandGitHub 3888c56f1a Add padding when loading traces or none found (#8760) 2021-03-30 20:16:06 +02:00
Bram Kragten 6f07966ef8 Update en.json 2021-03-30 10:48:04 +02:00
GitHub Action 09eafe8abd Translation update 2021-03-30 00:48:42 +00:00
Paulus Schoutsen 6719a42e27 Bumped version to 20210330.0 2021-03-30 00:15:58 +00:00
Bram KragtenandGitHub 4b98a70ee8 Fix rendering when selecting all in datatable (#8749)
Fixes #8619
2021-03-29 17:15:08 -07:00
Bram KragtenandGitHub db3f5447ca Add filtering by devices/areas to scripts (#8748) 2021-03-29 17:14:02 -07:00
Bram KragtenandGitHub fed63f645d Add filtering by devices/areas to scenes (#8747) 2021-03-29 17:09:50 -07:00
Bram KragtenandGitHub e7315bb570 Align filtering of integrations with other pages (#8746) 2021-03-29 17:07:11 -07:00
Bram KragtenandGitHub cd2404f26a Add link between trace and editor (#8750) 2021-03-29 17:05:51 -07:00
Paulus SchoutsenandGitHub b866166425 Adjust for latest trace API (#8755) 2021-03-29 17:01:39 -07:00
Bram KragtenandGitHub 46580376dd Make trace somewhat useable on mobile (#8752) 2021-03-29 16:59:31 -07:00
Thomas LovénandGitHub b8bfb44aec Rename layout to view_layout (#8714) 2021-03-29 14:28:58 -07:00
Bram KragtenandGitHub a153f572d0 Add screenshot for manifest (#8753) 2021-03-29 13:12:55 -07:00
66c30a59e7 Check if Google Assistant is linked (#8613)
Co-authored-by: Paulus Schoutsen <[email protected]>
2021-03-29 19:27:45 +02:00
Bram KragtenandGitHub 10b8efc5cb Add filtering to automaton overview (#8736)
* Add filtering to automaton overview

* Update ha-automation-picker.ts

* Update ha-combo-box.ts

* imports

* Rename component

* localize + comments
2021-03-29 14:33:48 +02:00
Bram KragtenandGitHub c65d414b7b Show if config entry is not loaded (#8717) 2021-03-29 11:33:41 +02:00
Bram KragtenandGitHub 7f7d89c745 Hopefully fix some back button issues (#8708) 2021-03-29 11:29:43 +02:00
742028b691 Add analytics integration (#8695)
Co-authored-by: Bram Kragten <[email protected]>
Co-authored-by: Philip Allgaier <[email protected]>
2021-03-29 09:47:04 +02:00
GitHub Action 62f685bac2 Translation update 2021-03-29 00:48:39 +00:00
Bram Kragten 9bdda77e89 Fix demo states translation (#8586) 2021-03-08 13:04:58 +01:00
Bram Kragten fa7bd28c92 Bumped version to 20210302.6 2021-03-07 23:20:37 +01:00
Philip AllgaierandBram Kragten 279f78e4a8 Ensure dev-tools state attribute checkbox state gets stored (#8579) 2021-03-07 23:19:13 +01:00
Bram Kragten 8ec3cbdb33 Fix codemirror cursor color (#8571) 2021-03-07 23:18:55 +01:00
Philip AllgaierandBram Kragten 7449f7e73f Handle delay templates properly + error handling tweaks (#8578)
Co-authored-by: Bram Kragten <[email protected]>
2021-03-07 23:17:05 +01:00
Bram Kragten d680fde759 Don't allow UI editor for service calls with templates (#8581) 2021-03-07 23:16:49 +01:00
Bram Kragten ba77a88714 Bumped version to 20210302.5 2021-03-05 17:27:46 +01:00
Bram Kragten 9b39087102 Fix codemirror active line (#8558)
fixes #8556
2021-03-05 17:27:14 +01:00
Bram Kragten a00961b9ef Bumped version to 20210302.4 2021-03-04 17:03:14 +01:00
Bram Kragten 701c188bab Bump codemirror to 0.18 (#8546) 2021-03-04 17:02:51 +01:00
Bram Kragten e81002807f Add max height to yaml editor (#8527) 2021-03-04 17:02:33 +01:00
Bram Kragten e14d652651 Bumped version to 20210302.3 2021-03-03 13:19:12 +01:00
Bram Kragten 98ae5270ef Bumped version to 20210302.2 2021-03-03 12:50:25 +01:00
Bram Kragten 19ccf0ab40 Bump codemirror (#8524) 2021-03-03 12:50:16 +01:00
Bram Kragten 6021bec5ee Bumped version to 20210302.1 2021-03-03 10:42:45 +01:00
Bram Kragten 7fcadc85fa Dont show config changes when user saved it (#8520) 2021-03-03 10:42:13 +01:00
Bram KragtenandGitHub 5d7f971a82 Merge pull request #8517 from home-assistant/dev 2021-03-02 16:16:22 +01:00
Bram KragtenandGitHub c42430ccf9 Merge pull request #8509 from home-assistant/dev 2021-03-01 23:33:33 +01:00
Bram KragtenandGitHub 16fa6904d9 Merge pull request #8474 from home-assistant/dev 2021-02-26 22:05:19 +01:00
Bram KragtenandGitHub 12a8a1531d Merge pull request #8459 from home-assistant/dev 2021-02-25 18:54:46 +01:00
c85f69c9ee Merge pull request #8448 from home-assistant/dev
Co-authored-by: Bram Kragten <[email protected]>
Co-authored-by: Philip Allgaier <[email protected]>
Co-authored-by: J. Nick Koston <[email protected]>
Co-authored-by: GitHub Action <[email protected]>
Co-authored-by: Joakim Sørensen <[email protected]>
Co-authored-by: Álvaro Fernández Rojas <[email protected]>
Co-authored-by: Marc Mueller <[email protected]>
Co-authored-by: Kendell R <[email protected]>
Co-authored-by: larena1 <[email protected]>
2021-02-24 20:36:51 +01:00
Bram KragtenandGitHub 216526e391 Merge pull request #8433 from home-assistant/dev 2021-02-22 20:18:48 +01:00
Bram KragtenandGitHub 311e1cfb00 Merge pull request #8354 from home-assistant/dev 2021-02-08 15:28:40 +01:00
1028 changed files with 36805 additions and 21590 deletions
+25 -7
View File
@@ -4,8 +4,7 @@
"plugin:@typescript-eslint/recommended",
"plugin:wc/recommended",
"plugin:lit/recommended",
"prettier",
"prettier/@typescript-eslint"
"prettier"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
@@ -29,9 +28,7 @@
"__BUILD__": false,
"__VERSION__": false,
"__STATIC_PATH__": false,
"Polymer": true,
"webkitSpeechRecognition": false,
"ResizeObserver": false
"Polymer": true
},
"env": {
"browser": true,
@@ -84,8 +81,29 @@
"@typescript-eslint/no-unused-vars": 0,
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/no-shadow": ["error"]
"@typescript-eslint/no-shadow": ["error"],
"@typescript-eslint/naming-convention": [
0,
{
"selector": "default",
"format": ["camelCase", "snake_case"],
"leadingUnderscore": "allow",
"trailingUnderscore": "allow"
},
{
"selector": ["variable"],
"format": ["camelCase", "snake_case", "UPPER_CASE"],
"leadingUnderscore": "allow",
"trailingUnderscore": "allow"
},
{
"selector": "typeLike",
"format": ["PascalCase"]
}
],
"lit/attribute-value-entities": 0
},
"plugins": ["disable", "import", "lit", "prettier", "@typescript-eslint"],
"processor": "disable/disable"
"processor": "disable/disable",
"ignorePatterns": ["src/resources/lit-virtualizer/*"]
}
+9 -26
View File
@@ -1,8 +1,6 @@
name: Report a bug with the UI, Frontend or Lovelace
about: Report an issue related to the Home Assistant frontend.
description: Report an issue related to the Home Assistant frontend.
labels: bug
title: ""
issue_body: true
body:
- type: markdown
attributes:
@@ -97,11 +95,7 @@ body:
If your issue is about how an entity is shown in the UI, please add the
state and attributes for all situations. You can find this information
at Developer Tools -> States.
value: |
```yaml
# Paste your state here.
```
render: txt
- type: textarea
attributes:
label: Problem-relevant frontend configuration
@@ -110,29 +104,18 @@ body:
configuration of the used cards. Fill this out even if it seems
unimportant to you. Please be sure to remove personal information like
passwords, private URLs and other credentials.
value: |
```yaml
# Paste your YAML here.
```
render: yaml
- type: textarea
attributes:
label: Javascript errors shown in your browser console/inspector
description: >
If you come across any Javascript or other error logs, e.g., in your
browser console/inspector please provide them.
value: |
```txt
# Paste your logs here.
```
- type: markdown
render: txt
- type: textarea
attributes:
value: |
## Additional information
- type: markdown
attributes:
value: |
label: Additional information
description: >
If you have any additional information for us, use the field below.
Please note, you can attach screenshots or screen recordings here,
by dragging and dropping files in the field below.
Please note, you can attach screenshots or screen recordings here, by
dragging and dropping files in the field below.
+4 -2
View File
@@ -37,9 +37,11 @@ jobs:
- name: Build resources
run: ./node_modules/.bin/gulp gen-icons-json build-translations gather-gallery-demos
- name: Run eslint
run: ./node_modules/.bin/eslint '{**/src,src}/**/*.{js,ts,html}' --ignore-path .gitignore
run: yarn run lint:eslint
- name: Run tsc
run: ./node_modules/.bin/tsc
run: yarn run lint:types
- name: Run prettier
run: yarn run lint:prettier
test:
runs-on: ubuntu-latest
steps:
+5 -3
View File
@@ -6,8 +6,7 @@ on:
- published
env:
WHEELS_TAG: 3.7-alpine3.11
PYTHON_VERSION: 3.7
PYTHON_VERSION: 3.8
NODE_VERSION: 12.1
jobs:
@@ -64,6 +63,9 @@ jobs:
strategy:
matrix:
arch: ["aarch64", "armhf", "armv7", "amd64", "i386"]
tag:
- "3.8-alpine3.12"
- "3.9-alpine3.13"
steps:
- name: Download requirements.txt
uses: actions/download-artifact@v2
@@ -73,7 +75,7 @@ jobs:
- name: Build wheels
uses: home-assistant/wheels@master
with:
tag: ${{ env.WHEELS_TAG }}
tag: ${{ matrix.tag }}
arch: ${{ matrix.arch }}
wheels-host: ${{ secrets.WHEELS_HOST }}
wheels-key: ${{ secrets.WHEELS_KEY }}
+12 -9
View File
@@ -1,10 +1,17 @@
.DS_Store
.reify-cache
# build
build
build-translations/*
hass_frontend/*
dist
# yarn
.yarn
yarn-error.log
node_modules/*
npm-debug.log
.DS_Store
hass_frontend/*
.reify-cache
# Python stuff
*.py[cod]
@@ -14,11 +21,8 @@ hass_frontend/*
# venv stuff
pyvenv.cfg
pip-selfcheck.json
venv
venv/*
.venv
lib
bin
dist
# vscode
.vscode/*
@@ -31,9 +35,8 @@ src/cast/dev_const.ts
# Secrets
.lokalise_token
yarn-error.log
#asdf
# asdf
.tool-versions
# Home Assistant config
+4
View File
@@ -0,0 +1,4 @@
module.exports = {
require: "test-mocha/testconf.js",
timeout: 10000,
};
+7 -16
View File
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path");
const env = require("./env.js");
const paths = require("./paths.js");
@@ -51,15 +52,16 @@ module.exports.terserOptions = (latestBuild) => ({
module.exports.babelOptions = ({ latestBuild }) => ({
babelrc: false,
compact: false,
presets: [
!latestBuild && [
require("@babel/preset-env").default,
"@babel/preset-env",
{
useBuiltIns: "entry",
corejs: "3.6",
},
],
require("@babel/preset-typescript").default,
"@babel/preset-typescript",
].filter(Boolean),
plugins: [
// Part of ES2018. Converts {...a, b: 2} to Object.assign({}, a, {b: 2})
@@ -72,23 +74,12 @@ module.exports.babelOptions = ({ latestBuild }) => ({
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
[
require("@babel/plugin-proposal-decorators").default,
{ decoratorsBeforeExport: true },
],
[
require("@babel/plugin-proposal-class-properties").default,
{ loose: true },
],
["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }],
["@babel/plugin-proposal-private-methods", { loose: true }],
["@babel/plugin-proposal-class-properties", { loose: true }],
].filter(Boolean),
});
// Are already ES5, cause warnings when babelified.
module.exports.babelExclude = () => [
require.resolve("@mdi/js/mdi.js"),
require.resolve("hls.js"),
];
const outputPath = (outputRoot, latestBuild) =>
path.resolve(outputRoot, latestBuild ? "frontend_latest" : "frontend_es5");
+1
View File
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const fs = require("fs");
const path = require("path");
const paths = require("./paths.js");
+1
View File
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path");
module.exports = {
+77 -94
View File
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path");
const commonjs = require("@rollup/plugin-commonjs");
@@ -32,88 +33,77 @@ const createRollupConfig = ({
publicPath,
dontHash,
isWDS,
}) => {
return {
/**
* @type { import("rollup").InputOptions }
*/
inputOptions: {
input: entry,
// Some entry points contain no JavaScript. This setting silences a warning about that.
// https://rollupjs.org/guide/en/#preserveentrysignatures
preserveEntrySignatures: false,
plugins: [
ignore({
files: bundle.emptyPackages({ latestBuild }),
}) => ({
/**
* @type { import("rollup").InputOptions }
*/
inputOptions: {
input: entry,
// Some entry points contain no JavaScript. This setting silences a warning about that.
// https://rollupjs.org/guide/en/#preserveentrysignatures
preserveEntrySignatures: false,
plugins: [
ignore({
files: bundle.emptyPackages({ latestBuild }),
}),
resolve({
extensions,
preferBuiltins: false,
browser: true,
rootDir: paths.polymer_dir,
}),
commonjs(),
json(),
babel({
...bundle.babelOptions({ latestBuild }),
extensions,
babelHelpers: isWDS ? "inline" : "bundled",
}),
string({
// Import certain extensions as strings
include: [path.join(paths.polymer_dir, "node_modules/**/*.css")],
}),
replace(bundle.definedVars({ isProdBuild, latestBuild, defineOverlay })),
!isWDS &&
manifest({
publicPath,
}),
resolve({
extensions,
preferBuiltins: false,
browser: true,
rootDir: paths.polymer_dir,
!isWDS && worker(),
!isWDS && dontHashPlugin({ dontHash }),
!isWDS && isProdBuild && terser(bundle.terserOptions(latestBuild)),
!isWDS &&
isStatsBuild &&
visualizer({
// https://github.com/btd/rollup-plugin-visualizer#options
open: true,
sourcemap: true,
}),
commonjs({
namedExports: {
"js-yaml": ["safeDump", "safeLoad"],
},
}),
json(),
babel({
...bundle.babelOptions({ latestBuild }),
extensions,
exclude: bundle.babelExclude(),
babelHelpers: isWDS ? "inline" : "bundled",
}),
string({
// Import certain extensions as strings
include: [path.join(paths.polymer_dir, "node_modules/**/*.css")],
}),
replace(
bundle.definedVars({ isProdBuild, latestBuild, defineOverlay })
),
!isWDS &&
manifest({
publicPath,
}),
!isWDS && worker(),
!isWDS && dontHashPlugin({ dontHash }),
!isWDS && isProdBuild && terser(bundle.terserOptions(latestBuild)),
!isWDS &&
isStatsBuild &&
visualizer({
// https://github.com/btd/rollup-plugin-visualizer#options
open: true,
sourcemap: true,
}),
].filter(Boolean),
},
/**
* @type { import("rollup").OutputOptions }
*/
outputOptions: {
// https://rollupjs.org/guide/en/#outputdir
dir: outputPath,
// https://rollupjs.org/guide/en/#outputformat
format: latestBuild ? "es" : "systemjs",
// https://rollupjs.org/guide/en/#outputexternallivebindings
externalLiveBindings: false,
// https://rollupjs.org/guide/en/#outputentryfilenames
// https://rollupjs.org/guide/en/#outputchunkfilenames
// https://rollupjs.org/guide/en/#outputassetfilenames
entryFileNames:
isProdBuild && !isStatsBuild ? "[name]-[hash].js" : "[name].js",
chunkFileNames:
isProdBuild && !isStatsBuild ? "c.[hash].js" : "[name].js",
assetFileNames:
isProdBuild && !isStatsBuild ? "a.[hash].js" : "[name].js",
// https://rollupjs.org/guide/en/#outputsourcemap
sourcemap: isProdBuild ? true : "inline",
},
};
};
].filter(Boolean),
},
/**
* @type { import("rollup").OutputOptions }
*/
outputOptions: {
// https://rollupjs.org/guide/en/#outputdir
dir: outputPath,
// https://rollupjs.org/guide/en/#outputformat
format: latestBuild ? "es" : "systemjs",
// https://rollupjs.org/guide/en/#outputexternallivebindings
externalLiveBindings: false,
// https://rollupjs.org/guide/en/#outputentryfilenames
// https://rollupjs.org/guide/en/#outputchunkfilenames
// https://rollupjs.org/guide/en/#outputassetfilenames
entryFileNames:
isProdBuild && !isStatsBuild ? "[name]-[hash].js" : "[name].js",
chunkFileNames: isProdBuild && !isStatsBuild ? "c.[hash].js" : "[name].js",
assetFileNames: isProdBuild && !isStatsBuild ? "a.[hash].js" : "[name].js",
// https://rollupjs.org/guide/en/#outputsourcemap
sourcemap: isProdBuild ? true : "inline",
},
});
const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild, isWDS }) => {
return createRollupConfig(
const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild, isWDS }) =>
createRollupConfig(
bundle.config.app({
isProdBuild,
latestBuild,
@@ -121,31 +111,24 @@ const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild, isWDS }) => {
isWDS,
})
);
};
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
return createRollupConfig(
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) =>
createRollupConfig(
bundle.config.demo({
isProdBuild,
latestBuild,
isStatsBuild,
})
);
};
const createCastConfig = ({ isProdBuild, latestBuild }) => {
return createRollupConfig(bundle.config.cast({ isProdBuild, latestBuild }));
};
const createCastConfig = ({ isProdBuild, latestBuild }) =>
createRollupConfig(bundle.config.cast({ isProdBuild, latestBuild }));
const createHassioConfig = ({ isProdBuild, latestBuild }) => {
return createRollupConfig(bundle.config.hassio({ isProdBuild, latestBuild }));
};
const createHassioConfig = ({ isProdBuild, latestBuild }) =>
createRollupConfig(bundle.config.hassio({ isProdBuild, latestBuild }));
const createGalleryConfig = ({ isProdBuild, latestBuild }) => {
return createRollupConfig(
bundle.config.gallery({ isProdBuild, latestBuild })
);
};
const createGalleryConfig = ({ isProdBuild, latestBuild }) =>
createRollupConfig(bundle.config.gallery({ isProdBuild, latestBuild }));
module.exports = {
createAppConfig,
+1
View File
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path");
const fs = require("fs");
+21 -23
View File
@@ -1,9 +1,10 @@
/* eslint-disable @typescript-eslint/no-var-requires */
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");
const bundle = require("./bundle.js");
const log = require("fancy-log");
class LogStartCompilePlugin {
@@ -46,7 +47,6 @@ const createWebpackConfig = ({
rules: [
{
test: /\.m?js$|\.ts$/,
exclude: bundle.babelExclude(),
use: {
loader: "babel-loader",
options: bundle.babelOptions({ latestBuild }),
@@ -94,6 +94,7 @@ const createWebpackConfig = ({
? path.resolve(context, resource)
: require.resolve(resource);
} catch (err) {
// eslint-disable-next-line no-console
console.error(
"Error in Home Assistant ignore plugin",
resource,
@@ -114,8 +115,9 @@ const createWebpackConfig = ({
// We need to change the import of the polyfill for EventTarget, so we replace the polyfill file with our customized one
new webpack.NormalModuleReplacementPlugin(
new RegExp(
require.resolve(
"lit-virtualizer/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.js"
path.resolve(
paths.polymer_dir,
"src/resources/lit-virtualizer/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.js"
)
),
path.resolve(paths.polymer_dir, "src/resources/EventTarget-ponyfill.js")
@@ -124,6 +126,11 @@ const createWebpackConfig = ({
].filter(Boolean),
resolve: {
extensions: [".ts", ".js", ".json"],
alias: {
"lit/decorators$": "lit/decorators.js",
"lit/directive$": "lit/directive.js",
"lit/polyfill-support$": "lit/polyfill-support.js",
},
},
output: {
filename: ({ chunk }) => {
@@ -144,33 +151,24 @@ const createWebpackConfig = ({
};
};
const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
return createWebpackConfig(
const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild }) =>
createWebpackConfig(
bundle.config.app({ isProdBuild, latestBuild, isStatsBuild })
);
};
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
return createWebpackConfig(
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) =>
createWebpackConfig(
bundle.config.demo({ isProdBuild, latestBuild, isStatsBuild })
);
};
const createCastConfig = ({ isProdBuild, latestBuild }) => {
return createWebpackConfig(bundle.config.cast({ isProdBuild, latestBuild }));
};
const createCastConfig = ({ isProdBuild, latestBuild }) =>
createWebpackConfig(bundle.config.cast({ isProdBuild, latestBuild }));
const createHassioConfig = ({ isProdBuild, latestBuild }) => {
return createWebpackConfig(
bundle.config.hassio({ isProdBuild, latestBuild })
);
};
const createHassioConfig = ({ isProdBuild, latestBuild }) =>
createWebpackConfig(bundle.config.hassio({ isProdBuild, latestBuild }));
const createGalleryConfig = ({ isProdBuild, latestBuild }) => {
return createWebpackConfig(
bundle.config.gallery({ isProdBuild, latestBuild })
);
};
const createGalleryConfig = ({ isProdBuild, latestBuild }) =>
createWebpackConfig(bundle.config.gallery({ isProdBuild, latestBuild }));
module.exports = {
createAppConfig,
+7 -17
View File
@@ -1,16 +1,9 @@
import "@material/mwc-button/mwc-button";
import "@polymer/paper-item/paper-icon-item";
import "@polymer/paper-listbox/paper-listbox";
import { Auth, Connection } from "home-assistant-js-websocket";
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
internalProperty,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { CastManager } from "../../../../src/cast/cast_manager";
import {
castSendShowLovelaceView,
@@ -32,7 +25,6 @@ import {
import "../../../../src/layouts/hass-loading-screen";
import { generateDefaultViewConfig } from "../../../../src/panels/lovelace/common/generate-lovelace-config";
import "./hc-layout";
import "@material/mwc-button/mwc-button";
@customElement("hc-cast")
class HcCast extends LitElement {
@@ -42,9 +34,9 @@ class HcCast extends LitElement {
@property() public castManager!: CastManager;
@internalProperty() private askWrite = false;
@state() private askWrite = false;
@internalProperty() private lovelaceConfig?: LovelaceConfig | null;
@state() private lovelaceConfig?: LovelaceConfig | null;
protected render(): TemplateResult {
if (this.lovelaceConfig === undefined) {
@@ -54,9 +46,7 @@ class HcCast extends LitElement {
const error =
this.castManager.castState === "NO_DEVICES_AVAILABLE"
? html`
<p>
There were no suitable Chromecast devices to cast to found.
</p>
<p>There were no suitable Chromecast devices to cast to found.</p>
`
: undefined;
@@ -206,7 +196,7 @@ class HcCast extends LitElement {
}
}
static get styles(): CSSResult {
static get styles(): CSSResultGroup {
return css`
.center-item {
display: flex;
+10 -19
View File
@@ -11,15 +11,8 @@ import {
getAuth,
getAuthOptions,
} from "home-assistant-js-websocket";
import {
css,
CSSResult,
customElement,
html,
LitElement,
TemplateResult,
internalProperty,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators";
import { CastManager, getCastManager } from "../../../../src/cast/cast_manager";
import { castSendShowDemo } from "../../../../src/cast/receiver_messages";
import {
@@ -60,19 +53,19 @@ const INTRO = html`
@customElement("hc-connect")
export class HcConnect extends LitElement {
@internalProperty() private loading = false;
@state() private loading = false;
// If we had stored credentials but we cannot connect,
// show a screen asking retry or logout.
@internalProperty() private cannotConnect = false;
@state() private cannotConnect = false;
@internalProperty() private error?: string | TemplateResult;
@state() private error?: string | TemplateResult;
@internalProperty() private auth?: Auth;
@state() private auth?: Auth;
@internalProperty() private connection?: Connection;
@state() private connection?: Connection;
@internalProperty() private castManager?: CastManager | null;
@state() private castManager?: CastManager | null;
private openDemo = false;
@@ -86,9 +79,7 @@ export class HcConnect extends LitElement {
</div>
<div class="card-actions">
<a href="/">
<mwc-button>
Retry
</mwc-button>
<mwc-button> Retry </mwc-button>
</a>
<div class="spacer"></div>
<mwc-button @click=${this._handleLogout}>Log out</mwc-button>
@@ -299,7 +290,7 @@ export class HcConnect extends LitElement {
}
}
static get styles(): CSSResult {
static get styles(): CSSResultGroup {
return css`
.card-content a {
color: var(--primary-color);
+3 -10
View File
@@ -4,15 +4,8 @@ import {
getUser,
HassUser,
} from "home-assistant-js-websocket";
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../../src/components/ha-card";
@customElement("hc-layout")
@@ -69,7 +62,7 @@ class HcLayout extends LitElement {
}
}
static get styles(): CSSResult {
static get styles(): CSSResultGroup {
return css`
:host {
display: flex;
+5 -10
View File
@@ -1,10 +1,5 @@
import {
customElement,
html,
internalProperty,
property,
TemplateResult,
} from "lit-element";
import { html, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { mockHistory } from "../../../../demo/src/stubs/history";
import { LovelaceConfig } from "../../../../src/data/lovelace";
import {
@@ -21,7 +16,7 @@ import "./hc-lovelace";
class HcDemo extends HassElement {
@property({ attribute: false }) public lovelacePath!: string;
@internalProperty() private _lovelaceConfig?: LovelaceConfig;
@state() private _lovelaceConfig?: LovelaceConfig;
protected render(): TemplateResult {
if (!this._lovelaceConfig) {
@@ -38,10 +33,10 @@ class HcDemo extends HassElement {
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
this._initialize();
this._initializeHass();
}
private async _initialize() {
private async _initializeHass() {
const initial: Partial<MockHomeAssistant> = {
// Override updateHass so that the correct hass lifecycle methods are called
updateHass: (hassUpdate: Partial<HomeAssistant>) =>
+3 -10
View File
@@ -1,12 +1,5 @@
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { HomeAssistant } from "../../../../src/types";
@customElement("hc-launch-screen")
@@ -29,7 +22,7 @@ class HcLaunchScreen extends LitElement {
`;
}
static get styles(): CSSResult {
static get styles(): CSSResultGroup {
return css`
:host {
display: block;
+4 -10
View File
@@ -1,12 +1,5 @@
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { LovelaceConfig } from "../../../../src/data/lovelace";
import { Lovelace } from "../../../../src/panels/lovelace/types";
import "../../../../src/panels/lovelace/views/hui-view";
@@ -35,6 +28,7 @@ class HcLovelace extends LitElement {
}
const lovelace: Lovelace = {
config: this.lovelaceConfig,
rawConfig: this.lovelaceConfig,
editMode: false,
urlPath: this.urlPath!,
enableFullEditMode: () => undefined,
@@ -90,7 +84,7 @@ class HcLovelace extends LitElement {
return undefined;
}
static get styles(): CSSResult {
static get styles(): CSSResultGroup {
return css`
:host {
min-height: 100vh;
+15 -13
View File
@@ -3,12 +3,8 @@ import {
getAuth,
UnsubscribeFunc,
} from "home-assistant-js-websocket";
import {
customElement,
html,
internalProperty,
TemplateResult,
} from "lit-element";
import { html, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators";
import { CAST_NS } from "../../../../src/cast/const";
import {
ConnectMessage,
@@ -36,13 +32,13 @@ let resourcesLoaded = false;
@customElement("hc-main")
export class HcMain extends HassElement {
@internalProperty() private _showDemo = false;
@state() private _showDemo = false;
@internalProperty() private _lovelaceConfig?: LovelaceConfig;
@state() private _lovelaceConfig?: LovelaceConfig;
@internalProperty() private _lovelacePath: string | number | null = null;
@state() private _lovelacePath: string | number | null = null;
@internalProperty() private _error?: string;
@state() private _error?: string;
private _unsubLovelace?: UnsubscribeFunc;
@@ -221,11 +217,17 @@ export class HcMain extends HassElement {
}
private async _generateLovelaceConfig() {
const { generateLovelaceConfigFromHass } = await import(
"../../../../src/panels/lovelace/common/generate-lovelace-config"
const { generateLovelaceDashboardStrategy } = await import(
"../../../../src/panels/lovelace/strategies/get-strategy"
);
this._handleNewLovelaceConfig(
await generateLovelaceConfigFromHass(this.hass!)
await generateLovelaceDashboardStrategy(
{
hass: this.hass!,
narrow: false,
},
"original-states"
)
);
}
+21 -13
View File
@@ -246,11 +246,15 @@ export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
"light.living_room_lights": {
entity_id: "light.living_room_lights",
state: "off",
state: "on",
attributes: {
min_mireds: 111,
max_mireds: 400,
brightness: 175,
color_temp: 300,
supported_color_modes: ["brightness", "color_temp"],
friendly_name: "Living Room Lights",
color_mode: "color_temp",
supported_features: 55,
},
},
@@ -263,13 +267,27 @@ export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
},
"light.kitchen_lights": {
entity_id: "light.kitchen_lights",
state: "on",
attributes: {
min_mireds: 111,
max_mireds: 400,
brightness: 200,
rgb_color: [255, 175, 96],
supported_color_modes: ["brightness", "color_temp", "rgb"],
color_mode: "rgb",
friendly_name: "Kitchen Lights",
supported_features: 55,
},
},
"light.lifx5": {
entity_id: "light.lifx5",
state: "off",
attributes: {
friendly_name: "Kitchen Lights",
supported_color_modes: ["brightness"],
friendly_name: "Garage Lights",
supported_features: 1,
},
},
"sensor.plexspy": {
entity_id: "sensor.plexspy",
state: "0",
@@ -482,16 +500,6 @@ export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
icon: "hademo:history",
},
},
"light.lifx5": {
entity_id: "light.lifx5",
state: "on",
attributes: {
min_mireds: 111,
max_mireds: 400,
friendly_name: "Garage Lights",
supported_features: 55,
},
},
"sensor.alok_to_home": {
entity_id: "sensor.alok_to_home",
state: "41",
@@ -1114,6 +1114,9 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
min_mireds: 153,
max_mireds: 500,
brightness: 63,
color_temp: 200,
supported_color_modes: ["brightness", "color_temp", "rgb"],
color_mode: "color_temp",
friendly_name: "Upstairs lights",
supported_features: 63,
custom_ui_state_card: "state-card-custom-ui",
@@ -1125,6 +1128,7 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
attributes: {
friendly_name: "Walk in closet lights",
supported_features: 41,
supported_color_modes: ["brightness", "color_temp"],
custom_ui_state_card: "state-card-custom-ui",
icon: "mdi:wall-sconce",
},
@@ -1136,6 +1140,8 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
brightness: 254,
friendly_name: "Outdoor lights",
supported_features: 41,
supported_color_modes: ["brightness"],
color_mode: "brightness",
custom_ui_state_card: "state-card-custom-ui",
icon: "mdi:wall-sconce",
},
@@ -1148,6 +1154,8 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
max_mireds: 500,
brightness: 128,
color_temp: 366,
supported_color_modes: ["brightness", "color_temp", "rgb"],
color_mode: "color_temp",
effect_list: ["colorloop"],
friendly_name: "Downstairs lights",
supported_features: 63,
@@ -1307,6 +1315,7 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
attributes: {
min_mireds: 153,
max_mireds: 500,
supported_color_modes: ["brightness", "color_temp"],
is_deconz_group: false,
friendly_name: "Bedside Lamp",
supported_features: 63,
@@ -1320,6 +1329,7 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
attributes: {
min_mireds: 153,
max_mireds: 500,
supported_color_modes: ["brightness", "color_temp"],
is_deconz_group: false,
friendly_name: "Floorlamp Reading Light",
supported_features: 43,
@@ -1335,6 +1345,8 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
max_mireds: 500,
brightness: 128,
color_temp: 366,
supported_color_modes: ["brightness", "color_temp", "rgb"],
color_mode: "color_temp",
effect_list: ["colorloop"],
is_deconz_group: false,
friendly_name: "Hallway window light",
@@ -1349,6 +1361,7 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
attributes: {
brightness: 77,
is_deconz_group: false,
supported_color_modes: ["brightness"],
friendly_name: "Isa Ceiling Light",
supported_features: 41,
custom_ui_state_card: "state-card-custom-ui",
@@ -1363,6 +1376,8 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
max_mireds: 500,
brightness: 150,
color_temp: 366,
supported_color_modes: ["brightness", "color_temp"],
color_mode: "color_temp",
effect_list: ["colorloop"],
is_deconz_group: false,
friendly_name: "Floorlamp",
@@ -1377,6 +1392,7 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
attributes: {
friendly_name: "Bedroom Ceiling Light",
supported_features: 41,
supported_color_modes: ["brightness"],
custom_ui_state_card: "state-card-custom-ui",
icon: "mdi:ceiling-light",
},
@@ -1387,6 +1403,7 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
attributes: {
friendly_name: "Nightlight",
supported_features: 17,
supported_color_modes: ["brightness"],
custom_ui_state_card: "state-card-custom-ui",
icon: "mdi:lamp",
},
@@ -1753,6 +1770,7 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
power_consumption: 2.2,
friendly_name: "Upstairs Hallway Light",
supported_features: 33,
supported_color_modes: ["brightness"],
custom_ui_state_card: "state-card-custom-ui",
icon: "mdi:ceiling-light",
},
@@ -1768,6 +1786,7 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
power_consumption: 0,
friendly_name: "Dining Room Light",
supported_features: 33,
supported_color_modes: ["brightness"],
custom_ui_state_card: "state-card-custom-ui",
icon: "mdi:ceiling-light",
},
@@ -1783,6 +1802,7 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
power_consumption: 0,
friendly_name: "Living room Spotlights",
supported_features: 33,
supported_color_modes: ["brightness"],
custom_ui_state_card: "state-card-custom-ui",
icon: "mdi:track-light",
},
@@ -1799,6 +1819,7 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
power_consumption: 2.5,
friendly_name: "Passage Lights",
supported_features: 33,
supported_color_modes: ["brightness"],
custom_ui_state_card: "state-card-custom-ui",
icon: "mdi:track-light",
},
@@ -1843,6 +1864,7 @@ export const demoEntitiesTeachingbirds: DemoConfig["entities"] = () =>
power_consumption: 37.4,
friendly_name: "Kitchen Lights",
supported_features: 33,
supported_color_modes: ["brightness"],
custom_ui_state_card: "state-card-custom-ui",
icon: "mdi:track-light",
},
+29 -43
View File
@@ -440,57 +440,43 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
type: "horizontal-stack",
},
{
type: "grid",
columns: 2,
cards: [
{
cards: [
{
graph: "line",
type: "sensor",
entity: "sensor.temperature_bedroom",
},
{
graph: "line",
type: "sensor",
name: "S's room",
entity: "sensor.temperature_stefan",
},
],
type: "horizontal-stack",
graph: "line",
type: "sensor",
entity: "sensor.temperature_bedroom",
},
{
cards: [
{
graph: "line",
type: "sensor",
entity: "sensor.temperature_passage",
},
{
graph: "line",
type: "sensor",
name: "Bathroom",
entity: "sensor.temperature_downstairs_bathroom",
},
],
type: "horizontal-stack",
graph: "line",
type: "sensor",
name: "S's room",
entity: "sensor.temperature_stefan",
},
{
cards: [
{
graph: "line",
type: "sensor",
entity: "sensor.temperature_storage",
},
{
graph: "line",
type: "sensor",
name: "Refrigerator",
entity: "sensor.refrigerator",
},
],
type: "horizontal-stack",
graph: "line",
type: "sensor",
entity: "sensor.temperature_passage",
},
{
graph: "line",
type: "sensor",
name: "Bathroom",
entity: "sensor.temperature_downstairs_bathroom",
},
{
graph: "line",
type: "sensor",
entity: "sensor.temperature_storage",
},
{
graph: "line",
type: "sensor",
name: "Refrigerator",
entity: "sensor.refrigerator",
},
],
type: "vertical-stack",
},
{
entities: [
+1 -1
View File
@@ -1,5 +1,5 @@
/* eslint-disable */
import { LitElement } from "lit-element";
import { LitElement } from "lit";
import "./card-tools";
class CardModder extends LitElement {
+1 -1
View File
@@ -1,5 +1,5 @@
/* eslint-disable */
import { html, LitElement } from "lit-element";
import { html, LitElement } from "lit";
if (!window.cardTools) {
const version = 0.2;
+4 -11
View File
@@ -1,12 +1,5 @@
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators";
import { CastManager } from "../../../src/cast/cast_manager";
import { castSendShowDemo } from "../../../src/cast/receiver_messages";
import "../../../src/components/ha-icon";
@@ -20,7 +13,7 @@ import { HomeAssistant } from "../../../src/types";
class CastDemoRow extends LitElement implements LovelaceRow {
public hass!: HomeAssistant;
@internalProperty() private _castManager?: CastManager | null;
@state() private _castManager?: CastManager | null;
public setConfig(_config: CastConfig): void {
// No config possible.
@@ -73,7 +66,7 @@ class CastDemoRow extends LitElement implements LovelaceRow {
this.style.display = this._castManager ? "" : "none";
}
static get styles(): CSSResult {
static get styles(): CSSResultGroup {
return css`
:host {
display: flex;
+5 -12
View File
@@ -1,14 +1,7 @@
import "@material/mwc-button";
import {
css,
CSSResult,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { until } from "lit-html/directives/until";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { property, state } from "lit/decorators";
import { until } from "lit/directives/until";
import "../../../src/components/ha-card";
import "../../../src/components/ha-circular-progress";
import { LovelaceCardConfig } from "../../../src/data/lovelace";
@@ -26,7 +19,7 @@ export class HADemoCard extends LitElement implements LovelaceCard {
@property({ attribute: false }) public hass!: MockHomeAssistant;
@internalProperty() private _switching?: boolean;
@state() private _switching?: boolean;
private _hidden = localStorage.hide_demo_card;
@@ -113,7 +106,7 @@ export class HADemoCard extends LitElement implements LovelaceCard {
}
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
css`
a {
+3 -3
View File
@@ -22,9 +22,9 @@ import { mockTemplate } from "./stubs/template";
import { mockTranslations } from "./stubs/translations";
class HaDemo extends HomeAssistantAppEl {
protected async _initialize() {
protected async _initializeHass() {
const initial: Partial<MockHomeAssistant> = {
panelUrl: (this as any).panelUrl,
panelUrl: (this as any)._panelUrl,
// Override updateHass so that the correct hass lifecycle methods are called
updateHass: (hassUpdate: Partial<HomeAssistant>) =>
this._updateHass(hassUpdate),
@@ -70,7 +70,7 @@ class HaDemo extends HomeAssistantAppEl {
}
e.preventDefault();
navigate(this, href);
navigate(href);
},
{ capture: true }
);
+1 -3
View File
@@ -3,8 +3,6 @@ import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
export const mockTranslations = (hass: MockHomeAssistant) => {
hass.mockWS(
"frontend/get_translations",
(/* msg: {language: string, category: string} */) => {
return { resources: {} };
}
(/* msg: {language: string, category: string} */) => ({ resources: {} })
);
};
+26 -3
View File
@@ -1,7 +1,7 @@
import { html } from "@polymer/polymer/lib/utils/html-tag";
/* eslint-plugin-disable lit */
import { PolymerElement } from "@polymer/polymer/polymer-element";
import { safeLoad } from "js-yaml";
import { load } from "js-yaml";
import { createCardElement } from "../../../src/panels/lovelace/create-element/create-card-element";
class DemoCard extends PolymerElement {
@@ -15,6 +15,10 @@ class DemoCard extends PolymerElement {
margin: 0 0 20px;
color: var(--primary-color);
}
h2 small {
font-size: 0.5em;
color: var(--primary-text-color);
}
#card {
max-width: 400px;
width: 100vw;
@@ -34,7 +38,12 @@ class DemoCard extends PolymerElement {
}
}
</style>
<h2>[[config.heading]]</h2>
<h2>
[[config.heading]]
<template is="dom-if" if="[[_size]]">
<small>(size [[_size]])</small>
</template>
</h2>
<div class="root">
<div id="card"></div>
<template is="dom-if" if="[[showConfig]]">
@@ -55,6 +64,9 @@ class DemoCard extends PolymerElement {
observer: "_configChanged",
},
showConfig: Boolean,
_size: {
type: Number,
},
};
}
@@ -68,8 +80,19 @@ class DemoCard extends PolymerElement {
card.removeChild(card.lastChild);
}
const el = this._createCardElement(safeLoad(config.config)[0]);
const el = this._createCardElement(load(config.config)[0]);
card.appendChild(el);
this._getSize(el);
}
async _getSize(el) {
await customElements.whenDefined(el.localName);
if (!("getCardSize" in el)) {
this._size = undefined;
return;
}
this._size = await el.getCardSize();
}
_createCardElement(cardConfig) {
+58 -92
View File
@@ -2,8 +2,7 @@ import { DemoTrace } from "./types";
export const basicTrace: DemoTrace = {
trace: {
last_action: "action/2",
last_condition: "condition/0",
last_step: "action/2",
run_id: "0",
state: "stopped",
timestamp: {
@@ -13,7 +12,61 @@ export const basicTrace: DemoTrace = {
trigger: "state of input_boolean.toggle_1",
domain: "automation",
item_id: "1615419646544",
action_trace: {
trace: {
"trigger/0": [
{
path: "trigger/0",
timestamp: "2021-03-25T04:36:51.223693+00:00",
},
],
"condition/0": [
{
path: "condition/0",
timestamp: "2021-03-25T04:36:51.228243+00:00",
changed_variables: {
trigger: {
platform: "state",
entity_id: "input_boolean.toggle_1",
from_state: {
entity_id: "input_boolean.toggle_1",
state: "on",
attributes: {
editable: true,
friendly_name: "Toggle 1",
},
last_changed: "2021-03-24T19:03:59.141440+00:00",
last_updated: "2021-03-24T19:03:59.141440+00:00",
context: {
id: "5d0918eb379214d07554bdab6a08bcff",
parent_id: null,
user_id: null,
},
},
to_state: {
entity_id: "input_boolean.toggle_1",
state: "off",
attributes: {
editable: true,
friendly_name: "Toggle 1",
},
last_changed: "2021-03-25T04:36:51.220696+00:00",
last_updated: "2021-03-25T04:36:51.220696+00:00",
context: {
id: "664d6d261450a9ecea6738e97269a149",
parent_id: null,
user_id: "d1b4e89da01445fa8bc98e39fac477ca",
},
},
for: null,
attribute: null,
description: "state of input_boolean.toggle_1",
},
},
result: {
result: true,
},
},
],
"action/0": [
{
path: "action/0",
@@ -158,56 +211,7 @@ export const basicTrace: DemoTrace = {
},
],
},
condition_trace: {
"condition/0": [
{
path: "condition/0",
timestamp: "2021-03-25T04:36:51.228243+00:00",
changed_variables: {
trigger: {
platform: "state",
entity_id: "input_boolean.toggle_1",
from_state: {
entity_id: "input_boolean.toggle_1",
state: "on",
attributes: {
editable: true,
friendly_name: "Toggle 1",
},
last_changed: "2021-03-24T19:03:59.141440+00:00",
last_updated: "2021-03-24T19:03:59.141440+00:00",
context: {
id: "5d0918eb379214d07554bdab6a08bcff",
parent_id: null,
user_id: null,
},
},
to_state: {
entity_id: "input_boolean.toggle_1",
state: "off",
attributes: {
editable: true,
friendly_name: "Toggle 1",
},
last_changed: "2021-03-25T04:36:51.220696+00:00",
last_updated: "2021-03-25T04:36:51.220696+00:00",
context: {
id: "664d6d261450a9ecea6738e97269a149",
parent_id: null,
user_id: "d1b4e89da01445fa8bc98e39fac477ca",
},
},
for: null,
attribute: null,
description: "state of input_boolean.toggle_1",
},
},
result: {
result: true,
},
},
],
},
config: {
id: "1615419646544",
alias: "Ensure Party mode",
@@ -285,45 +289,7 @@ export const basicTrace: DemoTrace = {
parent_id: "664d6d261450a9ecea6738e97269a149",
user_id: null,
},
variables: {
trigger: {
platform: "state",
entity_id: "input_boolean.toggle_1",
from_state: {
entity_id: "input_boolean.toggle_1",
state: "on",
attributes: {
editable: true,
friendly_name: "Toggle 1",
},
last_changed: "2021-03-24T19:03:59.141440+00:00",
last_updated: "2021-03-24T19:03:59.141440+00:00",
context: {
id: "5d0918eb379214d07554bdab6a08bcff",
parent_id: null,
user_id: null,
},
},
to_state: {
entity_id: "input_boolean.toggle_1",
state: "off",
attributes: {
editable: true,
friendly_name: "Toggle 1",
},
last_changed: "2021-03-25T04:36:51.220696+00:00",
last_updated: "2021-03-25T04:36:51.220696+00:00",
context: {
id: "664d6d261450a9ecea6738e97269a149",
parent_id: null,
user_id: "d1b4e89da01445fa8bc98e39fac477ca",
},
},
for: null,
attribute: null,
description: "state of input_boolean.toggle_1",
},
},
script_execution: "finished",
},
logbookEntries: [
{
@@ -0,0 +1,44 @@
import { LogbookEntry } from "../../../../src/data/logbook";
import { AutomationTraceExtended } from "../../../../src/data/trace";
import { DemoTrace } from "./types";
export const mockDemoTrace = (
tracePartial: Partial<AutomationTraceExtended>,
logbookEntries?: LogbookEntry[]
): DemoTrace => ({
trace: {
last_step: "",
run_id: "0",
state: "stopped",
timestamp: {
start: "2021-03-25T04:36:51.223693+00:00",
finish: "2021-03-25T04:36:51.266132+00:00",
},
trigger: "mocked trigger",
domain: "automation",
item_id: "1615419646544",
trace: {
"trigger/0": [
{
path: "trigger/0",
changed_variables: {
trigger: {
description: "mocked trigger",
},
},
timestamp: "2021-03-25T04:36:51.223693+00:00",
},
],
},
config: {
trigger: [],
action: [],
},
context: {
id: "abcd",
},
script_execution: "finished",
...tracePartial,
},
logbookEntries: logbookEntries || [],
});
+9 -43
View File
@@ -2,8 +2,7 @@ import { DemoTrace } from "./types";
export const motionLightTrace: DemoTrace = {
trace: {
last_action: "action/3",
last_condition: null,
last_step: "action/3",
run_id: "1",
state: "stopped",
timestamp: {
@@ -13,7 +12,13 @@ export const motionLightTrace: DemoTrace = {
trigger: "state of binary_sensor.pauluss_macbook_pro_camera_in_use",
domain: "automation",
item_id: "1614732497392",
action_trace: {
trace: {
"trigger/0": [
{
path: "trigger/0",
timestamp: "2021-03-25T04:36:51.223693+00:00",
},
],
"action/0": [
{
path: "action/0",
@@ -124,7 +129,6 @@ export const motionLightTrace: DemoTrace = {
},
],
},
condition_trace: {},
config: {
mode: "restart",
max_exceeded: "silent",
@@ -172,45 +176,7 @@ export const motionLightTrace: DemoTrace = {
parent_id: "e22ddfd5f11dc4aad9a52fc10dab613b",
user_id: null,
},
variables: {
trigger: {
platform: "state",
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
from_state: {
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
state: "off",
attributes: {
friendly_name: "Pauluss MacBook Pro Camera In Use",
icon: "mdi:camera-off",
},
last_changed: "2021-03-14T06:06:29.235325+00:00",
last_updated: "2021-03-14T06:06:29.235325+00:00",
context: {
id: "ad4864c5ce957c38a07b50378eeb245d",
parent_id: null,
user_id: null,
},
},
to_state: {
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
state: "on",
attributes: {
friendly_name: "Pauluss MacBook Pro Camera In Use",
icon: "mdi:camera",
},
last_changed: "2021-03-14T06:07:01.762009+00:00",
last_updated: "2021-03-14T06:07:01.762009+00:00",
context: {
id: "e22ddfd5f11dc4aad9a52fc10dab613b",
parent_id: null,
user_id: null,
},
},
for: null,
attribute: null,
description: "state of binary_sensor.pauluss_macbook_pro_camera_in_use",
},
},
script_execution: "finished",
},
logbookEntries: [
{
@@ -0,0 +1,96 @@
import { dump } from "js-yaml";
import { html, css, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../src/components/ha-card";
import { describeAction } from "../../../src/data/script_i18n";
import { provideHass } from "../../../src/fake_data/provide_hass";
import { HomeAssistant } from "../../../src/types";
const actions = [
{ wait_template: "{{ true }}", alias: "Something with an alias" },
{ delay: "0:05" },
{ wait_template: "{{ true }}" },
{
condition: "template",
value_template: "{{ true }}",
},
{ event: "happy_event" },
{
device_id: "abcdefgh",
domain: "plex",
entity_id: "media_player.kitchen",
},
{ scene: "scene.kitchen_morning" },
{
wait_for_trigger: [
{
platform: "state",
entity_id: "input_boolean.toggle_1",
},
],
},
{
variables: {
hello: "world",
},
},
{
service: "input_boolean.toggle",
target: {
entity_id: "input_boolean.toggle_4",
},
},
];
@customElement("demo-automation-describe-action")
export class DemoAutomationDescribeAction extends LitElement {
@property({ attribute: false }) hass!: HomeAssistant;
protected render(): TemplateResult {
if (!this.hass) {
return html``;
}
return html`
<ha-card header="Actions">
${actions.map(
(conf) => html`
<div class="action">
<span>${describeAction(this.hass, conf as any)}</span>
<pre>${dump(conf)}</pre>
</div>
`
)}
</ha-card>
`;
}
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");
}
static get styles() {
return css`
ha-card {
max-width: 600px;
margin: 24px auto;
}
.action {
padding: 16px;
display: flex;
align-items: center;
justify-content: space-between;
}
span {
margin-right: 16px;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"demo-automation-describe-action": DemoAutomationDescribeAction;
}
}
@@ -0,0 +1,60 @@
import { dump } from "js-yaml";
import { html, css, LitElement, TemplateResult } from "lit";
import { customElement } from "lit/decorators";
import "../../../src/components/ha-card";
import { describeCondition } from "../../../src/data/automation_i18n";
const conditions = [
{ condition: "and" },
{ condition: "not" },
{ condition: "or" },
{ condition: "state" },
{ condition: "numeric_state" },
{ condition: "sun", after: "sunset" },
{ condition: "sun", after: "sunrise" },
{ condition: "zone" },
{ condition: "time" },
{ condition: "template" },
];
@customElement("demo-automation-describe-condition")
export class DemoAutomationDescribeCondition extends LitElement {
protected render(): TemplateResult {
return html`
<ha-card header="Conditions">
${conditions.map(
(conf) => html`
<div class="condition">
<span>${describeCondition(conf as any)}</span>
<pre>${dump(conf)}</pre>
</div>
`
)}
</ha-card>
`;
}
static get styles() {
return css`
ha-card {
max-width: 600px;
margin: 24px auto;
}
.condition {
padding: 16px;
display: flex;
align-items: center;
justify-content: space-between;
}
span {
margin-right: 16px;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"demo-automation-describe-condition": DemoAutomationDescribeCondition;
}
}
@@ -0,0 +1,63 @@
import { dump } from "js-yaml";
import { html, css, LitElement, TemplateResult } from "lit";
import { customElement } from "lit/decorators";
import "../../../src/components/ha-card";
import { describeTrigger } from "../../../src/data/automation_i18n";
const triggers = [
{ platform: "state" },
{ platform: "mqtt" },
{ platform: "geo_location" },
{ platform: "homeassistant" },
{ platform: "numeric_state" },
{ platform: "sun" },
{ platform: "time_pattern" },
{ platform: "webhook" },
{ platform: "zone" },
{ platform: "tag" },
{ platform: "time" },
{ platform: "template" },
{ platform: "event" },
];
@customElement("demo-automation-describe-trigger")
export class DemoAutomationDescribeTrigger extends LitElement {
protected render(): TemplateResult {
return html`
<ha-card header="Triggers">
${triggers.map(
(conf) => html`
<div class="trigger">
<span>${describeTrigger(conf as any)}</span>
<pre>${dump(conf)}</pre>
</div>
`
)}
</ha-card>
`;
}
static get styles() {
return css`
ha-card {
max-width: 600px;
margin: 24px auto;
}
.trigger {
padding: 16px;
display: flex;
align-items: center;
justify-content: space-between;
}
span {
margin-right: 16px;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"demo-automation-describe-trigger": DemoAutomationDescribeTrigger;
}
}
@@ -0,0 +1,81 @@
import { html, css, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../src/components/ha-card";
import "../../../src/components/trace/hat-script-graph";
import "../../../src/components/trace/hat-trace-timeline";
import { provideHass } from "../../../src/fake_data/provide_hass";
import { HomeAssistant } from "../../../src/types";
import { mockDemoTrace } from "../data/traces/mock-demo-trace";
import { DemoTrace } from "../data/traces/types";
const traces: DemoTrace[] = [
mockDemoTrace({ state: "running" }),
mockDemoTrace({ state: "debugged" }),
mockDemoTrace({ state: "stopped", script_execution: "failed_conditions" }),
mockDemoTrace({ state: "stopped", script_execution: "failed_single" }),
mockDemoTrace({ state: "stopped", script_execution: "failed_max_runs" }),
mockDemoTrace({ state: "stopped", script_execution: "finished" }),
mockDemoTrace({ state: "stopped", script_execution: "aborted" }),
mockDemoTrace({
state: "stopped",
script_execution: "error",
error: 'Variable "beer" cannot be None',
}),
mockDemoTrace({ state: "stopped", script_execution: "cancelled" }),
];
@customElement("demo-automation-trace-timeline")
export class DemoAutomationTraceTimeline extends LitElement {
@property({ attribute: false }) hass?: HomeAssistant;
protected render(): TemplateResult {
if (!this.hass) {
return html``;
}
return html`
${traces.map(
(trace) => html`
<ha-card .header=${trace.trace.config.alias}>
<div class="card-content">
<hat-trace-timeline
.hass=${this.hass}
.trace=${trace.trace}
.logbookEntries=${trace.logbookEntries}
></hat-trace-timeline>
<button @click=${() => console.log(trace)}>Log trace</button>
</div>
</ha-card>
`
)}
`;
}
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");
}
static get styles() {
return css`
ha-card {
max-width: 600px;
margin: 24px;
}
.card-content {
display: flex;
}
button {
position: absolute;
top: 0;
right: 0;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"demo-automation-trace-timeline": DemoAutomationTraceTimeline;
}
}
+37 -10
View File
@@ -1,18 +1,13 @@
import {
customElement,
html,
css,
LitElement,
TemplateResult,
property,
} from "lit-element";
import { html, css, LitElement, TemplateResult } from "lit";
import "../../../src/components/ha-card";
import "../../../src/components/trace/hat-script-graph";
import "../../../src/components/trace/hat-trace-timeline";
import { provideHass } from "../../../src/fake_data/provide_hass";
import { HomeAssistant } from "../../../src/types";
import { DemoTrace } from "../data/traces/types";
import { basicTrace } from "../data/traces/basic_trace";
import { motionLightTrace } from "../data/traces/motion-light-trace";
import { customElement, property, state } from "lit/decorators";
const traces: DemoTrace[] = [basicTrace, motionLightTrace];
@@ -20,20 +15,38 @@ const traces: DemoTrace[] = [basicTrace, motionLightTrace];
export class DemoAutomationTrace extends LitElement {
@property({ attribute: false }) hass?: HomeAssistant;
@state() private _selected = {};
protected render(): TemplateResult {
if (!this.hass) {
return html``;
}
return html`
${traces.map(
(trace) => html`
<ha-card .heading=${trace.trace.config.alias}>
(trace, idx) => html`
<ha-card .header=${trace.trace.config.alias}>
<div class="card-content">
<hat-script-graph
.trace=${trace.trace}
.selected=${this._selected[idx]}
@graph-node-selected=${(ev) => {
this._selected = { ...this._selected, [idx]: ev.detail.path };
}}
></hat-script-graph>
<hat-trace-timeline
allowPick
.hass=${this.hass}
.trace=${trace.trace}
.logbookEntries=${trace.logbookEntries}
.selectedPath=${this._selected[idx]}
@value-changed=${(ev) => {
this._selected = {
...this._selected,
[idx]: ev.detail.value,
};
}}
></hat-trace-timeline>
<button @click=${() => console.log(trace)}>Log trace</button>
</div>
</ha-card>
`
@@ -53,6 +66,20 @@ export class DemoAutomationTrace extends LitElement {
max-width: 600px;
margin: 24px;
}
.card-content {
display: flex;
}
.card-content > * {
margin-right: 16px;
}
.card-content > *:last-child {
margin-right: 0;
}
button {
position: absolute;
top: 0;
right: 0;
}
`;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -93,4 +87,8 @@ class DemoAlarmPanelEntity extends LitElement {
}
}
customElements.define("demo-hui-alarm-panel-card", DemoAlarmPanelEntity);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-alarm-panel-card": DemoAlarmPanelEntity;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -75,4 +69,8 @@ class DemoConditional extends LitElement {
}
}
customElements.define("demo-hui-conditional-card", DemoConditional);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-conditional-card": DemoConditional;
}
}
+7 -9
View File
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -239,4 +233,8 @@ class DemoEntities extends LitElement {
}
}
customElements.define("demo-hui-entities-card", DemoEntities);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-entities-card": DemoEntities;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -91,4 +85,8 @@ class DemoButtonEntity extends LitElement {
}
}
customElements.define("demo-hui-entity-button-card", DemoButtonEntity);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-entity-button-card": DemoButtonEntity;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -132,4 +126,8 @@ class DemoEntityFilter extends LitElement {
}
}
customElements.define("demo-hui-entity-filter-card", DemoEntityFilter);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-entity-filter-card": DemoEntityFilter;
}
}
+7 -9
View File
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -129,4 +123,8 @@ class DemoGaugeEntity extends LitElement {
}
}
customElements.define("demo-hui-gauge-card", DemoGaugeEntity);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-gauge-card": DemoGaugeEntity;
}
}
+9 -11
View File
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -186,7 +180,7 @@ const CONFIGS = [
name:
- light.kitchen_lights
- entity: lock.kitchen_door
name:
name:
- light.ceiling_lights
`,
},
@@ -194,7 +188,7 @@ const CONFIGS = [
heading: "Custom tap action",
config: `
- type: glance
columns: 4
columns: 4
entities:
- entity: lock.kitchen_door
name: Custom
@@ -232,4 +226,8 @@ class DemoGlanceEntity extends LitElement {
}
}
customElements.define("demo-hui-glance-card", DemoGlanceEntity);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-glance-card": DemoGlanceEntity;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { mockHistory } from "../../../demo/src/stubs/history";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
@@ -49,6 +43,110 @@ const ENTITIES = [
];
const CONFIGS = [
{
heading: "Default Grid",
config: `
- type: grid
cards:
- type: entity
entity: light.kitchen_lights
- type: entity
entity: light.bed_light
- type: entity
entity: device_tracker.demo_paulus
- type: sensor
entity: sensor.illumination
graph: line
- type: entity
entity: device_tracker.demo_anne_therese
`,
},
{
heading: "Non-square Grid with 2 columns",
config: `
- type: grid
columns: 2
square: false
cards:
- type: entity
entity: light.kitchen_lights
- type: entity
entity: light.bed_light
- type: entity
entity: device_tracker.demo_paulus
- type: sensor
entity: sensor.illumination
graph: line
`,
},
{
heading: "Default Grid with title",
config: `
- type: grid
title: Kitchen
cards:
- type: entity
entity: light.kitchen_lights
- type: entity
entity: light.bed_light
- type: entity
entity: device_tracker.demo_paulus
- type: sensor
entity: sensor.illumination
graph: line
- type: entity
entity: device_tracker.demo_anne_therese
`,
},
{
heading: "Columns 4",
config: `
- type: grid
columns: 4
cards:
- type: entity
entity: light.kitchen_lights
- type: entity
entity: light.bed_light
- type: entity
entity: device_tracker.demo_paulus
- type: sensor
entity: sensor.illumination
graph: line
`,
},
{
heading: "Columns 2",
config: `
- type: grid
columns: 2
cards:
- type: entity
entity: light.kitchen_lights
- type: entity
entity: light.bed_light
`,
},
{
heading: "Columns 1",
config: `
- type: grid
columns: 1
cards:
- type: entity
entity: light.kitchen_lights
`,
},
{
heading: "Size for single card",
config: `
- type: grid
cards:
- type: entity
entity: light.kitchen_lights
`,
},
{
heading: "Vertical Stack",
config: `
@@ -99,45 +197,9 @@ const CONFIGS = [
entity: light.bed_light
`,
},
{
heading: "Default Grid",
config: `
- type: grid
cards:
- type: entity
entity: light.kitchen_lights
- type: entity
entity: light.bed_light
- type: entity
entity: device_tracker.demo_paulus
- type: sensor
entity: sensor.illumination
graph: line
- type: entity
entity: device_tracker.demo_anne_therese
`,
},
{
heading: "Non-square Grid with 2 columns",
config: `
- type: grid
columns: 2
square: false
cards:
- type: entity
entity: light.kitchen_lights
- type: entity
entity: light.bed_light
- type: entity
entity: device_tracker.demo_paulus
- type: sensor
entity: sensor.illumination
graph: line
`,
},
];
@customElement("demo-hui-stack-card")
@customElement("demo-hui-grid-and-stack-card")
class DemoStack extends LitElement {
@query("#demos") private _demoRoot!: HTMLElement;
@@ -155,4 +217,8 @@ class DemoStack extends LitElement {
}
}
customElements.define("demo-hui-stack-card", DemoStack);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-grid-and-stack-card": DemoStack;
}
}
+7 -2
View File
@@ -1,4 +1,5 @@
import { customElement, html, LitElement, TemplateResult } from "lit-element";
import { html, LitElement, TemplateResult } from "lit";
import { customElement } from "lit/decorators";
import "../components/demo-cards";
const CONFIGS = [
@@ -42,4 +43,8 @@ class DemoIframe extends LitElement {
}
}
customElements.define("demo-hui-iframe-card", DemoIframe);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-iframe-card": DemoIframe;
}
}
+7 -9
View File
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -85,4 +79,8 @@ class DemoLightEntity extends LitElement {
}
}
customElements.define("demo-hui-light-card", DemoLightEntity);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-light-card": DemoLightEntity;
}
}
+7 -9
View File
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -183,4 +177,8 @@ class DemoMap extends LitElement {
}
}
customElements.define("demo-hui-map-card", DemoMap);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-map-card": DemoMap;
}
}
+7 -9
View File
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { mockTemplate } from "../../../demo/src/stubs/template";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -276,4 +270,8 @@ class DemoMarkdown extends LitElement {
}
}
customElements.define("demo-hui-markdown-card", DemoMarkdown);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-markdown-card": DemoMarkdown;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
import { createMediaPlayerEntities } from "../data/media_players";
@@ -180,4 +174,8 @@ class DemoHuiMediaControlCard extends LitElement {
}
}
customElements.define("demo-hui-media-control-card", DemoHuiMediaControlCard);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-media-control-card": DemoHuiMediaControlCard;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
import { createMediaPlayerEntities } from "../data/media_players";
@@ -77,4 +71,8 @@ class DemoHuiMediaPlayerRow extends LitElement {
}
}
customElements.define("demo-hui-media-player-row", DemoHuiMediaPlayerRow);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-media-player-row": DemoHuiMediaPlayerRow;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -147,4 +141,8 @@ class DemoPictureElements extends LitElement {
}
}
customElements.define("demo-hui-picture-elements-card", DemoPictureElements);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-picture-elements-card": DemoPictureElements;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -102,4 +96,8 @@ class DemoPictureEntity extends LitElement {
}
}
customElements.define("demo-hui-picture-entity-card", DemoPictureEntity);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-picture-entity-card": DemoPictureEntity;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -143,4 +137,8 @@ class DemoPictureGlance extends LitElement {
}
}
customElements.define("demo-hui-picture-glance-card", DemoPictureGlance);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-picture-glance-card": DemoPictureGlance;
}
}
+7 -9
View File
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
import { createPlantEntities } from "../data/plants";
@@ -52,4 +46,8 @@ export class DemoPlantEntity extends LitElement {
}
}
customElements.define("demo-hui-plant-card", DemoPlantEntity);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-plant-card": DemoPlantEntity;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -48,4 +42,8 @@ class DemoShoppingListEntity extends LitElement {
}
}
customElements.define("demo-hui-shopping-list-card", DemoShoppingListEntity);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-shopping-list-card": DemoShoppingListEntity;
}
}
@@ -1,11 +1,5 @@
import {
customElement,
html,
LitElement,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, query } from "lit/decorators";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-cards";
@@ -96,4 +90,8 @@ class DemoThermostatEntity extends LitElement {
}
}
customElements.define("demo-hui-thermostat-card", DemoThermostatEntity);
declare global {
interface HTMLElementTagNameMap {
"demo-hui-thermostat-card": DemoThermostatEntity;
}
}
+354
View File
@@ -0,0 +1,354 @@
import { html, css, LitElement, TemplateResult } from "lit";
import "../../../src/components/ha-formfield";
import "../../../src/components/ha-switch";
import { IntegrationManifest } from "../../../src/data/integration";
import { provideHass } from "../../../src/fake_data/provide_hass";
import { HomeAssistant } from "../../../src/types";
import "../../../src/panels/config/integrations/ha-integration-card";
import "../../../src/panels/config/integrations/ha-ignored-config-entry-card";
import "../../../src/panels/config/integrations/ha-config-flow-card";
import type {
ConfigEntryExtended,
DataEntryFlowProgressExtended,
} from "../../../src/panels/config/integrations/ha-config-integrations";
import { DeviceRegistryEntry } from "../../../src/data/device_registry";
import { EntityRegistryEntry } from "../../../src/data/entity_registry";
import { classMap } from "lit/directives/class-map";
import { customElement, property, state } from "lit/decorators";
const createConfigEntry = (
title: string,
override: Partial<ConfigEntryExtended> = {}
): ConfigEntryExtended => ({
entry_id: title,
domain: "esphome",
localized_domain_name: "ESPHome",
title,
source: "zeroconf",
state: "loaded",
supports_options: false,
supports_unload: true,
disabled_by: null,
pref_disable_new_entities: false,
pref_disable_polling: false,
reason: null,
...override,
});
const createManifest = (
isCustom: boolean,
isCloud: boolean,
name = "ESPHome"
): IntegrationManifest => ({
name,
domain: "esphome",
is_built_in: !isCustom,
config_flow: false,
documentation: "https://www.home-assistant.io/integrations/esphome/",
iot_class: isCloud ? "cloud_polling" : "local_polling",
});
const loadedEntry = createConfigEntry("Loaded");
const nameAsDomainEntry = createConfigEntry("ESPHome");
const longNameEntry = createConfigEntry(
"Entry with a super long name that is going to the next line"
);
const longNonBreakingNameEntry = createConfigEntry(
"EntryWithASuperLongNameThatDoesNotBreak"
);
const configPanelEntry = createConfigEntry("Config Panel", {
domain: "mqtt",
localized_domain_name: "MQTT",
});
const optionsFlowEntry = createConfigEntry("Options Flow", {
supports_options: true,
});
const disabledPollingEntry = createConfigEntry("Disabled Polling", {
pref_disable_polling: true,
});
const setupErrorEntry = createConfigEntry("Setup Error", {
state: "setup_error",
});
const migrationErrorEntry = createConfigEntry("Migration Error", {
state: "migration_error",
});
const setupRetryEntry = createConfigEntry("Setup Retry", {
state: "setup_retry",
});
const setupRetryReasonEntry = createConfigEntry("Setup Retry", {
state: "setup_retry",
reason: "connection_error",
});
const setupRetryReasonMissingKeyEntry = createConfigEntry("Setup Retry", {
state: "setup_retry",
reason:
"HTTPSConnectionpool: Max retries exceeded with NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x9eedfc10>: Failed to establish a new connection: [Errno 113] Host is unreachable')",
});
const failedUnloadEntry = createConfigEntry("Failed Unload", {
state: "failed_unload",
});
const notLoadedEntry = createConfigEntry("Not Loaded", { state: "not_loaded" });
const disabledEntry = createConfigEntry("Disabled", {
state: "not_loaded",
disabled_by: "user",
});
const disabledFailedUnloadEntry = createConfigEntry(
"Disabled - Failed Unload",
{
state: "failed_unload",
disabled_by: "user",
}
);
const configFlows: DataEntryFlowProgressExtended[] = [
{
flow_id: "adbb401329d8439ebb78ef29837826a8",
handler: "roku",
context: {
source: "ssdp",
unique_id: "YF008D862864",
title_placeholders: {
name: "Living room Roku",
},
},
step_id: "discovery_confirm",
localized_title: "Living room Roku",
},
{
flow_id: "adbb401329d8439ebb78ef29837826a8",
handler: "hue",
context: {
source: "reauth",
unique_id: "YF008D862864",
title_placeholders: {
name: "Living room Roku",
},
},
step_id: "discovery_confirm",
localized_title: "Philips Hue",
},
];
const configEntries: Array<{
items: ConfigEntryExtended[];
is_custom?: boolean;
disabled?: boolean;
highlight?: string;
}> = [
{ items: [loadedEntry] },
{ items: [configPanelEntry] },
{ items: [optionsFlowEntry] },
{ items: [disabledPollingEntry] },
{ items: [nameAsDomainEntry] },
{ items: [longNameEntry] },
{ items: [longNonBreakingNameEntry] },
{ items: [setupErrorEntry] },
{ items: [migrationErrorEntry] },
{ items: [setupRetryEntry] },
{ items: [setupRetryReasonEntry] },
{ items: [setupRetryReasonMissingKeyEntry] },
{ items: [failedUnloadEntry] },
{ items: [notLoadedEntry] },
{
items: [
loadedEntry,
setupErrorEntry,
migrationErrorEntry,
longNameEntry,
longNonBreakingNameEntry,
setupRetryEntry,
failedUnloadEntry,
notLoadedEntry,
disabledEntry,
nameAsDomainEntry,
configPanelEntry,
optionsFlowEntry,
],
},
{ disabled: true, items: [disabledEntry] },
{ disabled: true, items: [disabledFailedUnloadEntry] },
{
disabled: true,
items: [disabledEntry, disabledFailedUnloadEntry],
},
{
items: [loadedEntry, configPanelEntry],
highlight: "Loaded",
},
];
const createEntityRegistryEntries = (
item: ConfigEntryExtended
): EntityRegistryEntry[] => [
{
config_entry_id: item.entry_id,
device_id: "mock-device-id",
area_id: null,
disabled_by: null,
entity_id: "binary_sensor.updater",
name: null,
icon: null,
platform: "updater",
},
];
const createDeviceRegistryEntries = (
item: ConfigEntryExtended
): DeviceRegistryEntry[] => [
{
entry_type: null,
config_entries: [item.entry_id],
connections: [],
manufacturer: "ESPHome",
model: "Mock Device",
name: "Tag Reader",
sw_version: null,
id: "mock-device-id",
identifiers: [],
via_device_id: null,
area_id: null,
name_by_user: null,
disabled_by: null,
},
];
@customElement("demo-integration-card")
export class DemoIntegrationCard extends LitElement {
@property({ attribute: false }) hass?: HomeAssistant;
@state() isCustomIntegration = false;
@state() isCloud = false;
protected render(): TemplateResult {
if (!this.hass) {
return html``;
}
return html`
<div class="container">
<div class="filters">
<ha-formfield label="Custom Integration">
<ha-switch @change=${this._toggleCustomIntegration}></ha-switch>
</ha-formfield>
<ha-formfield label="Relies on cloud">
<ha-switch @change=${this._toggleCloud}></ha-switch>
</ha-formfield>
</div>
<ha-ignored-config-entry-card
.hass=${this.hass}
.entry=${createConfigEntry("Ignored Entry")}
.manifest=${createManifest(this.isCustomIntegration, this.isCloud)}
></ha-ignored-config-entry-card>
${configFlows.map(
(flow) => html`
<ha-config-flow-card
.hass=${this.hass}
.flow=${flow}
.manifest=${createManifest(
this.isCustomIntegration,
this.isCloud,
flow.handler === "roku" ? "Roku" : "Philips Hue"
)}
></ha-config-flow-card>
`
)}
${configEntries.map(
(info) => html`
<ha-integration-card
class=${classMap({
highlight: info.highlight !== undefined,
})}
.hass=${this.hass}
domain="esphome"
.items=${info.items}
.manifest=${createManifest(
this.isCustomIntegration,
this.isCloud
)}
.entityRegistryEntries=${createEntityRegistryEntries(
info.items[0]
)}
.deviceRegistryEntries=${createDeviceRegistryEntries(
info.items[0]
)}
?disabled=${info.disabled}
.selectedConfigEntryId=${info.highlight}
></ha-integration-card>
`
)}
</div>
<div class="container">
<!-- One that is standalone to see how it increases height if height
not defined by other cards. -->
<ha-integration-card
.hass=${this.hass}
domain="esphome"
.items=${[
loadedEntry,
setupErrorEntry,
migrationErrorEntry,
setupRetryEntry,
failedUnloadEntry,
]}
.manifest=${createManifest(this.isCustomIntegration, this.isCloud)}
.entityRegistryEntries=${createEntityRegistryEntries(loadedEntry)}
.deviceRegistryEntries=${createDeviceRegistryEntries(loadedEntry)}
></ha-integration-card>
</div>
`;
}
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");
hass.updateTranslations("config", "en");
// Normally this string is loaded from backend
hass.addTranslations(
{
"component.esphome.config.error.connection_error":
"Can't connect to ESP. Please make sure your YAML file contains an 'api:' line.",
},
"en"
);
}
private _toggleCustomIntegration() {
this.isCustomIntegration = !this.isCustomIntegration;
}
private _toggleCloud() {
this.isCloud = !this.isCloud;
}
static get styles() {
return css`
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
grid-gap: 16px 16px;
padding: 8px 16px 16px;
margin-bottom: 64px;
}
.container > * {
max-width: 500px;
}
ha-formfield {
margin: 8px 0;
display: block;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"demo-integration-card": DemoIntegrationCard;
}
}
+92 -25
View File
@@ -1,21 +1,11 @@
import {
customElement,
html,
LitElement,
property,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, query } from "lit/decorators";
import "../../../src/components/ha-card";
import {
SUPPORT_BRIGHTNESS,
SUPPORT_COLOR,
SUPPORT_COLOR_TEMP,
LightColorModes,
SUPPORT_EFFECT,
SUPPORT_FLASH,
SUPPORT_TRANSITION,
SUPPORT_WHITE_VALUE,
} from "../../../src/data/light";
import "../../../src/dialogs/more-info/more-info-content";
import { getEntity } from "../../../src/fake_data/entity";
@@ -32,7 +22,8 @@ const ENTITIES = [
getEntity("light", "kitchen_light", "on", {
friendly_name: "Brightness Light",
brightness: 200,
supported_features: SUPPORT_BRIGHTNESS,
supported_color_modes: [LightColorModes.BRIGHTNESS],
color_mode: LightColorModes.BRIGHTNESS,
}),
getEntity("light", "color_temperature_light", "on", {
friendly_name: "White Color Temperature Light",
@@ -40,20 +31,96 @@ const ENTITIES = [
color_temp: 75,
min_mireds: 30,
max_mireds: 150,
supported_features: SUPPORT_BRIGHTNESS + SUPPORT_COLOR_TEMP,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
],
color_mode: LightColorModes.COLOR_TEMP,
}),
getEntity("light", "color_effectslight", "on", {
friendly_name: "Color Effets Light",
getEntity("light", "color_hs_light", "on", {
friendly_name: "Color HS Light",
brightness: 255,
hs_color: [30, 100],
white_value: 36,
supported_features:
SUPPORT_BRIGHTNESS +
SUPPORT_EFFECT +
SUPPORT_FLASH +
SUPPORT_COLOR +
SUPPORT_TRANSITION +
SUPPORT_WHITE_VALUE,
rgb_color: [30, 100, 255],
min_mireds: 30,
max_mireds: 150,
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
LightColorModes.HS,
],
color_mode: LightColorModes.HS,
effect_list: ["random", "colorloop"],
}),
getEntity("light", "color_rgb_ct_light", "on", {
friendly_name: "Color RGB + CT Light",
brightness: 255,
color_temp: 75,
min_mireds: 30,
max_mireds: 150,
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
LightColorModes.RGB,
],
color_mode: LightColorModes.COLOR_TEMP,
effect_list: ["random", "colorloop"],
}),
getEntity("light", "color_RGB_light", "on", {
friendly_name: "Color Effets Light",
brightness: 255,
rgb_color: [30, 100, 255],
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_color_modes: [LightColorModes.BRIGHTNESS, LightColorModes.RGB],
color_mode: LightColorModes.RGB,
effect_list: ["random", "colorloop"],
}),
getEntity("light", "color_rgbw_light", "on", {
friendly_name: "Color RGBW Light",
brightness: 255,
rgbw_color: [30, 100, 255, 125],
min_mireds: 30,
max_mireds: 150,
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
LightColorModes.RGBW,
],
color_mode: LightColorModes.RGBW,
effect_list: ["random", "colorloop"],
}),
getEntity("light", "color_rgbww_light", "on", {
friendly_name: "Color RGBWW Light",
brightness: 255,
rgbww_color: [30, 100, 255, 125, 10],
min_mireds: 30,
max_mireds: 150,
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
LightColorModes.RGBWW,
],
color_mode: LightColorModes.RGBWW,
effect_list: ["random", "colorloop"],
}),
getEntity("light", "color_xy_light", "on", {
friendly_name: "Color XY Light",
brightness: 255,
xy_color: [30, 100],
rgb_color: [30, 100, 255],
min_mireds: 30,
max_mireds: 150,
supported_features: SUPPORT_EFFECT + SUPPORT_FLASH + SUPPORT_TRANSITION,
supported_color_modes: [
LightColorModes.BRIGHTNESS,
LightColorModes.COLOR_TEMP,
LightColorModes.XY,
],
color_mode: LightColorModes.XY,
effect_list: ["random", "colorloop"],
}),
];
+2 -1
View File
@@ -1,5 +1,6 @@
import "@material/mwc-button";
import { customElement, html, LitElement, TemplateResult } from "lit-element";
import { html, LitElement, TemplateResult } from "lit";
import { customElement } from "lit/decorators";
import "../../../src/components/ha-card";
import { ActionHandlerEvent } from "../../../src/data/lovelace";
import { actionHandler } from "../../../src/panels/lovelace/common/directives/action-handler-directive";
@@ -1,12 +1,6 @@
import { mdiArrowUpBoldCircle, mdiPuzzle } from "@mdi/js";
import {
css,
CSSResultArray,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { property } from "lit/decorators";
import memoizeOne from "memoize-one";
import { atLeastVersion } from "../../../src/common/config/version";
import { navigate } from "../../../src/common/navigate";
@@ -47,9 +41,7 @@ class HassioAddonRepositoryEl extends LitElement {
const repo = this.repo;
let _addons = this.addons;
if (!this.hass.userData?.showAdvanced) {
_addons = _addons.filter((addon) => {
return !addon.advanced;
});
_addons = _addons.filter((addon) => !addon.advanced);
}
const addons = this._getAddons(_addons, this.filter);
@@ -68,9 +60,7 @@ class HassioAddonRepositoryEl extends LitElement {
}
return html`
<div class="content">
<h1>
${repo.name}
</h1>
<h1>${repo.name}</h1>
<div class="card-group">
${addons.map(
(addon) => html`
@@ -130,10 +120,10 @@ class HassioAddonRepositoryEl extends LitElement {
}
private _addonTapped(ev) {
navigate(this, `/hassio/addon/${ev.currentTarget.addon.slug}`);
navigate(`/hassio/addon/${ev.currentTarget.addon.slug}`);
}
static get styles(): CSSResultArray {
static get styles(): CSSResultGroup {
return [
hassioStyle,
css`
+12 -15
View File
@@ -4,13 +4,13 @@ import "@material/mwc-list/mwc-list-item";
import { mdiDotsVertical } from "@mdi/js";
import {
css,
CSSResult,
internalProperty,
CSSResultGroup,
html,
LitElement,
property,
PropertyValues,
} from "lit-element";
import { html, TemplateResult } from "lit-html";
TemplateResult,
} from "lit";
import { property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { atLeastVersion } from "../../../src/common/config/version";
import { fireEvent } from "../../../src/common/dom/fire_event";
@@ -58,7 +58,7 @@ class HassioAddonStore extends LitElement {
@property({ attribute: false }) public route!: Route;
@internalProperty() private _filter?: string;
@state() private _filter?: string;
public async refreshData() {
await reloadHassioAddons(this.hass);
@@ -86,9 +86,7 @@ class HassioAddonStore extends LitElement {
main-page
supervisor
>
<span slot="header">
${this.supervisor.localize("panel.store")}
</span>
<span slot="header"> ${this.supervisor.localize("panel.store")} </span>
<ha-button-menu
corner="BOTTOM_START"
slot="toolbar-icon"
@@ -140,7 +138,7 @@ class HassioAddonStore extends LitElement {
protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps);
const repositoryUrl = extractSearchParam("repository_url");
navigate(this, "/hassio/store", true);
navigate("/hassio/store", { replace: true });
if (repositoryUrl) {
this._manageRepositories(repositoryUrl);
}
@@ -154,8 +152,8 @@ class HassioAddonStore extends LitElement {
repositories: HassioAddonRepository[],
addons: HassioAddonInfo[],
filter?: string
) => {
return repositories.sort(sortRepos).map((repo) => {
) =>
repositories.sort(sortRepos).map((repo) => {
const filteredAddons = addons.filter(
(addon) => addon.repository === repo.slug
);
@@ -171,8 +169,7 @@ class HassioAddonStore extends LitElement {
></hassio-addon-repository>
`
: html``;
});
}
})
);
private _handleAction(ev: CustomEvent<ActionDetail>) {
@@ -221,7 +218,7 @@ class HassioAddonStore extends LitElement {
this._filter = e.detail.value;
}
static get styles(): CSSResult {
static get styles(): CSSResultGroup {
return css`
hassio-addon-repository {
margin-top: 24px;
@@ -4,15 +4,13 @@ import "@polymer/paper-item/paper-item";
import "@polymer/paper-listbox/paper-listbox";
import {
css,
CSSResult,
customElement,
CSSResultGroup,
html,
internalProperty,
LitElement,
property,
PropertyValues,
TemplateResult,
} from "lit-element";
} from "lit";
import { customElement, property, state } from "lit/decorators";
import "web-animations-js/web-animations-next-lite.min";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-card";
@@ -39,15 +37,15 @@ class HassioAddonAudio extends LitElement {
@property({ attribute: false }) public addon!: HassioAddonDetails;
@internalProperty() private _error?: string;
@state() private _error?: string;
@internalProperty() private _inputDevices?: HassioHardwareAudioDevice[];
@state() private _inputDevices?: HassioHardwareAudioDevice[];
@internalProperty() private _outputDevices?: HassioHardwareAudioDevice[];
@state() private _outputDevices?: HassioHardwareAudioDevice[];
@internalProperty() private _selectedInput!: null | string;
@state() private _selectedInput!: null | string;
@internalProperty() private _selectedOutput!: null | string;
@state() private _selectedOutput!: null | string;
protected render(): TemplateResult {
return html`
@@ -69,13 +67,13 @@ class HassioAddonAudio extends LitElement {
.selected=${this._selectedInput!}
>
${this._inputDevices &&
this._inputDevices.map((item) => {
return html`
this._inputDevices.map(
(item) => html`
<paper-item device=${item.device || ""}>
${item.name}
</paper-item>
`;
})}
`
)}
</paper-listbox>
</paper-dropdown-menu>
<paper-dropdown-menu
@@ -90,13 +88,13 @@ class HassioAddonAudio extends LitElement {
.selected=${this._selectedOutput!}
>
${this._outputDevices &&
this._outputDevices.map((item) => {
return html`
this._outputDevices.map(
(item) => html`
<paper-item device=${item.device || ""}
>${item.name}</paper-item
>
`;
})}
`
)}
</paper-listbox>
</paper-dropdown-menu>
</div>
@@ -109,7 +107,7 @@ class HassioAddonAudio extends LitElement {
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
@@ -1,12 +1,5 @@
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../../src/components/ha-circular-progress";
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
@@ -70,7 +63,7 @@ class HassioAddonConfigDashboard extends LitElement {
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
@@ -3,18 +3,16 @@ import { ActionDetail } from "@material/mwc-list";
import "@material/mwc-list/mwc-list-item";
import { mdiDotsVertical } from "@mdi/js";
import "@polymer/iron-autogrow-textarea/iron-autogrow-textarea";
import { DEFAULT_SCHEMA, Type } from "js-yaml";
import {
css,
CSSResult,
customElement,
CSSResultGroup,
html,
internalProperty,
LitElement,
property,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
} from "lit";
import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/buttons/ha-progress-button";
@@ -30,6 +28,7 @@ import {
HassioAddonDetails,
HassioAddonSetOptionParams,
setHassioAddonOption,
validateHassioAddonOption,
} from "../../../../src/data/hassio/addon";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
@@ -41,6 +40,13 @@ import { hassioStyle } from "../../resources/hassio-style";
const SUPPORTED_UI_TYPES = ["string", "select", "boolean", "integer", "float"];
const ADDON_YAML_SCHEMA = DEFAULT_SCHEMA.extend([
new Type("!secret", {
kind: "scalar",
construct: (data) => `!secret ${data}`,
}),
]);
@customElement("hassio-addon-config")
class HassioAddonConfig extends LitElement {
@property({ attribute: false }) public addon!: HassioAddonDetails;
@@ -53,31 +59,27 @@ class HassioAddonConfig extends LitElement {
@property({ type: Boolean }) private _valid = true;
@internalProperty() private _canShowSchema = false;
@state() private _canShowSchema = false;
@internalProperty() private _showOptional = false;
@state() private _showOptional = false;
@internalProperty() private _error?: string;
@state() private _error?: string;
@internalProperty() private _options?: Record<string, unknown>;
@state() private _options?: Record<string, unknown>;
@internalProperty() private _yamlMode = false;
@state() private _yamlMode = false;
@query("ha-yaml-editor") private _editor?: HaYamlEditor;
public computeLabel = (entry: HaFormSchema): string => {
return (
this.addon.translations[this.hass.language]?.configuration?.[entry.name]
?.name ||
this.addon.translations.en?.configuration?.[entry.name].name ||
entry.name
);
};
public computeLabel = (entry: HaFormSchema): string =>
this.addon.translations[this.hass.language]?.configuration?.[entry.name]
?.name ||
this.addon.translations.en?.configuration?.[entry.name].name ||
entry.name;
private _filteredShchema = memoizeOne(
(options: Record<string, unknown>, schema: HaFormSchema[]) => {
return schema.filter((entry) => entry.name in options || entry.required);
}
(options: Record<string, unknown>, schema: HaFormSchema[]) =>
schema.filter((entry) => entry.name in options || entry.required)
);
protected render(): TemplateResult {
@@ -132,6 +134,7 @@ class HassioAddonConfig extends LitElement {
></ha-form>`
: html` <ha-yaml-editor
@value-changed=${this._configChanged}
.schema=${ADDON_YAML_SCHEMA}
></ha-yaml-editor>`}
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
${!this._yamlMode ||
@@ -266,36 +269,45 @@ class HassioAddonConfig extends LitElement {
private async _saveTapped(ev: CustomEvent): Promise<void> {
const button = ev.currentTarget as any;
const eventdata = {
success: true,
response: undefined,
path: "options",
};
button.progress = true;
this._error = undefined;
try {
const validation = await validateHassioAddonOption(
this.hass,
this.addon.slug,
this._editor?.value
);
if (!validation.valid) {
throw Error(validation.message);
}
await setHassioAddonOption(this.hass, this.addon.slug, {
options: this._yamlMode ? this._editor?.value : this._options,
});
this._configHasChanged = false;
const eventdata = {
success: true,
response: undefined,
path: "options",
};
fireEvent(this, "hass-api-called", eventdata);
if (this.addon?.state === "started") {
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
}
} catch (err) {
this._error = this.supervisor.localize(
"addon.configuration.options.failed_to_save",
"addon.failed_to_save",
"error",
extractApiErrorMessage(err)
);
eventdata.success = false;
}
button.progress = false;
fireEvent(this, "hass-api-called", eventdata);
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
@@ -1,15 +1,13 @@
import { PaperInputElement } from "@polymer/paper-input/paper-input";
import {
css,
CSSResult,
customElement,
CSSResultGroup,
html,
internalProperty,
LitElement,
property,
PropertyValues,
TemplateResult,
} from "lit-element";
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-card";
@@ -43,9 +41,9 @@ class HassioAddonNetwork extends LitElement {
@property({ attribute: false }) public addon!: HassioAddonDetails;
@internalProperty() private _error?: string;
@state() private _error?: string;
@internalProperty() private _config?: NetworkItem[];
@state() private _config?: NetworkItem[];
public connectedCallback(): void {
super.connectedCallback();
@@ -79,12 +77,10 @@ class HassioAddonNetwork extends LitElement {
"addon.configuration.network.host"
)}
</th>
<th>
${this.supervisor.localize("common.description")}
</th>
<th>${this.supervisor.localize("common.description")}</th>
</tr>
${this._config!.map((item) => {
return html`
${this._config!.map(
(item) => html`
<tr>
<td>${item.container}</td>
<td>
@@ -100,8 +96,8 @@ class HassioAddonNetwork extends LitElement {
</td>
<td>${this._computeDescription(item)}</td>
</tr>
`;
})}
`
)}
</tbody>
</table>
</div>
@@ -124,25 +120,20 @@ class HassioAddonNetwork extends LitElement {
}
}
private _computeDescription = (item: NetworkItem): string => {
return (
this.addon.translations[this.hass.language]?.network?.[item.container]
?.description ||
this.addon.translations.en?.network?.[item.container]?.description ||
item.description
);
};
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 _setNetworkConfig(): void {
const network = this.addon.network || {};
const description = this.addon.network_description || {};
const items: NetworkItem[] = Object.keys(network).map((key) => {
return {
container: key,
host: network[key],
description: description[key],
};
});
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));
}
@@ -223,7 +214,7 @@ class HassioAddonNetwork extends LitElement {
button.progress = false;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
@@ -1,14 +1,5 @@
import "../../../../src/components/ha-card";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import "../../../../src/components/ha-circular-progress";
import "../../../../src/components/ha-markdown";
import {
@@ -21,6 +12,7 @@ import { haStyle } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { hassioStyle } from "../../resources/hassio-style";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
import { customElement, property, state } from "lit/decorators";
@customElement("hassio-addon-documentation-tab")
class HassioAddonDocumentationDashboard extends LitElement {
@@ -30,9 +22,9 @@ class HassioAddonDocumentationDashboard extends LitElement {
@property({ attribute: false }) public addon?: HassioAddonDetails;
@internalProperty() private _error?: string;
@state() private _error?: string;
@internalProperty() private _content?: string;
@state() private _content?: string;
public async connectedCallback(): Promise<void> {
super.connectedCallback();
@@ -57,7 +49,7 @@ class HassioAddonDocumentationDashboard extends LitElement {
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
+12 -15
View File
@@ -4,16 +4,8 @@ import {
mdiInformationVariant,
mdiMathLog,
} from "@mdi/js";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
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 { navigate } from "../../../src/common/navigate";
@@ -52,7 +44,7 @@ class HassioAddonDashboard extends LitElement {
@property({ type: Boolean }) public narrow!: boolean;
@internalProperty() _error?: string;
@state() _error?: string;
private _computeTail = memoizeOne((route: Route) => {
const dividerPos = route.path.indexOf("/", 1);
@@ -133,7 +125,7 @@ class HassioAddonDashboard extends LitElement {
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
@@ -177,12 +169,13 @@ class HassioAddonDashboard extends LitElement {
const requestedAddon = extractSearchParam("addon");
if (requestedAddon) {
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
const validAddon = addonsInfo.addons
.some((addon) => addon.slug === requestedAddon);
const validAddon = addonsInfo.addons.some(
(addon) => addon.slug === requestedAddon
);
if (!validAddon) {
this._error = this.supervisor.localize("my.error_addon_not_found");
} else {
navigate(this, `/hassio/addon/${requestedAddon}`, true);
navigate(`/hassio/addon/${requestedAddon}`, { replace: true });
}
}
}
@@ -190,6 +183,10 @@ class HassioAddonDashboard extends LitElement {
}
private async _apiCalled(ev): Promise<void> {
if (!ev.detail.success) {
return;
}
const pathSplit: string[] = ev.detail.path?.split("/");
if (!pathSplit || pathSplit.length === 0) {
+1 -1
View File
@@ -1,4 +1,4 @@
import { customElement, property } from "lit-element";
import { customElement, property } from "lit/decorators";
import { HassioAddonDetails } from "../../../src/data/hassio/addon";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import {
@@ -1,12 +1,5 @@
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../../src/components/ha-circular-progress";
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
@@ -42,7 +35,7 @@ class HassioAddonInfoDashboard extends LitElement {
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
+26 -36
View File
@@ -14,17 +14,9 @@ import {
mdiPound,
mdiShield,
} from "@mdi/js";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { classMap } from "lit-html/directives/class-map";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
import { atLeastVersion } from "../../../../src/common/config/version";
import { fireEvent } from "../../../../src/common/dom/fire_event";
@@ -90,9 +82,9 @@ class HassioAddonInfo extends LitElement {
@property({ attribute: false }) public supervisor!: Supervisor;
@internalProperty() private _metrics?: HassioStats;
@state() private _metrics?: HassioStats;
@internalProperty() private _error?: string;
@state() private _error?: string;
private _addonStoreInfo = memoizeOne(
(slug: string, storeAddons: StoreAddon[]) =>
@@ -171,16 +163,16 @@ class HassioAddonInfo extends LitElement {
: ""}
</div>
<div class="card-actions">
<mwc-button @click=${this._updateClicked}>
${this.supervisor.localize("common.update")}
</mwc-button>
${this.addon.changelog
? html`
<mwc-button @click=${this._openChangelog}>
${this.supervisor.localize("addon.dashboard.changelog")}
</mwc-button>
`
: ""}
: html`<span></span>`}
<mwc-button @click=${this._updateClicked}>
${this.supervisor.localize("common.update")}
</mwc-button>
</div>
</ha-card>
`
@@ -242,14 +234,18 @@ class HassioAddonInfo extends LitElement {
? html`
Current version: ${this.addon.version}
<div class="changelog" @click=${this._openChangelog}>
(<span class="changelog-link">${
this.supervisor.localize("addon.dashboard.changelog")}</span
(<span class="changelog-link"
>${this.supervisor.localize(
"addon.dashboard.changelog"
)}</span
>)
</div>
`
: html`<span class="changelog-link" @click=${this._openChangelog}>${
this.supervisor.localize("addon.dashboard.changelog")
}</span>`}
: html`<span class="changelog-link" @click=${this._openChangelog}
>${this.supervisor.localize(
"addon.dashboard.changelog"
)}</span
>`}
</div>
<div class="description light-color">
@@ -257,13 +253,9 @@ class HassioAddonInfo extends LitElement {
${this.supervisor.localize(
"addon.dashboard.visit_addon_page",
"name",
html`<a
href="${this.addon.url!}"
target="_blank"
rel="noreferrer"
>
${this.addon.name}
</a>`
html`<a href="${this.addon.url!}" target="_blank" rel="noreferrer"
>${this.addon.name}</a
>`
)}
</div>
<div class="addon-container">
@@ -562,9 +554,7 @@ class HassioAddonInfo extends LitElement {
<span slot="heading">
${this.supervisor.localize("addon.dashboard.hostname")}
</span>
<code slot="description">
${this.addon.hostname}
</code>
<code slot="description"> ${this.addon.hostname} </code>
</ha-settings-row>
${metrics.map(
(metric) =>
@@ -771,7 +761,7 @@ class HassioAddonInfo extends LitElement {
}
private _openIngress(): void {
navigate(this, `/hassio/ingress/${this.addon.slug}`);
navigate(`/hassio/ingress/${this.addon.slug}`);
}
private get _computeShowIngressUI(): boolean {
@@ -993,7 +983,7 @@ class HassioAddonInfo extends LitElement {
addons: [this.addon.slug],
homeassistant: false,
},
updateHandler: async () => await this._updateAddon(),
updateHandler: async () => this._updateAddon(),
});
}
@@ -1061,7 +1051,7 @@ class HassioAddonInfo extends LitElement {
}
private _openConfiguration(): void {
navigate(this, `/hassio/addon/${this.addon.slug}/config`);
navigate(`/hassio/addon/${this.addon.slug}/config`);
}
private async _uninstallClicked(ev: CustomEvent): Promise<void> {
@@ -1100,7 +1090,7 @@ class HassioAddonInfo extends LitElement {
button.progress = false;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
@@ -1,12 +1,5 @@
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../../src/components/ha-circular-progress";
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
@@ -38,7 +31,7 @@ class HassioAddonLogDashboard extends LitElement {
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
+5 -13
View File
@@ -1,14 +1,6 @@
import "@material/mwc-button";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../src/components/ha-card";
import {
fetchHassioAddonLogs,
@@ -29,9 +21,9 @@ class HassioAddonLogs extends LitElement {
@property({ attribute: false }) public addon!: HassioAddonDetails;
@internalProperty() private _error?: string;
@state() private _error?: string;
@internalProperty() private _content?: string;
@state() private _content?: string;
public async connectedCallback(): Promise<void> {
super.connectedCallback();
@@ -59,7 +51,7 @@ class HassioAddonLogs extends LitElement {
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
+3 -10
View File
@@ -1,12 +1,5 @@
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
interface State {
bold: boolean;
@@ -25,7 +18,7 @@ class HassioAnsiToHtml extends LitElement {
return html`${this._parseTextToColoredPre(this.content)}`;
}
static get styles(): CSSResult {
static get styles(): CSSResultGroup {
return css`
pre {
overflow-x: auto;
+8 -15
View File
@@ -1,13 +1,6 @@
import { mdiHelpCircle } from "@mdi/js";
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../src/components/ha-relative-time";
import "../../../src/components/ha-svg-icon";
import { HomeAssistant } from "../../../src/types";
@@ -56,13 +49,13 @@ class HassioCardContent extends LitElement {
></ha-svg-icon>
`}
<div>
<div class="title">
${this.title}
</div>
<div class="title">${this.title}</div>
<div class="addition">
${this.description}
${/* treat as available when undefined */
this.available === false ? " (Not available)" : ""}
${
/* treat as available when undefined */
this.available === false ? " (Not available)" : ""
}
${this.datetime
? html`
<ha-relative-time
@@ -77,7 +70,7 @@ class HassioCardContent extends LitElement {
`;
}
static get styles(): CSSResult {
static get styles(): CSSResultGroup {
return css`
ha-svg-icon {
margin-right: 24px;
@@ -2,13 +2,8 @@ import "@material/mwc-icon-button/mwc-icon-button";
import { mdiFolderUpload } from "@mdi/js";
import "@polymer/iron-input/iron-input";
import "@polymer/paper-input/paper-input-container";
import {
customElement,
html,
internalProperty,
LitElement,
TemplateResult,
} from "lit-element";
import { html, LitElement, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators";
import { fireEvent } from "../../../src/common/dom/fire_event";
import "../../../src/components/ha-circular-progress";
import "../../../src/components/ha-file-upload";
@@ -33,9 +28,9 @@ const MAX_FILE_SIZE = 1 * 1024 * 1024 * 1024; // 1GB
export class HassioUploadSnapshot extends LitElement {
public hass!: HomeAssistant;
@internalProperty() public value: string | null = null;
@state() public value: string | null = null;
@internalProperty() private _uploading = false;
@state() private _uploading = false;
public render(): TemplateResult {
return html`
@@ -0,0 +1,54 @@
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../src/components/ha-svg-icon";
@customElement("supervisor-formfield-label")
class SupervisorFormfieldLabel extends LitElement {
@property({ type: String }) public label!: string;
@property({ type: String }) public imageUrl?: string;
@property({ type: String }) public iconPath?: string;
@property({ type: String }) public version?: string;
protected render(): TemplateResult {
return html`
${this.imageUrl
? html`<img loading="lazy" .src=${this.imageUrl} class="icon" />`
: this.iconPath
? html`<ha-svg-icon .path=${this.iconPath} class="icon"></ha-svg-icon>`
: ""}
<span class="label">${this.label}</span>
${this.version
? html`<span class="version">(${this.version})</span>`
: ""}
`;
}
static get styles(): CSSResultGroup {
return css`
:host {
display: flex;
align-items: center;
}
.label {
margin-right: 4px;
}
.version {
color: var(--secondary-text-color);
}
.icon {
max-height: 22px;
max-width: 22px;
margin-right: 8px;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"supervisor-formfield-label": SupervisorFormfieldLabel;
}
}
+8 -18
View File
@@ -1,13 +1,6 @@
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { classMap } from "lit-html/directives/class-map";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import "../../../src/components/ha-bar";
import "../../../src/components/ha-settings-row";
import { roundWithOneDecimal } from "../../../src/util/calculate";
@@ -23,13 +16,9 @@ class SupervisorMetric extends LitElement {
protected render(): TemplateResult {
const roundedValue = roundWithOneDecimal(this.value);
return html`<ha-settings-row>
<span slot="heading">
${this.description}
</span>
<span slot="heading"> ${this.description} </span>
<div slot="description" .title=${this.tooltip ?? ""}>
<span class="value">
${roundedValue} %
</span>
<span class="value"> ${roundedValue} % </span>
<ha-bar
class="${classMap({
"target-warning": roundedValue > 50,
@@ -41,7 +30,7 @@ class SupervisorMetric extends LitElement {
</ha-settings-row>`;
}
static get styles(): CSSResult {
static get styles(): CSSResultGroup {
return css`
ha-settings-row {
padding: 0;
@@ -73,8 +62,9 @@ class SupervisorMetric extends LitElement {
);
}
.value {
width: 42px;
width: 48px;
padding-right: 4px;
flex-shrink: 0;
}
`;
}
@@ -0,0 +1,450 @@
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 { atLeastVersion } from "../../../src/common/config/version";
import { formatDate } from "../../../src/common/datetime/format_date";
import { formatDateTime } from "../../../src/common/datetime/format_date_time";
import { LocalizeFunc } from "../../../src/common/translations/localize";
import "../../../src/components/ha-checkbox";
import "../../../src/components/ha-formfield";
import "../../../src/components/ha-radio";
import type { HaRadio } from "../../../src/components/ha-radio";
import {
HassioFullSnapshotCreateParams,
HassioPartialSnapshotCreateParams,
HassioSnapshotDetail,
} from "../../../src/data/hassio/snapshot";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import { PolymerChangedEvent } from "../../../src/polymer-types";
import { HomeAssistant } from "../../../src/types";
import "./supervisor-formfield-label";
interface CheckboxItem {
slug: string;
checked: boolean;
name: string;
}
interface AddonCheckboxItem extends CheckboxItem {
version: string;
}
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 });
}
if (folders.includes("share")) {
list.push({ slug: "share", name: "Share", checked: false });
}
if (folders.includes("media")) {
list.push({ slug: "media", name: "Media", checked: false });
}
if (folders.includes("addons/local")) {
list.push({ slug: "addons/local", name: "Local add-ons", checked: false });
}
return list.sort((a, b) => (a.name > b.name ? 1 : -1));
};
const _computeAddons = (addons): AddonCheckboxItem[] =>
addons
.map((addon) => ({
slug: addon.slug,
name: addon.name,
version: addon.version,
checked: false,
}))
.sort((a, b) => (a.name > b.name ? 1 : -1));
@customElement("supervisor-snapshot-content")
export class SupervisorSnapshotContent extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property() public localize?: LocalizeFunc;
@property({ attribute: false }) public supervisor?: Supervisor;
@property({ attribute: false }) public snapshot?: HassioSnapshotDetail;
@property() public snapshotType: HassioSnapshotDetail["type"] = "full";
@property({ attribute: false }) public folders?: CheckboxItem[];
@property({ attribute: false }) public addons?: AddonCheckboxItem[];
@property({ type: Boolean }) public homeAssistant = false;
@property({ type: Boolean }) public snapshotHasPassword = false;
@property({ type: Boolean }) public onboarding = false;
@property() public snapshotName = "";
@property() public snapshotPassword = "";
@property() public confirmSnapshotPassword = "";
public willUpdate(changedProps) {
super.willUpdate(changedProps);
if (!this.hasUpdated) {
this.folders = _computeFolders(
this.snapshot
? this.snapshot.folders
: ["homeassistant", "ssl", "share", "media", "addons/local"]
);
this.addons = _computeAddons(
this.snapshot
? this.snapshot.addons
: this.supervisor?.supervisor.addons
);
this.snapshotType = this.snapshot?.type || "full";
this.snapshotName = this.snapshot?.name || "";
this.snapshotHasPassword = this.snapshot?.protected || false;
}
}
private _localize = (string: string) =>
this.supervisor?.localize(`snapshot.${string}`) ||
this.localize!(`ui.panel.page-onboarding.restore.${string}`);
protected render(): TemplateResult {
if (!this.onboarding && !this.supervisor) {
return html``;
}
const foldersSection =
this.snapshotType === "partial" ? this._getSection("folders") : undefined;
const addonsSection =
this.snapshotType === "partial" ? this._getSection("addons") : undefined;
return html`
${this.snapshot
? html`<div class="details">
${this.snapshot.type === "full"
? this._localize("full_snapshot")
: this._localize("partial_snapshot")}
(${Math.ceil(this.snapshot.size * 10) / 10 + " MB"})<br />
${this.hass
? formatDateTime(new Date(this.snapshot.date), this.hass.locale)
: this.snapshot.date}
</div>`
: html`<paper-input
name="snapshotName"
.label=${this.supervisor?.localize("snapshot.name") || "Name"}
.value=${this.snapshotName}
@value-changed=${this._handleTextValueChanged}
>
</paper-input>`}
${!this.snapshot || this.snapshot.type === "full"
? html`<div class="sub-header">
${!this.snapshot
? this._localize("type")
: this._localize("select_type")}
</div>
<div class="snapshot-types">
<ha-formfield .label=${this._localize("full_snapshot")}>
<ha-radio
@change=${this._handleRadioValueChanged}
value="full"
name="snapshotType"
.checked=${this.snapshotType === "full"}
>
</ha-radio>
</ha-formfield>
<ha-formfield .label=${this._localize("partial_snapshot")}>
<ha-radio
@change=${this._handleRadioValueChanged}
value="partial"
name="snapshotType"
.checked=${this.snapshotType === "partial"}
>
</ha-radio>
</ha-formfield>
</div>`
: ""}
${this.snapshotType === "partial"
? html`<div class="partial-picker">
${this.snapshot && this.snapshot.homeassistant
? html`
<ha-formfield
.label=${html`<supervisor-formfield-label
label="Home Assistant"
.iconPath=${mdiHomeAssistant}
.version=${this.snapshot.homeassistant}
>
</supervisor-formfield-label>`}
>
<ha-checkbox
.checked=${this.homeAssistant}
@click=${() => {
this.homeAssistant = !this.homeAssistant;
}}
>
</ha-checkbox>
</ha-formfield>
`
: ""}
${foldersSection?.templates.length
? html`
<ha-formfield
.label=${html`<supervisor-formfield-label
.label=${this._localize("folders")}
.iconPath=${mdiFolder}
>
</supervisor-formfield-label>`}
>
<ha-checkbox
@change=${this._toggleSection}
.checked=${foldersSection.checked}
.indeterminate=${foldersSection.indeterminate}
.section=${"folders"}
>
</ha-checkbox>
</ha-formfield>
<div class="section-content">${foldersSection.templates}</div>
`
: ""}
${addonsSection?.templates.length
? html`
<ha-formfield
.label=${html`<supervisor-formfield-label
.label=${this._localize("addons")}
.iconPath=${mdiPuzzle}
>
</supervisor-formfield-label>`}
>
<ha-checkbox
@change=${this._toggleSection}
.checked=${addonsSection.checked}
.indeterminate=${addonsSection.indeterminate}
.section=${"addons"}
>
</ha-checkbox>
</ha-formfield>
<div class="section-content">${addonsSection.templates}</div>
`
: ""}
</div> `
: ""}
${this.snapshotType === "partial" &&
(!this.snapshot || this.snapshotHasPassword)
? html`<hr />`
: ""}
${!this.snapshot
? html`<ha-formfield
class="password"
.label=${this._localize("password_protection")}
>
<ha-checkbox
.checked=${this.snapshotHasPassword}
@change=${this._toggleHasPassword}
>
</ha-checkbox>
</ha-formfield>`
: ""}
${this.snapshotHasPassword
? html`
<paper-input
.label=${this._localize("password")}
type="password"
name="snapshotPassword"
.value=${this.snapshotPassword}
@value-changed=${this._handleTextValueChanged}
>
</paper-input>
${!this.snapshot
? html` <paper-input
.label=${this.supervisor?.localize("confirm_password")}
type="password"
name="confirmSnapshotPassword"
.value=${this.confirmSnapshotPassword}
@value-changed=${this._handleTextValueChanged}
>
</paper-input>`
: ""}
`
: ""}
`;
}
static get styles(): CSSResultGroup {
return css`
.partial-picker ha-formfield {
display: block;
}
.partial-picker ha-checkbox {
--mdc-checkbox-touch-target-size: 32px;
}
.partial-picker {
display: block;
margin: 0px -6px;
}
supervisor-formfield-label {
display: inline-flex;
align-items: center;
}
hr {
border-color: var(--divider-color);
border-bottom: none;
margin: 16px 0;
}
.details {
color: var(--secondary-text-color);
}
.section-content {
display: flex;
flex-direction: column;
margin-left: 30px;
}
ha-formfield.password {
display: block;
margin: 0 -14px -16px;
}
.snapshot-types {
display: flex;
margin-left: -13px;
}
.sub-header {
margin-top: 8px;
}
`;
}
public snapshotDetails():
| HassioPartialSnapshotCreateParams
| HassioFullSnapshotCreateParams {
const data: any = {};
if (!this.snapshot) {
data.name = this.snapshotName || formatDate(new Date(), this.hass.locale);
}
if (this.snapshotHasPassword) {
data.password = this.snapshotPassword;
if (!this.snapshot) {
data.confirm_password = this.confirmSnapshotPassword;
}
}
if (this.snapshotType === "full") {
return data;
}
const addons = this.addons
?.filter((addon) => addon.checked)
.map((addon) => addon.slug);
const folders = this.folders
?.filter((folder) => folder.checked)
.map((folder) => folder.slug);
if (addons?.length) {
data.addons = addons;
}
if (folders?.length) {
data.folders = folders;
}
if (this.homeAssistant) {
data.homeassistant = this.homeAssistant;
}
return data;
}
private _getSection(section: string) {
const templates: TemplateResult[] = [];
const addons =
section === "addons"
? new Map(
this.supervisor?.addon.addons.map((item) => [item.slug, item])
)
: undefined;
let checkedItems = 0;
this[section].forEach((item) => {
templates.push(html`<ha-formfield
.label=${html`<supervisor-formfield-label
.label=${item.name}
.iconPath=${section === "addons" ? mdiPuzzle : mdiFolder}
.imageUrl=${section === "addons" &&
!this.onboarding &&
atLeastVersion(this.hass.config.version, 0, 105) &&
addons?.get(item.slug)?.icon
? `/api/hassio/addons/${item.slug}/icon`
: undefined}
.version=${item.version}
>
</supervisor-formfield-label>`}
>
<ha-checkbox
.item=${item}
.checked=${item.checked}
.section=${section}
@change=${this._updateSectionEntry}
>
</ha-checkbox>
</ha-formfield>`);
if (item.checked) {
checkedItems++;
}
});
const checked = checkedItems === this[section].length;
return {
templates,
checked,
indeterminate: !checked && checkedItems !== 0,
};
}
private _handleRadioValueChanged(ev: CustomEvent) {
const input = ev.currentTarget as HaRadio;
this[input.name] = input.value;
}
private _handleTextValueChanged(ev: PolymerChangedEvent<string>) {
const input = ev.currentTarget as PaperInputElement;
this[input.name!] = ev.detail.value;
}
private _toggleHasPassword(): void {
this.snapshotHasPassword = !this.snapshotHasPassword;
}
private _toggleSection(ev): void {
const section = ev.currentTarget.section;
this[section] = (section === "addons" ? this.addons : this.folders)!.map(
(item) => ({
...item,
checked: ev.currentTarget.checked,
})
);
}
private _updateSectionEntry(ev): void {
const item = ev.currentTarget.item;
const section = ev.currentTarget.section;
this[section] = this[section].map((entry) =>
entry.slug === item.slug
? {
...entry,
checked: ev.currentTarget.checked,
}
: entry
);
}
}
declare global {
interface HTMLElementTagNameMap {
"supervisor-snapshot-content": SupervisorSnapshotContent;
}
}
+5 -12
View File
@@ -1,13 +1,6 @@
import { mdiArrowUpBoldCircle, mdiPuzzle } from "@mdi/js";
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { atLeastVersion } from "../../../src/common/config/version";
import { navigate } from "../../../src/common/navigate";
import { compare } from "../../../src/common/string/compare";
@@ -90,7 +83,7 @@ class HassioAddons extends LitElement {
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
@@ -103,11 +96,11 @@ class HassioAddons extends LitElement {
}
private _addonTapped(ev: any): void {
navigate(this, `/hassio/addon/${ev.currentTarget.addon.slug}/info`);
navigate(`/hassio/addon/${ev.currentTarget.addon.slug}/info`);
}
private _openStore(): void {
navigate(this, "/hassio/store");
navigate("/hassio/store");
}
}
+3 -10
View File
@@ -1,12 +1,5 @@
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import "../../../src/layouts/hass-tabs-subpage";
import { haStyle } from "../../../src/resources/styles";
@@ -53,7 +46,7 @@ class HassioDashboard extends LitElement {
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
css`
+31 -19
View File
@@ -1,14 +1,7 @@
import "@material/mwc-button";
import { mdiHomeAssistant } from "@mdi/js";
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
import { atLeastVersion } from "../../../src/common/config/version";
import { fireEvent } from "../../../src/common/dom/fire_event";
@@ -40,9 +33,8 @@ import { HomeAssistant } from "../../../src/types";
import { showDialogSupervisorUpdate } from "../dialogs/update/show-dialog-update";
import { hassioStyle } from "../resources/hassio-style";
const computeVersion = (key: string, version: string): string => {
return key === "os" ? version : `${key}-${version}`;
};
const computeVersion = (key: string, version: string): string =>
key === "os" ? version : `${key}-${version}`;
@customElement("hassio-update")
export class HassioUpdate extends LitElement {
@@ -50,11 +42,12 @@ export class HassioUpdate extends LitElement {
@property({ attribute: false }) public supervisor!: Supervisor;
private _pendingUpdates = memoizeOne((supervisor: Supervisor): number => {
return Object.keys(supervisor).filter(
(value) => supervisor[value].update_available
).length;
});
private _pendingUpdates = memoizeOne(
(supervisor: Supervisor): number =>
Object.keys(supervisor).filter(
(value) => supervisor[value].update_available
).length
);
protected render(): TemplateResult {
if (!this.supervisor) {
@@ -227,13 +220,32 @@ export class HassioUpdate extends LitElement {
}
private async _updateCore(): Promise<void> {
await updateCore(this.hass);
try {
await updateCore(this.hass);
} catch (err) {
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
showAlertDialog(this, {
title: this.supervisor.localize(
"common.failed_to_update_name",
"name",
"Home Assistant Core"
),
text: extractApiErrorMessage(err),
});
return;
}
}
fireEvent(this, "supervisor-collection-refresh", {
collection: "core",
});
fireEvent(this, "supervisor-applying-update", {
name: "Home Assistant Core",
version: this.supervisor.core.version_latest,
});
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
+194
View File
@@ -0,0 +1,194 @@
import { mdiClose } from "@mdi/js";
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 { compare } from "../../../../src/common/string/compare";
import "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-expansion-panel";
import { HassioHardwareInfo } from "../../../../src/data/hassio/hardware";
import { dump } from "../../../../src/resources/js-yaml-dump";
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { HassioHardwareDialogParams } from "./show-dialog-hassio-hardware";
const _filterDevices = memoizeOne(
(showAdvanced: boolean, hardware: HassioHardwareInfo, filter: string) =>
hardware.devices
.filter(
(device) =>
(showAdvanced ||
["tty", "gpio", "input"].includes(device.subsystem)) &&
(device.by_id?.toLowerCase().includes(filter) ||
device.name.toLowerCase().includes(filter) ||
device.dev_path.toLocaleLowerCase().includes(filter) ||
JSON.stringify(device.attributes)
.toLocaleLowerCase()
.includes(filter))
)
.sort((a, b) => compare(a.name, b.name))
);
@customElement("dialog-hassio-hardware")
class HassioHardwareDialog extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@state() private _dialogParams?: HassioHardwareDialogParams;
@state() private _filter?: string;
public showDialog(params: HassioHardwareDialogParams) {
this._dialogParams = params;
}
public closeDialog() {
this._dialogParams = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
protected render(): TemplateResult {
if (!this._dialogParams) {
return html``;
}
const devices = _filterDevices(
this.hass.userData?.showAdvanced || false,
this._dialogParams.hardware,
(this._filter || "").toLowerCase()
);
return html`
<ha-dialog
open
scrimClickAction
hideActions
@closed=${this.closeDialog}
.heading=${true}
>
<div class="header" slot="heading">
<h2>
${this._dialogParams.supervisor.localize("dialog.hardware.title")}
</h2>
<mwc-icon-button dialogAction="close">
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
</mwc-icon-button>
<search-input
autofocus
no-label-float
.filter=${this._filter}
@value-changed=${this._handleSearchChange}
.label=${this._dialogParams.supervisor.localize(
"dialog.hardware.search"
)}
>
</search-input>
</div>
${devices.map(
(device) =>
html`<ha-expansion-panel
.header=${device.name}
.secondary=${device.by_id || undefined}
outlined
>
<div class="device-property">
<span>
${this._dialogParams!.supervisor.localize(
"dialog.hardware.subsystem"
)}:
</span>
<span>${device.subsystem}</span>
</div>
<div class="device-property">
<span>
${this._dialogParams!.supervisor.localize(
"dialog.hardware.device_path"
)}:
</span>
<code>${device.dev_path}</code>
</div>
${device.by_id
? html` <div class="device-property">
<span>
${this._dialogParams!.supervisor.localize(
"dialog.hardware.id"
)}:
</span>
<code>${device.by_id}</code>
</div>`
: ""}
<div class="attributes">
<span>
${this._dialogParams!.supervisor.localize(
"dialog.hardware.attributes"
)}:
</span>
<pre>${dump(device.attributes, { indent: 2 })}</pre>
</div>
</ha-expansion-panel>`
)}
</ha-dialog>
`;
}
private _handleSearchChange(ev: CustomEvent) {
this._filter = ev.detail.value;
}
static get styles(): CSSResultGroup {
return [
haStyle,
haStyleDialog,
css`
mwc-icon-button {
position: absolute;
right: 16px;
top: 10px;
text-decoration: none;
color: var(--primary-text-color);
}
h2 {
margin: 18px 42px 0 18px;
color: var(--primary-text-color);
}
ha-expansion-panel {
margin: 4px 0;
}
pre,
code {
background-color: var(--markdown-code-background-color, none);
border-radius: 3px;
}
pre {
padding: 16px;
overflow: auto;
line-height: 1.45;
font-family: var(--code-font-family, monospace);
}
code {
font-size: 85%;
padding: 0.2em 0.4em;
}
search-input {
margin: 0 16px;
display: block;
}
.device-property {
display: flex;
justify-content: space-between;
}
.attributes {
margin-top: 12px;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"dialog-hassio-hardware": HassioHardwareDialog;
}
}
@@ -0,0 +1,19 @@
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { HassioHardwareInfo } from "../../../../src/data/hassio/hardware";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
export interface HassioHardwareDialogParams {
supervisor: Supervisor;
hardware: HassioHardwareInfo;
}
export const showHassioHardwareDialog = (
element: HTMLElement,
dialogParams: HassioHardwareDialogParams
): void => {
fireEvent(element, "show-dialog", {
dialogTag: "dialog-hassio-hardware",
dialogImport: () => import("./dialog-hassio-hardware"),
dialogParams,
});
};
@@ -1,13 +1,5 @@
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { createCloseHeading } from "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-markdown";
import { haStyleDialog } from "../../../../src/resources/styles";
@@ -23,7 +15,7 @@ class HassioMarkdownDialog extends LitElement {
@property() public content!: string;
@internalProperty() private _opened = false;
@state() private _opened = false;
public showDialog(params: HassioMarkdownDialogParams) {
this.title = params.title;
@@ -50,7 +42,7 @@ class HassioMarkdownDialog extends LitElement {
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyleDialog,
hassioStyle,
@@ -6,17 +6,9 @@ import "@material/mwc-tab";
import "@material/mwc-tab-bar";
import { mdiClose } from "@mdi/js";
import { PaperInputElement } from "@polymer/paper-input/paper-input";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { cache } from "lit-html/directives/cache";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { cache } from "lit/directives/cache";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/ha-circular-progress";
import "../../../../src/components/ha-dialog";
@@ -47,38 +39,39 @@ import { HassioNetworkDialogParams } from "./show-dialog-network";
const IP_VERSIONS = ["ipv4", "ipv6"];
@customElement("dialog-hassio-network")
export class DialogHassioNetwork extends LitElement
export class DialogHassioNetwork
extends LitElement
implements HassDialog<HassioNetworkDialogParams> {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public supervisor!: Supervisor;
@internalProperty() private _accessPoints?: AccessPoints;
@state() private _accessPoints?: AccessPoints;
@internalProperty() private _curTabIndex = 0;
@state() private _curTabIndex = 0;
@internalProperty() private _dirty = false;
@state() private _dirty = false;
@internalProperty() private _interface?: NetworkInterface;
@state() private _interface?: NetworkInterface;
@internalProperty() private _interfaces!: NetworkInterface[];
@state() private _interfaces!: NetworkInterface[];
@internalProperty() private _params?: HassioNetworkDialogParams;
@state() private _params?: HassioNetworkDialogParams;
@internalProperty() private _processing = false;
@state() private _processing = false;
@internalProperty() private _scanning = false;
@state() private _scanning = false;
@internalProperty() private _wifiConfiguration?: WifiConfiguration;
@state() private _wifiConfiguration?: WifiConfiguration;
public async showDialog(params: HassioNetworkDialogParams): Promise<void> {
this._params = params;
this._dirty = false;
this._curTabIndex = 0;
this.supervisor = params.supervisor;
this._interfaces = params.supervisor.network.interfaces.sort((a, b) => {
return a.primary > b.primary ? -1 : 1;
});
this._interfaces = params.supervisor.network.interfaces.sort((a, b) =>
a.primary > b.primary ? -1 : 1
);
this._interface = { ...this._interfaces[this._curTabIndex] };
await this.updateComplete;
@@ -542,7 +535,7 @@ export class DialogHassioNetwork extends LitElement
this._wifiConfiguration![id] = value;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyleDialog,
css`
@@ -3,16 +3,8 @@ import "@material/mwc-icon-button/mwc-icon-button";
import "@material/mwc-list/mwc-list-item";
import { mdiDelete } from "@mdi/js";
import { PaperInputElement } from "@polymer/paper-input/paper-input";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../src/components/ha-circular-progress";
import { createCloseHeading } from "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-svg-icon";
@@ -39,21 +31,21 @@ class HassioRegistriesDialog extends LitElement {
username: string;
}[];
@internalProperty() private _registry?: string;
@state() private _registry?: string;
@internalProperty() private _username?: string;
@state() private _username?: string;
@internalProperty() private _password?: string;
@state() private _password?: string;
@internalProperty() private _opened = false;
@state() private _opened = false;
@internalProperty() private _addingRegistry = false;
@state() private _addingRegistry = false;
protected render(): TemplateResult {
return html`
<ha-dialog
.open=${this._opened}
@closing=${this.closeDialog}
@closed=${this.closeDialog}
scrimClickAction
escapeKeyAction
.heading=${createCloseHeading(
@@ -108,8 +100,8 @@ class HassioRegistriesDialog extends LitElement {
</mwc-button>
`
: html`${this._registries?.length
? this._registries.map((entry) => {
return html`
? this._registries.map(
(entry) => html`
<mwc-list-item class="option" hasMeta twoline>
<span>${entry.registry}</span>
<span slot="secondary"
@@ -129,8 +121,8 @@ class HassioRegistriesDialog extends LitElement {
<ha-svg-icon .path=${mdiDelete}></ha-svg-icon>
</mwc-icon-button>
</mwc-list-item>
`;
})
`
)
: html`
<mwc-list-item>
<span
@@ -220,7 +212,7 @@ class HassioRegistriesDialog extends LitElement {
}
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
haStyleDialog,
@@ -252,9 +244,6 @@ class HassioRegistriesDialog extends LitElement {
mwc-list-item span[slot="secondary"] {
color: var(--secondary-text-color);
}
ha-paper-dropdown-menu {
display: block;
}
`,
];
}
@@ -5,17 +5,8 @@ import "@polymer/paper-input/paper-input";
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-item/paper-item-body";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
query,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/ha-circular-progress";
@@ -37,15 +28,15 @@ class HassioRepositoriesDialog extends LitElement {
@query("#repository_input", true) private _optionInput?: PaperInputElement;
@internalProperty() private _repositories?: HassioAddonRepository[];
@state() private _repositories?: HassioAddonRepository[];
@internalProperty() private _dialogParams?: HassioRepositoryDialogParams;
@state() private _dialogParams?: HassioRepositoryDialogParams;
@internalProperty() private _opened = false;
@state() private _opened = false;
@internalProperty() private _prosessing = false;
@state() private _processing = false;
@internalProperty() private _error?: string;
@state() private _error?: string;
public async showDialog(
dialogParams: HassioRepositoryDialogParams
@@ -76,7 +67,7 @@ class HassioRepositoriesDialog extends LitElement {
return html`
<ha-dialog
.open=${this._opened}
@closing=${this.closeDialog}
@closed=${this.closeDialog}
scrimClickAction
escapeKeyAction
.heading=${createCloseHeading(
@@ -87,8 +78,8 @@ class HassioRepositoriesDialog extends LitElement {
${this._error ? html`<div class="error">${this._error}</div>` : ""}
<div class="form">
${repositories.length
? repositories.map((repo) => {
return html`
? repositories.map(
(repo) => html`
<paper-item class="option">
<paper-item-body three-line>
<div>${repo.name}</div>
@@ -105,13 +96,9 @@ class HassioRepositoriesDialog extends LitElement {
<ha-svg-icon .path=${mdiDelete}></ha-svg-icon>
</mwc-icon-button>
</paper-item>
`;
})
: html`
<paper-item>
No repositories
</paper-item>
`}
`
)
: html` <paper-item> No repositories </paper-item> `}
<div class="layout horizontal bottom">
<paper-input
class="flex-auto"
@@ -123,8 +110,11 @@ class HassioRepositoriesDialog extends LitElement {
@keydown=${this._handleKeyAdd}
></paper-input>
<mwc-button @click=${this._addRepository}>
${this._prosessing
? html`<ha-circular-progress active></ha-circular-progress>`
${this._processing
? html`<ha-circular-progress
active
size="small"
></ha-circular-progress>`
: this._dialogParams!.supervisor.localize(
"dialog.repositories.add"
)}
@@ -138,7 +128,7 @@ class HassioRepositoriesDialog extends LitElement {
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
haStyleDialog,
@@ -160,9 +150,6 @@ class HassioRepositoriesDialog extends LitElement {
mwc-button {
margin-left: 8px;
}
ha-paper-dropdown-menu {
display: block;
}
ha-circular-progress {
display: block;
margin: 32px;
@@ -205,11 +192,9 @@ class HassioRepositoriesDialog extends LitElement {
if (!input || !input.value) {
return;
}
this._prosessing = true;
this._processing = true;
const repositories = this._filteredRepositories(this._repositories!);
const newRepositories = repositories.map((repo) => {
return repo.source;
});
const newRepositories = repositories.map((repo) => repo.source);
newRepositories.push(input.value);
try {
@@ -222,25 +207,19 @@ class HassioRepositoriesDialog extends LitElement {
} catch (err) {
this._error = extractApiErrorMessage(err);
}
this._prosessing = false;
this._processing = false;
}
private async _removeRepository(ev: Event) {
const slug = (ev.currentTarget as any).slug;
const repositories = this._filteredRepositories(this._repositories!);
const repository = repositories.find((repo) => {
return repo.slug === slug;
});
const repository = repositories.find((repo) => repo.slug === slug);
if (!repository) {
return;
}
const newRepositories = repositories
.map((repo) => {
return repo.source;
})
.filter((repo) => {
return repo !== repository.source;
});
.map((repo) => repo.source)
.filter((repo) => repo !== repository.source);
try {
await setSupervisorOption(this.hass, {
@@ -0,0 +1,151 @@
import "@material/mwc-button";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/buttons/ha-progress-button";
import { createCloseHeading } from "../../../../src/components/ha-dialog";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
import {
createHassioFullSnapshot,
createHassioPartialSnapshot,
} from "../../../../src/data/hassio/snapshot";
import { showAlertDialog } from "../../../../src/dialogs/generic/show-dialog-box";
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import "../../components/supervisor-snapshot-content";
import type { SupervisorSnapshotContent } from "../../components/supervisor-snapshot-content";
import { HassioCreateSnapshotDialogParams } from "./show-dialog-hassio-create-snapshot";
@customElement("dialog-hassio-create-snapshot")
class HassioCreateSnapshotDialog extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@state() private _dialogParams?: HassioCreateSnapshotDialogParams;
@state() private _error?: string;
@state() private _creatingSnapshot = false;
@query("supervisor-snapshot-content")
private _snapshotContent!: SupervisorSnapshotContent;
public showDialog(params: HassioCreateSnapshotDialogParams) {
this._dialogParams = params;
this._creatingSnapshot = false;
}
public closeDialog() {
this._dialogParams = undefined;
this._creatingSnapshot = false;
this._error = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
protected render(): TemplateResult {
if (!this._dialogParams) {
return html``;
}
return html`
<ha-dialog
open
scrimClickAction
@closed=${this.closeDialog}
.heading=${createCloseHeading(
this.hass,
this._dialogParams.supervisor.localize("snapshot.create_snapshot")
)}
>
${this._creatingSnapshot
? html` <ha-circular-progress active></ha-circular-progress>`
: html`<supervisor-snapshot-content
.hass=${this.hass}
.supervisor=${this._dialogParams.supervisor}
>
</supervisor-snapshot-content>`}
${this._error ? html`<p class="error">Error: ${this._error}</p>` : ""}
<mwc-button slot="secondaryAction" @click=${this.closeDialog}>
${this._dialogParams.supervisor.localize("common.close")}
</mwc-button>
<mwc-button
.disabled=${this._creatingSnapshot}
slot="primaryAction"
@click=${this._createSnapshot}
>
${this._dialogParams.supervisor.localize("snapshot.create")}
</mwc-button>
</ha-dialog>
`;
}
private async _createSnapshot(): Promise<void> {
if (this._dialogParams!.supervisor.info.state !== "running") {
showAlertDialog(this, {
title: this._dialogParams!.supervisor.localize(
"snapshot.could_not_create"
),
text: this._dialogParams!.supervisor.localize(
"snapshot.create_blocked_not_running",
"state",
this._dialogParams!.supervisor.info.state
),
});
return;
}
const snapshotDetails = this._snapshotContent.snapshotDetails();
this._creatingSnapshot = true;
this._error = "";
if (snapshotDetails.password && !snapshotDetails.password.length) {
this._error = this._dialogParams!.supervisor.localize(
"snapshot.enter_password"
);
this._creatingSnapshot = false;
return;
}
if (
snapshotDetails.password &&
snapshotDetails.password !== snapshotDetails.confirm_password
) {
this._error = this._dialogParams!.supervisor.localize(
"snapshot.passwords_not_matching"
);
this._creatingSnapshot = false;
return;
}
delete snapshotDetails.confirm_password;
try {
if (this._snapshotContent.snapshotType === "full") {
await createHassioFullSnapshot(this.hass, snapshotDetails);
} else {
await createHassioPartialSnapshot(this.hass, snapshotDetails);
}
this._dialogParams!.onCreate();
this.closeDialog();
} catch (err) {
this._error = extractApiErrorMessage(err);
}
this._creatingSnapshot = false;
}
static get styles(): CSSResultGroup {
return [
haStyle,
haStyleDialog,
css`
ha-circular-progress {
display: block;
text-align: center;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"dialog-hassio-create-snapshot": HassioCreateSnapshotDialog;
}
}
@@ -1,14 +1,6 @@
import { mdiClose } from "@mdi/js";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/ha-header-bar";
import { HassDialog } from "../../../../src/dialogs/make-dialog-manager";
@@ -18,11 +10,12 @@ import "../../components/hassio-upload-snapshot";
import { HassioSnapshotUploadDialogParams } from "./show-dialog-snapshot-upload";
@customElement("dialog-hassio-snapshot-upload")
export class DialogHassioSnapshotUpload extends LitElement
export class DialogHassioSnapshotUpload
extends LitElement
implements HassDialog<HassioSnapshotUploadDialogParams> {
@property({ attribute: false }) public hass!: HomeAssistant;
@internalProperty() private _params?: HassioSnapshotUploadDialogParams;
@state() private _params?: HassioSnapshotUploadDialogParams;
public async showDialog(
params: HassioSnapshotUploadDialogParams
@@ -57,9 +50,7 @@ export class DialogHassioSnapshotUpload extends LitElement
>
<div slot="heading">
<ha-header-bar>
<span slot="title">
Upload snapshot
</span>
<span slot="title"> Upload snapshot </span>
<mwc-icon-button slot="actionItems" dialogAction="cancel">
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
</mwc-icon-button>
@@ -79,7 +70,7 @@ export class DialogHassioSnapshotUpload extends LitElement
this.closeDialog();
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyleDialog,
css`
@@ -1,19 +1,12 @@
import "@material/mwc-button";
import { mdiClose, mdiDelete, mdiDownload, mdiHistory } from "@mdi/js";
import "@polymer/paper-checkbox/paper-checkbox";
import type { PaperCheckboxElement } from "@polymer/paper-checkbox/paper-checkbox";
import "@polymer/paper-input/paper-input";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { ActionDetail } from "@material/mwc-list";
import "@material/mwc-list/mwc-list-item";
import { mdiClose, mdiDotsVertical } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { slugify } from "../../../../src/common/string/slugify";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-button-menu";
import "../../../../src/components/ha-header-bar";
import "../../../../src/components/ha-svg-icon";
import { getSignedPath } from "../../../../src/data/auth";
@@ -22,96 +15,47 @@ import {
fetchHassioSnapshotInfo,
HassioSnapshotDetail,
} from "../../../../src/data/hassio/snapshot";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
import {
showAlertDialog,
showConfirmationDialog,
} from "../../../../src/dialogs/generic/show-dialog-box";
import { PolymerChangedEvent } from "../../../../src/polymer-types";
import { HassDialog } from "../../../../src/dialogs/make-dialog-manager";
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { fileDownload } from "../../../../src/util/file_download";
import "../../components/supervisor-snapshot-content";
import type { SupervisorSnapshotContent } from "../../components/supervisor-snapshot-content";
import { HassioSnapshotDialogParams } from "./show-dialog-hassio-snapshot";
const _computeFolders = (folders) => {
const list: Array<{ slug: string; name: string; checked: boolean }> = [];
if (folders.includes("homeassistant")) {
list.push({
slug: "homeassistant",
name: "Home Assistant configuration",
checked: true,
});
}
if (folders.includes("ssl")) {
list.push({ slug: "ssl", name: "SSL", checked: true });
}
if (folders.includes("share")) {
list.push({ slug: "share", name: "Share", checked: true });
}
if (folders.includes("addons/local")) {
list.push({ slug: "addons/local", name: "Local add-ons", checked: true });
}
return list;
};
const _computeAddons = (addons) => {
return addons.map((addon) => ({
slug: addon.slug,
name: addon.name,
version: addon.version,
checked: true,
}));
};
interface AddonItem {
slug: string;
name: string;
version: string;
checked: boolean | null | undefined;
}
interface FolderItem {
slug: string;
name: string;
checked: boolean | null | undefined;
}
@customElement("dialog-hassio-snapshot")
class HassioSnapshotDialog extends LitElement {
class HassioSnapshotDialog
extends LitElement
implements HassDialog<HassioSnapshotDialogParams> {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public supervisor?: Supervisor;
@state() private _error?: string;
@internalProperty() private _error?: string;
@state() private _snapshot?: HassioSnapshotDetail;
@internalProperty() private _onboarding = false;
@state() private _dialogParams?: HassioSnapshotDialogParams;
@internalProperty() private _snapshot?: HassioSnapshotDetail;
@state() private _restoringSnapshot = false;
@internalProperty() private _folders!: FolderItem[];
@internalProperty() private _addons!: AddonItem[];
@internalProperty() private _dialogParams?: HassioSnapshotDialogParams;
@internalProperty() private _snapshotPassword!: string;
@internalProperty() private _restoreHass = true;
@query("supervisor-snapshot-content")
private _snapshotContent!: SupervisorSnapshotContent;
public async showDialog(params: HassioSnapshotDialogParams) {
this._snapshot = await fetchHassioSnapshotInfo(this.hass, params.slug);
this._folders = _computeFolders(
this._snapshot?.folders
).sort((a: FolderItem, b: FolderItem) => (a.name > b.name ? 1 : -1));
this._addons = _computeAddons(
this._snapshot?.addons
).sort((a: AddonItem, b: AddonItem) => (a.name > b.name ? 1 : -1));
this._dialogParams = params;
this._onboarding = params.onboarding ?? false;
this.supervisor = params.supervisor;
if (!this._snapshot.homeassistant) {
this._restoreHass = false;
}
this._restoringSnapshot = false;
}
public closeDialog() {
this._snapshot = undefined;
this._dialogParams = undefined;
this._restoringSnapshot = false;
this._error = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
protected render(): TemplateResult {
@@ -119,204 +63,110 @@ class HassioSnapshotDialog extends LitElement {
return html``;
}
return html`
<ha-dialog open @closing=${this._closeDialog} .heading=${true}>
<ha-dialog
open
scrimClickAction
@closed=${this.closeDialog}
.heading=${true}
>
<div slot="heading">
<ha-header-bar>
<span slot="title">
${this._computeName}
</span>
<span slot="title">${this._snapshot.name}</span>
<mwc-icon-button slot="actionItems" dialogAction="cancel">
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
</mwc-icon-button>
</ha-header-bar>
</div>
<div class="details">
${this._snapshot.type === "full"
? "Full snapshot"
: "Partial snapshot"}
(${this._computeSize})<br />
${this._formatDatetime(this._snapshot.date)}
</div>
${this._snapshot.homeassistant
? html`<div>Home Assistant:</div>
<paper-checkbox
.checked=${this._restoreHass}
@change="${(ev: Event) => {
this._restoreHass = (ev.target as PaperCheckboxElement).checked!;
}}"
>
Home Assistant ${this._snapshot.homeassistant}
</paper-checkbox>`
: ""}
${this._folders.length
? html`
<div>Folders:</div>
<paper-dialog-scrollable class="no-margin-top">
${this._folders.map((item) => {
return html`
<paper-checkbox
.checked=${item.checked}
@change="${(ev: Event) =>
this._updateFolders(
item,
(ev.target as PaperCheckboxElement).checked
)}"
>
${item.name}
</paper-checkbox>
`;
})}
</paper-dialog-scrollable>
`
: ""}
${this._addons.length
? html`
<div>Add-on:</div>
<paper-dialog-scrollable class="no-margin-top">
${this._addons.map((item) => {
return html`
<paper-checkbox
.checked=${item.checked}
@change="${(ev: Event) =>
this._updateAddons(
item,
(ev.target as PaperCheckboxElement).checked
)}"
>
${item.name}
</paper-checkbox>
`;
})}
</paper-dialog-scrollable>
`
: ""}
${this._snapshot.protected
? html`
<paper-input
autofocus=""
label="Password"
type="password"
@value-changed=${this._passwordInput}
.value=${this._snapshotPassword}
></paper-input>
`
: ""}
${this._error ? html` <p class="error">Error: ${this._error}</p> ` : ""}
${this._restoringSnapshot
? html` <ha-circular-progress active></ha-circular-progress>`
: html`<supervisor-snapshot-content
.hass=${this.hass}
.supervisor=${this._dialogParams.supervisor}
.snapshot=${this._snapshot}
.onboarding=${this._dialogParams.onboarding || false}
.localize=${this._dialogParams.localize}
>
</supervisor-snapshot-content>`}
${this._error ? html`<p class="error">Error: ${this._error}</p>` : ""}
<div class="button-row" slot="primaryAction">
<mwc-button @click=${this._partialRestoreClicked}>
<ha-svg-icon .path=${mdiHistory} class="icon"></ha-svg-icon>
Restore Selected
</mwc-button>
${!this._onboarding
? html`
<mwc-button @click=${this._deleteClicked}>
<ha-svg-icon .path=${mdiDelete} class="icon warning">
</ha-svg-icon>
<span class="warning">Delete Snapshot</span>
</mwc-button>
`
: ""}
</div>
<div class="button-row" slot="secondaryAction">
${this._snapshot.type === "full"
? html`
<mwc-button @click=${this._fullRestoreClicked}>
<ha-svg-icon .path=${mdiHistory} class="icon"></ha-svg-icon>
Restore Everything
</mwc-button>
`
: ""}
${!this._onboarding
? html`<mwc-button @click=${this._downloadClicked}>
<ha-svg-icon .path=${mdiDownload} class="icon"></ha-svg-icon>
Download Snapshot
</mwc-button>`
: ""}
</div>
<mwc-button
.disabled=${this._restoringSnapshot}
slot="secondaryAction"
@click=${this._restoreClicked}
>
Restore
</mwc-button>
${!this._dialogParams.onboarding
? html`<ha-button-menu
fixed
slot="primaryAction"
@action=${this._handleMenuAction}
@closed=${(ev: Event) => ev.stopPropagation()}
>
<mwc-icon-button slot="trigger" alt="menu">
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
</mwc-icon-button>
<mwc-list-item>Download Snapshot</mwc-list-item>
<mwc-list-item class="error">Delete Snapshot</mwc-list-item>
</ha-button-menu>`
: ""}
</ha-dialog>
`;
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
haStyleDialog,
css`
paper-checkbox {
ha-svg-icon {
color: var(--primary-text-color);
}
ha-circular-progress {
display: block;
margin: 4px;
}
mwc-button ha-svg-icon {
margin-right: 4px;
}
.button-row {
display: grid;
gap: 8px;
margin-right: 8px;
}
.details {
color: var(--secondary-text-color);
}
.warning,
.error {
color: var(--error-color);
}
.buttons li {
list-style-type: none;
}
.buttons .icon {
margin-right: 16px;
}
.no-margin-top {
margin-top: 0;
text-align: center;
}
ha-header-bar {
--mdc-theme-on-primary: var(--primary-text-color);
--mdc-theme-primary: var(--mdc-theme-surface);
flex-shrink: 0;
}
/* overrule the ha-style-dialog max-height on small screens */
@media all and (max-width: 450px), all and (max-height: 500px) {
ha-header-bar {
--mdc-theme-primary: var(--app-header-background-color);
--mdc-theme-on-primary: var(--app-header-text-color, white);
}
display: block;
}
`,
];
}
private _updateFolders(item: FolderItem, value: boolean | null | undefined) {
this._folders = this._folders.map((folder) => {
if (folder.slug === item.slug) {
folder.checked = value;
}
return folder;
});
private _handleMenuAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
this._downloadClicked();
break;
case 1:
this._deleteClicked();
break;
}
}
private _updateAddons(item: AddonItem, value: boolean | null | undefined) {
this._addons = this._addons.map((addon) => {
if (addon.slug === item.slug) {
addon.checked = value;
}
return addon;
});
private async _restoreClicked() {
const snapshotDetails = this._snapshotContent.snapshotDetails();
this._restoringSnapshot = true;
if (this._snapshotContent.snapshotType === "full") {
await this._fullRestoreClicked(snapshotDetails);
} else {
await this._partialRestoreClicked(snapshotDetails);
}
this._restoringSnapshot = false;
}
private _passwordInput(ev: PolymerChangedEvent<string>) {
this._snapshotPassword = ev.detail.value;
}
private async _partialRestoreClicked() {
private async _partialRestoreClicked(snapshotDetails) {
if (
this.supervisor !== undefined &&
this.supervisor.info.state !== "running"
this._dialogParams?.supervisor !== undefined &&
this._dialogParams?.supervisor.info.state !== "running"
) {
await showAlertDialog(this, {
title: "Could not restore snapshot",
text: `Restoring a snapshot is not possible right now because the system is in ${this.supervisor.info.state} state.`,
text: `Restoring a snapshot is not possible right now because the system is in ${this._dialogParams?.supervisor.info.state} state.`,
});
return;
}
@@ -330,41 +180,17 @@ class HassioSnapshotDialog extends LitElement {
return;
}
const addons = this._addons
.filter((addon) => addon.checked)
.map((addon) => addon.slug);
const folders = this._folders
.filter((folder) => folder.checked)
.map((folder) => folder.slug);
const data: {
homeassistant: boolean;
addons: any;
folders: any;
password?: string;
} = {
homeassistant: this._restoreHass,
addons,
folders,
};
if (this._snapshot!.protected) {
data.password = this._snapshotPassword;
}
if (!this._onboarding) {
if (!this._dialogParams?.onboarding) {
this.hass
.callApi(
"POST",
`hassio/snapshots/${this._snapshot!.slug}/restore/partial`,
data
snapshotDetails
)
.then(
() => {
alert("Snapshot restored!");
this._closeDialog();
this.closeDialog();
},
(error) => {
this._error = error.body.message;
@@ -374,20 +200,20 @@ class HassioSnapshotDialog extends LitElement {
fireEvent(this, "restoring");
fetch(`/api/hassio/snapshots/${this._snapshot!.slug}/restore/partial`, {
method: "POST",
body: JSON.stringify(data),
body: JSON.stringify(snapshotDetails),
});
this._closeDialog();
this.closeDialog();
}
}
private async _fullRestoreClicked() {
private async _fullRestoreClicked(snapshotDetails) {
if (
this.supervisor !== undefined &&
this.supervisor.info.state !== "running"
this._dialogParams?.supervisor !== undefined &&
this._dialogParams?.supervisor.info.state !== "running"
) {
await showAlertDialog(this, {
title: "Could not restore snapshot",
text: `Restoring a snapshot is not possible right now because the system is in ${this.supervisor.info.state} state.`,
text: `Restoring a snapshot is not possible right now because the system is in ${this._dialogParams?.supervisor.info.state} state.`,
});
return;
}
@@ -402,20 +228,16 @@ class HassioSnapshotDialog extends LitElement {
return;
}
const data = this._snapshot!.protected
? { password: this._snapshotPassword }
: undefined;
if (!this._onboarding) {
if (!this._dialogParams?.onboarding) {
this.hass
.callApi(
"POST",
`hassio/snapshots/${this._snapshot!.slug}/restore/full`,
data
snapshotDetails
)
.then(
() => {
alert("Snapshot restored!");
this._closeDialog();
this.closeDialog();
},
(error) => {
this._error = error.body.message;
@@ -425,9 +247,9 @@ class HassioSnapshotDialog extends LitElement {
fireEvent(this, "restoring");
fetch(`/api/hassio/snapshots/${this._snapshot!.slug}/restore/full`, {
method: "POST",
body: JSON.stringify(data),
body: JSON.stringify(snapshotDetails),
});
this._closeDialog();
this.closeDialog();
}
}
@@ -450,7 +272,7 @@ class HassioSnapshotDialog extends LitElement {
if (this._dialogParams!.onDelete) {
this._dialogParams!.onDelete();
}
this._closeDialog();
this.closeDialog();
},
(error) => {
this._error = error.body.message;
@@ -466,7 +288,9 @@ class HassioSnapshotDialog extends LitElement {
`/api/hassio/snapshots/${this._snapshot!.slug}/download`
);
} catch (err) {
alert(`Error: ${extractApiErrorMessage(err)}`);
await showAlertDialog(this, {
text: extractApiErrorMessage(err),
});
return;
}
@@ -483,13 +307,11 @@ class HassioSnapshotDialog extends LitElement {
}
}
const name = this._computeName.replace(/[^a-z0-9]+/gi, "_");
const a = document.createElement("a");
a.href = signedPath.path;
a.download = `Hass_io_${name}.tar`;
this.shadowRoot!.appendChild(a);
a.click();
this.shadowRoot!.removeChild(a);
fileDownload(
this,
signedPath.path,
`home_assistant_snapshot_${slugify(this._computeName)}.tar`
);
}
private get _computeName() {
@@ -497,29 +319,6 @@ class HassioSnapshotDialog extends LitElement {
? this._snapshot.name || this._snapshot.slug
: "Unnamed snapshot";
}
private get _computeSize() {
return Math.ceil(this._snapshot!.size * 10) / 10 + " MB";
}
private _formatDatetime(datetime) {
return new Date(datetime).toLocaleDateString(navigator.language, {
weekday: "long",
year: "numeric",
month: "short",
day: "numeric",
hour: "numeric",
minute: "2-digit",
});
}
private _closeDialog() {
this._dialogParams = undefined;
this._snapshot = undefined;
this._snapshotPassword = "";
this._folders = [];
this._addons = [];
}
}
declare global {
@@ -0,0 +1,18 @@
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
export interface HassioCreateSnapshotDialogParams {
supervisor: Supervisor;
onCreate: () => void;
}
export const showHassioCreateSnapshotDialog = (
element: HTMLElement,
dialogParams: HassioCreateSnapshotDialogParams
): void => {
fireEvent(element, "show-dialog", {
dialogTag: "dialog-hassio-create-snapshot",
dialogImport: () => import("./dialog-hassio-create-snapshot"),
dialogParams,
});
};
@@ -1,4 +1,5 @@
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { LocalizeFunc } from "../../../../src/common/translations/localize";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
export interface HassioSnapshotDialogParams {
@@ -6,6 +7,7 @@ export interface HassioSnapshotDialogParams {
onDelete?: () => void;
onboarding?: boolean;
supervisor?: Supervisor;
localize?: LocalizeFunc;
}
export const showHassioSnapshotDialog = (
+1 -1
View File
@@ -1,4 +1,4 @@
import type { LitElement } from "lit-element";
import type { LitElement } from "lit";
import {
HassioAddonDetails,
restartHassioAddon,
@@ -1,23 +1,13 @@
import "@material/mwc-button/mwc-button";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
TemplateResult,
} from "lit-element";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/ha-circular-progress";
import "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-settings-row";
import "../../../../src/components/ha-svg-icon";
import "../../../../src/components/ha-switch";
import {
extractApiErrorMessage,
ignoreSupervisorError,
} from "../../../../src/data/hassio/common";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
import { createHassioPartialSnapshot } from "../../../../src/data/hassio/snapshot";
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import type { HomeAssistant } from "../../../../src/types";
@@ -27,15 +17,15 @@ import { SupervisorDialogSupervisorUpdateParams } from "./show-dialog-update";
class DialogSupervisorUpdate extends LitElement {
public hass!: HomeAssistant;
@internalProperty() private _opened = false;
@state() private _opened = false;
@internalProperty() private _createSnapshot = true;
@state() private _createSnapshot = true;
@internalProperty() private _action: "snapshot" | "update" | null = null;
@state() private _action: "snapshot" | "update" | null = null;
@internalProperty() private _error?: string;
@state() private _error?: string;
@internalProperty()
@state()
private _dialogParams?: SupervisorDialogSupervisorUpdateParams;
public async showDialog(
@@ -160,20 +150,11 @@ class DialogSupervisorUpdate extends LitElement {
}
this._action = "update";
try {
await this._dialogParams!.updateHandler!();
} catch (err) {
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
this._error = extractApiErrorMessage(err);
}
this._action = null;
return;
}
await this._dialogParams!.updateHandler!();
this.closeDialog();
}
static get styles(): CSSResult[] {
static get styles(): CSSResultGroup {
return [
haStyle,
haStyleDialog,
@@ -1,17 +1,18 @@
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { HassioPartialSnapshotCreateParams } from "../../../../src/data/hassio/snapshot";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
export interface SupervisorDialogSupervisorUpdateParams {
supervisor: Supervisor;
name: string;
version: string;
snapshotParams: any;
snapshotParams: HassioPartialSnapshotCreateParams;
updateHandler: () => Promise<void>;
}
export const showDialogSupervisorUpdate = (
element: HTMLElement,
dialogParams: SupervisorDialogSupervisorUpdateParams
dialogParams: Partial<SupervisorDialogSupervisorUpdateParams>
): void => {
fireEvent(element, "show-dialog", {
dialogTag: "dialog-supervisor-update",
+6
View File
@@ -15,5 +15,11 @@ body {
padding: 0;
height: 100vh;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #111111;
color: #e1e1e1;
}
}
`;
document.head.appendChild(styleEl);
+23 -7
View File
@@ -1,7 +1,11 @@
import { customElement, html, property, PropertyValues } from "lit-element";
import { html, PropertyValues } from "lit";
import { customElement, property } from "lit/decorators";
import { atLeastVersion } from "../../src/common/config/version";
import { applyThemesOnElement } from "../../src/common/dom/apply_themes_on_element";
import { fireEvent } from "../../src/common/dom/fire_event";
import { isNavigationClick } from "../../src/common/dom/is-navigation-click";
import { mainWindow } from "../../src/common/dom/get_main_window";
import { navigate } from "../../src/common/navigate";
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
import { Supervisor } from "../../src/data/supervisor/supervisor";
import { makeDialogManager } from "../../src/dialogs/make-dialog-manager";
@@ -44,13 +48,25 @@ export class HassioMain extends SupervisorBaseElement {
// We changed the navigate event to fire directly on the window, as that's
// where we are listening for it. However, the older panel_custom will
// listen on this element for navigation events, so we need to forward them.
window.addEventListener("location-changed", (ev) =>
// Joakim - April 26, 2021
// Due to changes in behavior in Google Chrome, we changed navigate to listen on the top element
mainWindow.addEventListener("location-changed", (ev) =>
// @ts-ignore
fireEvent(this, ev.type, ev.detail, {
bubbles: false,
})
);
// Paulus - May 17, 2021
// Convert the <a> tags to native nav in Home Assistant < 2021.6
document.body.addEventListener("click", (ev) => {
const href = isNavigationClick(ev);
if (href) {
navigate(href);
}
});
// Forward haptic events to parent window.
window.addEventListener("haptic", (ev) => {
// @ts-ignore
@@ -87,7 +103,7 @@ export class HassioMain extends SupervisorBaseElement {
private _applyTheme() {
let themeName: string;
let options: Partial<HomeAssistant["selectedTheme"]> | undefined;
let themeSettings: Partial<HomeAssistant["selectedTheme"]> | undefined;
if (atLeastVersion(this.hass.config.version, 0, 114)) {
themeName =
@@ -96,9 +112,9 @@ export class HassioMain extends SupervisorBaseElement {
? this.hass.themes.default_dark_theme!
: this.hass.themes.default_theme);
options = this.hass.selectedTheme;
if (themeName === "default" && options?.dark === undefined) {
options = {
themeSettings = this.hass.selectedTheme;
if (themeSettings?.dark === undefined) {
themeSettings = {
...this.hass.selectedTheme,
dark: this.hass.themes.darkMode,
};
@@ -113,7 +129,7 @@ export class HassioMain extends SupervisorBaseElement {
this.parentElement,
this.hass.themes,
themeName,
options
themeSettings
);
}
}
+10 -10
View File
@@ -1,11 +1,4 @@
import {
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { html, LitElement, TemplateResult } from "lit";
import { sanitizeUrl } from "@braintree/sanitize-url";
import {
createSearchParam,
@@ -20,6 +13,7 @@ import {
import { navigate } from "../../src/common/navigate";
import { HomeAssistant, Route } from "../../src/types";
import { Supervisor } from "../../src/data/supervisor/supervisor";
import { customElement, property, state } from "lit/decorators";
const REDIRECTS: Redirects = {
supervisor: {
@@ -43,6 +37,12 @@ const REDIRECTS: Redirects = {
addon: "string",
},
},
supervisor_ingress: {
redirect: "/hassio/ingress",
params: {
addon: "string",
},
},
supervisor_add_addon_repository: {
redirect: "/hassio/store",
params: {
@@ -59,7 +59,7 @@ class HassioMyRedirect extends LitElement {
@property({ attribute: false }) public route!: Route;
@internalProperty() public _error?: TemplateResult | string;
@state() public _error?: TemplateResult | string;
connectedCallback() {
super.connectedCallback();
@@ -89,7 +89,7 @@ class HassioMyRedirect extends LitElement {
return;
}
navigate(this, url, true);
navigate(url, { replace: true });
}
protected render(): TemplateResult {
+1 -1
View File
@@ -1,4 +1,4 @@
import { customElement, property } from "lit-element";
import { customElement, property } from "lit/decorators";
import { Supervisor } from "../../src/data/supervisor/supervisor";
import {
HassRouterPage,

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