Compare commits

...

160 Commits

Author SHA1 Message Date
Paulus Schoutsen
3717e94814 Switch onboarding and auth to dynamic import 2020-10-12 14:10:15 +00:00
Tobias Kündig
993d73c359 Added entity_id to history graph tooltip (#7310)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-10-12 14:12:54 +02:00
Philip Allgaier
97ca0b818e Capitalize first character of attributes (#7313) 2020-10-12 11:43:46 +02:00
Thomas Lovén
44166f76d4 Scriptomation yaml editor (#7273) 2020-10-12 11:26:16 +02:00
Nico Hirsch
557d6d37a1 Fix charts tooltip (#7216) 2020-10-12 11:12:20 +02:00
Paulus Schoutsen
d3ad56a307 Update compatibility and fix polyfills for ES5 (#7298) 2020-10-12 10:48:33 +02:00
Mischa Gruber
0641022ec5 Use translations for alexa (#7301) 2020-10-12 10:28:11 +02:00
Zack Barett
80c7a8473a Fix Entity Toggle not working for Type Row (#7289) 2020-10-12 10:26:23 +02:00
Matt
d9a954ca91 Close notification drawer after dismissing last notification (#7229)
* Close notification drawer after dismissing last

This change adds a listener to any changes of the notifications property once the drawer opens. After the last notification is dismissed, the notification drawer closes automatically, and the listener is removed.

* Use observer instead event for notification change

Using the observer pattern instead subscribing to change events for notification changes simplifies the implementation noticeably.
2020-10-12 10:25:04 +02:00
Donnie
c219f64322 Rename 'quick open dialog' to 'quick bar' (#7286) 2020-10-12 10:18:18 +02:00
HomeAssistant Azure
f7a9ecff21 [ci skip] Translation update 2020-10-12 00:32:48 +00:00
Jonas Bröms
2b3126ae04 hassio-addon-info.ts: Fix spelling (#7311) 2020-10-11 15:21:02 -05:00
Kyle Niewiada
934c227545 Sort profile refresh tokens by 'last used at' date (#4484) (#7199) 2020-10-11 01:17:05 -05:00
Villhellm
cc0515c217 Add help link on automations picker and updated links for scripts and scenes (#7129)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2020-10-11 01:14:22 -05:00
HomeAssistant Azure
55ba75f2bc [ci skip] Translation update 2020-10-11 00:32:41 +00:00
alex6480
c220228566 Add link to documentation for persons (#7205)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2020-10-10 16:19:59 -05:00
Daniel Martin Gonzalez
26b476ab3c Weather card: Add wind speed direction (#7202)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2020-10-10 16:19:40 -05:00
Paulus Schoutsen
b8a67d530f Update translations 2020-10-10 16:41:36 +02:00
HomeAssistant Azure
b08c96d2db [ci skip] Translation update 2020-10-10 00:32:54 +00:00
Philip Allgaier
4773c39a57 Ensure ha-dialog uses correct <a> color (#7255) 2020-10-09 11:29:47 +02:00
Ryan Meek
892843b290 Supervisor disk usage more info (#7247)
Co-authored-by: Joakim Sørensen <ludeeus@gmail.com>
2020-10-09 10:15:55 +02:00
HomeAssistant Azure
733244531e [ci skip] Translation update 2020-10-09 00:32:37 +00:00
Bram Kragten
66633273e2 Fix history chart fetching changes (#7235) 2020-10-08 16:41:25 +02:00
Spencer Williams
0405adcd16 Edit Person button in the Person "more info" dialog (fixes #4706) (#7208)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2020-10-08 16:40:55 +02:00
Ian Richardson
426a7ac8dd Show moon phase icon in state-label-badge (#7194)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-10-08 16:37:51 +02:00
Thomas Lovén
3bf6205ff7 Display qr code in tag properties (#7092) 2020-10-08 16:37:17 +02:00
Thomas Lovén
c7f4986e61 Put automation/script editor actions in a menu (#7250)
* Put automation/script editor actions in a menu

* Use disabled property instead of attribute
2020-10-08 16:37:01 +02:00
Gilson Marquato Júnior
0f0a3fdaf7 Add keyboard shortcut to save automation/scene/script (#7207) 2020-10-08 16:24:08 +02:00
Bram Kragten
7d6911b140 Replace mdc circular progress with mwc (#7248) 2020-10-08 16:17:20 +02:00
Jaroslav Hanslík
b8777539d7 Fixed localization of relative time (#7256) 2020-10-08 15:53:59 +02:00
Joakim Sørensen
5fc0eaef1a Warn about slow snapshot downloads (#7265) 2020-10-08 15:06:42 +02:00
Paulus Schoutsen
113718c3c1 Do not show weather forecast in generated UI (#7251) 2020-10-08 13:29:13 +02:00
Ryan Meek
701bea6cae Fix tab focus issue in entity picker and password form. (#7252) 2020-10-08 13:24:58 +02:00
Donnie
8d516ed12a Add "quick open" style dialog for selecting entities and running reload commands (#7230)
Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-10-08 13:20:57 +02:00
Joakim Sørensen
667c5744f2 Fix ha-bar display issue on firefox (#7263) 2020-10-08 12:29:21 +02:00
Bram Kragten
80b7c840e2 Fix cloud webhooks (#7261) 2020-10-08 10:33:06 +02:00
HomeAssistant Azure
919c86796f [ci skip] Translation update 2020-10-08 00:32:28 +00:00
Bram Kragten
c90c88ecbf Bump typescript (4) and babel (#7249) 2020-10-07 17:58:56 +02:00
Paulus Schoutsen
d9ba0e2c46 Upgrade to Webpack 5 (#6200) 2020-10-07 10:54:42 +02:00
HomeAssistant Azure
45b2fc590b [ci skip] Translation update 2020-10-07 00:32:14 +00:00
Daniel
17ffdb0247 Update script editor panel tooltips (#7204) 2020-10-06 20:44:20 +02:00
J. Nick Koston
c2fba15fc6 Avoid fetching logbook when there will never be entries (#7239) 2020-10-06 11:22:38 -05:00
Bram Kragten
5937be695f Bump Lit, use cache for query (#7245) 2020-10-06 15:55:55 +02:00
Tomasz
a076fcde84 replace ha-icon_button and ha-icon in stack card editor (#7233) 2020-10-06 12:50:06 +02:00
Bram Kragten
ede9931903 Only do 1 token update a time (#7236) 2020-10-06 10:55:12 +02:00
Paul Klingelhuber
722e01608c Fix flickering scrollbar when using progress-spinner (#7237) 2020-10-06 09:47:25 +02:00
HomeAssistant Azure
af926370d6 [ci skip] Translation update 2020-10-06 00:32:53 +00:00
Tomasz
5971aee02e dot notation for path property of ha-svg-icon (#7197) 2020-10-05 19:51:14 +02:00
Bram Kragten
3940606167 Fix Apple not showing cards (#7232) 2020-10-05 15:54:32 +02:00
David Beitey
da9faccada Allow viewport scaling (zooming) of frontend (#7180)
The inclusion of the `user-scalable=no` value in the viewport meta tag
prevented viewport scaling, disabling the ability to zoom the webpage.
This most typically affects mobile devices, given the nature of the
`<meta name="viewport">` tag.

Removing the restriction allows a user to zoom in to see small and fine
detail in the UI -- such as zooming in on particular areas of a home
security camera streams or other images, inspecting detail in state and
other graphs, and so on.

For users with accessibility requirements, such as low vision
conditions, being able to zoom the frontend means they can enlarge UI
elements to suit them (MDN explains several accessibility concerns at
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name#Accessibility_concerns_with_viewport_scaling)

This change has no effect on users that choose not to use it (for
example, only those that engage zooming such as via pinch-to-zoom on
mobile devices will see the change) -- the frontend remains the same
otherwise.  Elements of the frontend that do use pinch-to-zoom (e.g. the
Map) continue to work as expected, with pinches on that screen area
being captured by the map.
2020-10-05 13:29:07 +02:00
Ryan Meek
7e708b3bf7 Use consistent title case for headers in Supervisor (#7227) 2020-10-05 12:05:57 +02:00
Ryan Meek
05630c9896 Use client_id if no client_name in delete dialog (#7228) 2020-10-05 10:24:23 +02:00
HomeAssistant Azure
369c56db73 [ci skip] Translation update 2020-10-05 00:32:49 +00:00
Ryan Meek
9873459169 Styling fixes for hui-masonry-view (#7226) 2020-10-04 15:15:14 -05:00
HomeAssistant Azure
7776b3766b [ci skip] Translation update 2020-10-04 00:32:25 +00:00
HomeAssistant Azure
29c9004654 [ci skip] Translation update 2020-10-03 00:32:26 +00:00
Zack Barett
601c909004 Warning Element: Fix Overflow in Entity Row (#7193) 2020-10-02 11:29:29 -05:00
Tomasz
72aa9a3b62 use ha-svg-icon in more-info-weather (#7196) 2020-10-02 15:12:54 +02:00
Bram Kragten
2ecf7bca97 Set hass when creating card (#7187) 2020-10-02 15:09:27 +02:00
Zack Barett
cbdfaccdb2 Logbook: Fix for no state obj (#7191) 2020-10-02 14:57:42 +02:00
Zack Barett
93d1b9a2d5 Fix entities Card toggle (#7192) 2020-10-02 10:12:55 +02:00
HomeAssistant Azure
bfb5ee794e [ci skip] Translation update 2020-10-02 00:32:24 +00:00
J. Nick Koston
9ae8bd238b Fix reversal in power icon (#7188) 2020-10-01 11:24:13 -05:00
Bram Kragten
0171f3aec7 Bumped version to 20201001.0 2020-10-01 15:42:07 +02:00
Zack Barett
2c827bab9a Logbook: fix custom Icon (#7175) 2020-10-01 13:55:27 +02:00
Bram Kragten
ec920093d4 Fix panel view and backgrounds (#7181) 2020-10-01 13:54:54 +02:00
HomeAssistant Azure
4289ff6652 [ci skip] Translation update 2020-10-01 00:32:20 +00:00
Charles Garwood
cd32ef60da Show error if no OZW instances are detected (#7176) 2020-09-30 23:09:48 +02:00
Bram Kragten
0f59496778 Revert "Bumped version to 20200930.1"
This reverts commit 795b670b3c.
2020-09-30 17:14:44 +02:00
Bram Kragten
795b670b3c Bumped version to 20200930.1 2020-09-30 17:12:07 +02:00
Zack Barett
4ad65e3d69 Set correct type for setConfig (#7173) 2020-09-30 17:08:10 +02:00
Bram Kragten
f48b1150cf Set logbook border to divider color (#7172) 2020-09-30 17:06:52 +02:00
Zack Barett
198db8bc68 Update lovelace.ts 2020-09-30 09:59:09 -05:00
Bram Kragten
3ae447ca44 Fix updating columns (#7171)
Co-authored-by: Zack Barett <arnett.zackary@gmail.com>
2020-09-30 16:57:31 +02:00
Zack Barett
a2ec878ef0 Entities Card: Entity Row Editor (#7134)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-09-30 16:20:10 +02:00
Bram Kragten
d43b5d3337 Integrate user management in person (#7170) 2020-09-30 15:22:40 +02:00
uvjustin
11e3503dc2 Change exoplayer payload type (#7010)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-09-30 14:00:19 +02:00
Joakim Sørensen
accf44b769 Remove scooter from icon deprecation (#7169) 2020-09-30 11:48:41 +02:00
Zack Barett
771c7518e6 Custom Lovelace View Layouts (#6557)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-09-30 11:06:03 +02:00
Bram Kragten
4f2bad034a Fix safari issues and move scrollable to own container (#7029) 2020-09-30 11:05:45 +02:00
Bram Kragten
0456669aeb Bumped version to 20200930.0 2020-09-30 11:03:49 +02:00
Bram Kragten
2eb71321e7 Merge branch 'master' into dev 2020-09-30 10:59:57 +02:00
Bram Kragten
d2e9e22e4e Add media player to cast app (#7160)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2020-09-30 10:24:38 +02:00
Zack Barett
e2427c8dce Logbook: Localize Message & Style updates (#6978)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-09-30 10:24:04 +02:00
Marc Randolph
26162815c8 Expand error msg on why yaml defined entities can't be changed from UI (#6689) 2020-09-30 10:21:24 +02:00
Alexei Chetroi
d0c86ea2f7 Use ieee for zha.remove service data (#7163) 2020-09-30 10:20:01 +02:00
Zack Barett
4f5b4d4472 Calendar Card: Fix Calendar not updating events on config change (#7165) 2020-09-30 09:54:24 +02:00
HomeAssistant Azure
10d71587e7 [ci skip] Translation update 2020-09-30 00:32:25 +00:00
Zack Barett
9ac777d687 Add default to action editor (#7006)
* Add default to action editor

* only select default when action undefined

* Update action to actuall default when selecting default

* import type

* Tooltip and lokalize

* comments

* wording

* Comments

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-09-29 22:45:13 +02:00
Bram Kragten
7d1f9f3981 Add LocalizeMixin to state-info 2020-09-29 22:15:44 +02:00
Pawel
a214ab463e Add last_updated tooltip to more info dialog (#6926) 2020-09-29 22:10:29 +02:00
Joakim Sørensen
2f21f6ef8a Add unit_of_measurement to input-number-entity-row (#6965) 2020-09-29 21:55:20 +02:00
Joakim Sørensen
590cd8500d Restore snapshot from onboarding (#7132)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-09-29 20:30:25 +02:00
Bashir
f48a28264f More-Info Dialog Logbook Bug Fix (#7152) 2020-09-29 17:04:01 +02:00
Sam Pierce Lolla
51953bce09 Change "persons" to "people" (#7037)
People is the more common word in English
2020-09-29 17:00:41 +02:00
Paulus Schoutsen
c445d4b839 Update supported browsers for Cast 2020-09-29 11:31:03 +02:00
HomeAssistant Azure
9dabce1dd7 [ci skip] Translation update 2020-09-29 00:32:52 +00:00
Martin Hjelmare
6b77f08d86 Hide rpi_power entry during onboarding (#7001)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-09-28 23:23:52 +02:00
J. Nick Koston
50e03d41ab Add timeout to dev template renders (#7141) 2020-09-28 08:45:38 -05:00
Bram Kragten
4759c89628 Bring back lazy load more info + helper (#7131) 2020-09-28 13:29:02 +02:00
Kendell R
458ab9b1e0 Add --ha-card-border-width (#7021) 2020-09-28 13:08:57 +02:00
Tomasz
dfb2a7153b Add weekday to time contidion editor (#6848) 2020-09-28 12:28:43 +02:00
Zack Barett
e9141d82f3 Calendar Card: Initial View Editor (#7135) 2020-09-28 11:59:39 +02:00
HomeAssistant Azure
d9f42712e4 [ci skip] Translation update 2020-09-28 00:32:37 +00:00
HomeAssistant Azure
da0658f3d9 [ci skip] Translation update 2020-09-27 00:32:45 +00:00
HomeAssistant Azure
412a5a6d8e [ci skip] Translation update 2020-09-26 00:32:36 +00:00
Zack Barett
9cf9e6edd8 Allow initial View in Calendar Card (#6982) 2020-09-25 09:58:25 +02:00
Joakim Sørensen
28050fc9fb Add upload snapshot dialog (#7115)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-09-25 09:55:02 +02:00
HomeAssistant Azure
ea9f227fa8 [ci skip] Translation update 2020-09-25 00:32:27 +00:00
Bram Kragten
05164e90fb Revert lazy loading more info controls (#7123) 2020-09-24 20:36:05 +02:00
Bram Kragten
97156ccf8a Bumped version to 20200918.2 2020-09-24 20:35:25 +02:00
Simone Chemelli
003d55968e Added icon for power on/off (#7124) 2020-09-24 19:37:50 +02:00
Bram Kragten
98dd21b75c Revert lazy loading more info controls (#7123) 2020-09-24 19:31:38 +02:00
Zack Barett
a349e34bc2 Card Editor: Special Row doesn't show warning (#7093) 2020-09-24 11:36:43 -05:00
Shulyaka
245c825cbf Add humidifier entity row (#6213)
Co-authored-by: Zack Barett <zackbarett@hey.com>
2020-09-24 16:45:33 +02:00
rajlaud
4ba6698c4b Support twice daily forecasts in weather-forecast-card (#6065)
Co-authored-by: Zack Arnett <arnett.zackary@gmail.com>
2020-09-24 15:18:38 +02:00
Shulyaka
dac6edea90 Humidifier icon for off state (#7113) 2020-09-24 14:18:30 +02:00
Thomas Lovén
b2e2dbe0c2 Merge ha-paper-slider into ha-slider (#7114) 2020-09-24 14:16:28 +02:00
Simone Chemelli
f822fa0d57 Added icon for timestamp device class (#7117) 2020-09-24 14:03:42 +02:00
Joakim Sørensen
bbee94edba Prevent deletion of the owner user (#7116) 2020-09-24 13:45:07 +02:00
Joakim Sørensen
c39c408332 cloud-webhooks cleanup (#7118) 2020-09-24 13:28:44 +02:00
HomeAssistant Azure
dde4a40e69 [ci skip] Translation update 2020-09-24 00:32:23 +00:00
Bram Kragten
1afa4d2868 Bumped version to 20200918.1 2020-09-23 12:10:59 +02:00
Zack Arnett
d25f371d6c make the browser load 2020-09-23 12:09:25 +02:00
Brenden Crowie
948261d1d1 Corrected password changed message in User panel (#7111) 2020-09-23 12:05:55 +02:00
Zack Barett
04b7749f85 Fix Calendar Title from not removing (#7058) 2020-09-23 12:04:55 +02:00
Zack Barett
8668f0ff5b Progress circle when loading data (#7059) 2020-09-23 11:55:24 +02:00
Brenden Crowie
b7d8ff6c99 Corrected password changed message in User panel (#7111) 2020-09-23 09:52:32 +02:00
HomeAssistant Azure
0894a30f13 [ci skip] Translation update 2020-09-23 00:32:42 +00:00
Joakim Sørensen
bd511887a7 Adds hassio-system-metrics (#7105) 2020-09-22 21:58:31 +02:00
Zack Barett
0304c0eca0 Fix sensor card from not working with detail (#7060)
* Fix sensor card from not working with detail

* comments
2020-09-22 12:06:42 -05:00
Joakim Sørensen
6d5c6e2fbc Show message when there are no add-ons (#7101) 2020-09-22 13:15:06 +02:00
Bram Kragten
e7e7912519 Fix wait for trigger (#7089) 2020-09-22 10:58:43 +02:00
Andrew Rabert
b9c41d8f99 Optimize images (#7091) 2020-09-22 10:49:43 +02:00
Thomas Lovén
25a2264ac3 Use absolute URL for background image in media-control card (#7100) 2020-09-22 10:45:27 +02:00
HomeAssistant Azure
ad64657c74 [ci skip] Translation update 2020-09-22 00:32:23 +00:00
Michael Irigoyen
106f18a73a Update Material Design Icons to v5.6.55 (#7081) 2020-09-21 17:49:25 +02:00
Zack Barett
0fb38140a6 fix media icon diff (#7071) 2020-09-21 17:44:56 +02:00
b3nj1
60133941ae Fix for NOT IN / IN Operators (#7061) 2020-09-21 14:05:28 +02:00
Zack Barett
76db64c073 Fix Calendar Title from not removing (#7058) 2020-09-21 13:27:50 +02:00
Zack Barett
24b390ba03 Add actions to entities config struct (#7063) 2020-09-21 13:26:08 +02:00
Zack Barett
b4d34d9085 Add Hours to show to the cache key (#7072) 2020-09-21 13:15:07 +02:00
Thomas Lovén
f80bea27a9 Fix outline on mouseover in firefox (#7052) 2020-09-21 13:10:33 +02:00
Kendell R
4b846964be Adopt --code-font-family (#6997) 2020-09-21 09:56:42 +02:00
HomeAssistant Azure
e6357e2eef [ci skip] Translation update 2020-09-21 00:32:34 +00:00
Zack Barett
d538b6145f Media Player Browser: Fix child names add tooltip (#7020) 2020-09-20 11:34:56 +02:00
HomeAssistant Azure
229ba3a75c [ci skip] Translation update 2020-09-20 00:32:36 +00:00
HomeAssistant Azure
672b867847 [ci skip] Translation update 2020-09-19 00:32:53 +00:00
Zack Arnett
ca1dacd621 Update to actually set loading 2020-09-18 14:51:02 -05:00
Bram Kragten
26abb4301d Merge pull request #7055 from home-assistant/dev 2020-09-18 17:48:37 +02:00
Bram Kragten
045dac59af Bumped version to 20200918.0 2020-09-18 17:30:02 +02:00
Bram Kragten
1ffa87ea23 Fix duplicate items in sortables (#7053) 2020-09-18 17:28:19 +02:00
Kendell R
357df2bf68 Default colon color to primary text color (#7044)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-09-18 17:23:41 +02:00
Bram Kragten
24f3db3e3f Add hold action to buttons (#7051) 2020-09-18 17:20:31 +02:00
Zack Barett
4bb51b0120 fix log copy (#7048) 2020-09-18 12:53:26 +02:00
Bram Kragten
32b9c1eba1 Fix tap to toggle sidebar (#7049) 2020-09-18 12:17:10 +02:00
HomeAssistant Azure
40bffc1d25 [ci skip] Translation update 2020-09-18 00:32:23 +00:00
Bram Kragten
ed2c4e2642 Merge pull request #7034 from home-assistant/dev 2020-09-17 13:26:49 +02:00
Bram Kragten
b3353e220a Bumped version to 20200917.1 2020-09-17 13:02:52 +02:00
Bram Kragten
7dc917babf Adjust local source path (#7033) 2020-09-17 12:59:24 +02:00
384 changed files with 17558 additions and 5109 deletions

View File

@@ -76,12 +76,13 @@
"default-case": 0,
"wc/no-self-class": 0,
"@typescript-eslint/camelcase": 0,
"@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/no-use-before-define": 0,
"@typescript-eslint/no-non-null-assertion": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-unused-vars": 0,
"@typescript-eslint/explicit-function-return-type": 0
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/explicit-module-boundary-types": 0
},
"plugins": ["disable", "import", "lit", "prettier", "@typescript-eslint"],
"processor": "disable/disable"

View File

@@ -52,7 +52,10 @@ module.exports.terserOptions = (latestBuild) => ({
module.exports.babelOptions = ({ latestBuild }) => ({
babelrc: false,
presets: [
!latestBuild && [require("@babel/preset-env").default, { modules: false }],
!latestBuild && [
require("@babel/preset-env").default,
{ modules: false, useBuiltIns: "entry", corejs: 3 },
],
require("@babel/preset-typescript").default,
].filter(Boolean),
plugins: [
@@ -62,6 +65,7 @@ module.exports.babelOptions = ({ latestBuild }) => ({
{ loose: true, useBuiltIns: true },
],
// Only support the syntax, Webpack will handle it.
"@babel/plugin-syntax-import-meta",
"@babel/syntax-dynamic-import",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",

View File

@@ -2,7 +2,6 @@ const webpack = require("webpack");
const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
const ManifestPlugin = require("webpack-manifest-plugin");
const WorkerPlugin = require("worker-plugin");
const paths = require("./paths.js");
const bundle = require("./bundle");
@@ -55,7 +54,6 @@ const createWebpackConfig = ({
],
},
plugins: [
new WorkerPlugin(),
new ManifestPlugin({
// Only include the JS of entrypoints
filter: (file) => file.isInitial && !file.name.endsWith(".map"),

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -212,13 +212,8 @@
Chromecast is a technology developed by Google, and is available on:
</p>
<ul>
<li>Google Chrome (all platforms except on iOS)</li>
<li>
Microsoft Edge (all platforms,
<a href="https://www.microsoftedgeinsider.com" target="_blank"
>dev and canary builds only</a
>)
</li>
<li>Google Chrome (all platforms except iOS)</li>
<li>Microsoft Edge (all platforms)</li>
</ul>
</div>

View File

@@ -6,13 +6,60 @@ import { castContext } from "./cast_context";
import { HcMain } from "./layout/hc-main";
import { ReceivedMessage } from "./types";
const controller = new HcMain();
document.body.append(controller);
const lovelaceController = new HcMain();
document.body.append(lovelaceController);
const mediaPlayer = document.createElement("cast-media-player");
mediaPlayer.style.display = "none";
document.body.append(mediaPlayer);
const playerStylesAdded = false;
let controls: HTMLElement | null;
const setTouchControlsVisibility = (visible: boolean) => {
if (!castContext.getDeviceCapabilities().touch_input_supported) {
return;
}
controls =
controls ||
(document.body.querySelector("touch-controls") as HTMLElement | null);
if (controls) {
controls.style.display = visible ? "initial" : "none";
}
};
const showLovelaceController = () => {
mediaPlayer.style.display = "none";
lovelaceController.style.display = "initial";
document.body.setAttribute("style", "overflow-y: auto !important");
setTouchControlsVisibility(false);
};
const showMediaPlayer = () => {
lovelaceController.style.display = "none";
mediaPlayer.style.display = "initial";
document.body.removeAttribute("style");
setTouchControlsVisibility(true);
if (!playerStylesAdded) {
const style = document.createElement("style");
style.innerHTML = `
body {
--logo-image: url('https://www.home-assistant.io/images/home-assistant-logo.svg');
--logo-repeat: no-repeat;
--playback-logo-image: url('https://www.home-assistant.io/images/home-assistant-logo.svg');
--theme-hue: 200;
--progress-color: #03a9f4;
--splash-image: url('https://home-assistant.io/images/cast/splash.png');
--splash-size: cover;
}
`;
document.head.appendChild(style);
}
};
const options = new cast.framework.CastReceiverOptions();
options.disableIdleTimeout = true;
options.customNamespaces = {
// @ts-ignore
[CAST_NS]: cast.framework.system.MessageType.JSON,
};
@@ -30,13 +77,61 @@ options.uiConfig = new cast.framework.ui.UiConfig();
// @ts-ignore
options.uiConfig.touchScreenOptimizedApp = true;
castContext.setInactivityTimeout(86400); // 1 day
castContext.addCustomMessageListener(
CAST_NS,
// @ts-ignore
(ev: ReceivedMessage<HassMessage>) => {
// We received a show Lovelace command, stop media from playing, hide media player and show Lovelace controller
if (
playerManager.getPlayerState() !==
cast.framework.messages.PlayerState.IDLE
) {
playerManager.stop();
} else {
showLovelaceController();
}
const msg = ev.data;
msg.senderId = ev.senderId;
controller.processIncomingMessage(msg);
lovelaceController.processIncomingMessage(msg);
}
);
const playerManager = castContext.getPlayerManager();
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
(loadRequestData) => {
// We received a play media command, hide Lovelace and show media player
showMediaPlayer();
const media = loadRequestData.media;
// Special handling if it came from Google Assistant
if (media.entity) {
media.contentId = media.entity;
media.streamType = cast.framework.messages.StreamType.LIVE;
media.contentType = "application/vnd.apple.mpegurl";
// @ts-ignore
media.hlsVideoSegmentFormat =
cast.framework.messages.HlsVideoSegmentFormat.FMP4;
}
return loadRequestData;
}
);
playerManager.addEventListener(
cast.framework.events.EventType.MEDIA_STATUS,
(event) => {
if (
event.mediaStatus?.playerState ===
cast.framework.messages.PlayerState.IDLE &&
event.mediaStatus?.idleReason &&
event.mediaStatus?.idleReason !==
cast.framework.messages.IdleReason.INTERRUPTED
) {
// media finished or stopped, return to default Lovelace
showLovelaceController();
}
}
);

View File

@@ -9,7 +9,6 @@ import {
} from "lit-element";
import { LovelaceConfig } from "../../../../src/data/lovelace";
import { Lovelace } from "../../../../src/panels/lovelace/types";
import "../../../../src/panels/lovelace/views/hui-panel-view";
import "../../../../src/panels/lovelace/views/hui-view";
import { HomeAssistant } from "../../../../src/types";
import "./hc-launch-screen";
@@ -45,22 +44,13 @@ class HcLovelace extends LitElement {
deleteConfig: async () => undefined,
setEditMode: () => undefined,
};
return this.lovelaceConfig.views[index].panel
? html`
<hui-panel-view
.hass=${this.hass}
.lovelace=${lovelace}
.config=${this.lovelaceConfig.views[index]}
></hui-panel-view>
`
: html`
<hui-view
.hass=${this.hass}
.lovelace=${lovelace}
.index=${index}
columns="2"
></hui-view>
`;
return html`
<hui-view
.hass=${this.hass}
.lovelace=${lovelace}
.index=${index}
></hui-view>
`;
}
protected updated(changedProps) {
@@ -76,7 +66,7 @@ class HcLovelace extends LitElement {
if (configBackground) {
(this.shadowRoot!.querySelector(
"hui-view, hui-panel-view"
"hui-view"
) as HTMLElement)!.style.setProperty(
"--lovelace-background",
configBackground

View File

@@ -216,9 +216,7 @@ export class HcMain extends HassElement {
}
this._showDemo = false;
this._lovelacePath = msg.viewPath;
if (castContext.getDeviceCapabilities().touch_input_supported) {
this._breakFree();
}
this._sendStatus();
}
@@ -241,9 +239,6 @@ export class HcMain extends HassElement {
this._showDemo = true;
this._lovelacePath = "overview";
this._sendStatus();
if (castContext.getDeviceCapabilities().touch_input_supported) {
this._breakFree();
}
});
}
@@ -264,14 +259,6 @@ export class HcMain extends HassElement {
}
}
private _breakFree() {
const controls = document.body.querySelector("touch-controls");
if (controls) {
controls.remove();
}
document.body.setAttribute("style", "overflow-y: auto !important");
}
private sendMessage(senderId: string, response: any) {
castContext.sendCustomMessage(CAST_NS, senderId, response);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 767 B

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 803 B

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 110 KiB

View File

@@ -1,7 +1,7 @@
import { HassEntity } from "home-assistant-js-websocket";
import { property, PropertyValues, UpdatingElement } from "lit-element";
import dynamicContentUpdater from "../../../src/common/dom/dynamic_content_updater";
import { stateMoreInfoType } from "../../../src/common/entity/state_more_info_type";
import { stateMoreInfoType } from "../../../src/dialogs/more-info/state_more_info_control";
import "../../../src/dialogs/more-info/controls/more-info-alarm_control_panel";
import "../../../src/dialogs/more-info/controls/more-info-automation";
import "../../../src/dialogs/more-info/controls/more-info-camera";

View File

@@ -98,14 +98,14 @@ class HassioAddonStore extends LitElement {
main-page
.tabs=${supervisorTabs}
>
<span slot="header">Add-on store</span>
<span slot="header">Add-on Store</span>
<ha-button-menu
corner="BOTTOM_START"
slot="toolbar-icon"
@action=${this._handleAction}
>
<mwc-icon-button slot="trigger" alt="menu">
<ha-svg-icon path=${mdiDotsVertical}></ha-svg-icon>
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
</mwc-icon-button>
<mwc-list-item>
Repositories

View File

@@ -39,7 +39,7 @@ class HassioAddonConfig extends LitElement {
@property({ type: Boolean }) private _configHasChanged = false;
@query("ha-yaml-editor") private _editor!: HaYamlEditor;
@query("ha-yaml-editor", true) private _editor!: HaYamlEditor;
protected render(): TemplateResult {
const editor = this._editor;
@@ -175,7 +175,7 @@ class HassioAddonConfig extends LitElement {
}
iron-autogrow-textarea {
width: 100%;
font-family: monospace;
font-family: var(--code-font-family, monospace);
}
.syntaxerror {
color: var(--error-color);

View File

@@ -69,7 +69,7 @@ const STAGE_ICON = {
const PERMIS_DESC = {
stage: {
title: "Add-on Stage",
description: `Add-ons can have one of three stages:\n\n<ha-svg-icon path='${STAGE_ICON.stable}'></ha-svg-icon> **Stable**: These are add-ons ready to be used in production.\n\n<ha-svg-icon path='${STAGE_ICON.experimental}'></ha-svg-icon> **Experimental**: These may contain bugs, and may be unfinished.\n\n<ha-svg-icon path='${STAGE_ICON.deprecated}'></ha-svg-icon> **Deprecated**: These add-ons will no longer receive any updates.`,
description: `Add-ons can have one of three stages:\n\n<ha-svg-icon .path='${STAGE_ICON.stable}'></ha-svg-icon> **Stable**: These are add-ons ready to be used in production.\n\n<ha-svg-icon .path='${STAGE_ICON.experimental}'></ha-svg-icon> **Experimental**: These may contain bugs, and may be unfinished.\n\n<ha-svg-icon .path='${STAGE_ICON.deprecated}'></ha-svg-icon> **Deprecated**: These add-ons will no longer receive any updates.`,
},
rating: {
title: "Add-on Security Rating",
@@ -202,14 +202,14 @@ class HassioAddonInfo extends LitElement {
<ha-svg-icon
title="Add-on is running"
class="running"
path=${mdiCircle}
.path=${mdiCircle}
></ha-svg-icon>
`
: html`
<ha-svg-icon
title="Add-on is stopped"
class="stopped"
path=${mdiCircle}
.path=${mdiCircle}
></ha-svg-icon>
`}
`
@@ -283,7 +283,7 @@ class HassioAddonInfo extends LitElement {
label="host"
description=""
>
<ha-svg-icon path=${mdiNetwork}></ha-svg-icon>
<ha-svg-icon .path=${mdiNetwork}></ha-svg-icon>
</ha-label-badge>
`
: ""}
@@ -295,7 +295,7 @@ class HassioAddonInfo extends LitElement {
label="hardware"
description=""
>
<ha-svg-icon path=${mdiChip}></ha-svg-icon>
<ha-svg-icon .path=${mdiChip}></ha-svg-icon>
</ha-label-badge>
`
: ""}
@@ -307,7 +307,7 @@ class HassioAddonInfo extends LitElement {
label="hass"
description=""
>
<ha-svg-icon path=${mdiHomeAssistant}></ha-svg-icon>
<ha-svg-icon .path=${mdiHomeAssistant}></ha-svg-icon>
</ha-label-badge>
`
: ""}
@@ -319,7 +319,7 @@ class HassioAddonInfo extends LitElement {
label="hassio"
.description=${this.addon.hassio_role}
>
<ha-svg-icon path=${mdiHomeAssistant}></ha-svg-icon>
<ha-svg-icon .path=${mdiHomeAssistant}></ha-svg-icon>
</ha-label-badge>
`
: ""}
@@ -331,7 +331,7 @@ class HassioAddonInfo extends LitElement {
label="docker"
description=""
>
<ha-svg-icon path=${mdiDocker}></ha-svg-icon>
<ha-svg-icon .path=${mdiDocker}></ha-svg-icon>
</ha-label-badge>
`
: ""}
@@ -343,7 +343,7 @@ class HassioAddonInfo extends LitElement {
label="host pid"
description=""
>
<ha-svg-icon path=${mdiPound}></ha-svg-icon>
<ha-svg-icon .path=${mdiPound}></ha-svg-icon>
</ha-label-badge>
`
: ""}
@@ -356,7 +356,7 @@ class HassioAddonInfo extends LitElement {
label="apparmor"
description=""
>
<ha-svg-icon path=${mdiShield}></ha-svg-icon>
<ha-svg-icon .path=${mdiShield}></ha-svg-icon>
</ha-label-badge>
`
: ""}
@@ -368,7 +368,7 @@ class HassioAddonInfo extends LitElement {
label="auth"
description=""
>
<ha-svg-icon path=${mdiKey}></ha-svg-icon>
<ha-svg-icon .path=${mdiKey}></ha-svg-icon>
</ha-label-badge>
`
: ""}
@@ -381,7 +381,7 @@ class HassioAddonInfo extends LitElement {
description=""
>
<ha-svg-icon
path=${mdiCursorDefaultClickOutline}
.path=${mdiCursorDefaultClickOutline}
></ha-svg-icon>
</ha-label-badge>
`
@@ -798,10 +798,10 @@ class HassioAddonInfo extends LitElement {
);
if (!validate.data.valid) {
await showConfirmationDialog(this, {
title: "Failed to start addon - configruation validation faled!",
title: "Failed to start addon - configuration validation failed!",
text: validate.data.message.split(" Got ")[0],
confirm: () => this._openConfiguration(),
confirmText: "Go to configruation",
confirmText: "Go to configuration",
dismissText: "Cancel",
});
button.progress = false;

View File

@@ -0,0 +1,81 @@
import "../../../src/components/ha-file-upload";
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 { fireEvent } from "../../../src/common/dom/fire_event";
import "../../../src/components/ha-circular-progress";
import "../../../src/components/ha-svg-icon";
import {
HassioSnapshot,
uploadSnapshot,
} from "../../../src/data/hassio/snapshot";
import { HomeAssistant } from "../../../src/types";
import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
declare global {
interface HASSDomEvents {
"snapshot-uploaded": { snapshot: HassioSnapshot };
}
}
@customElement("hassio-upload-snapshot")
export class HassioUploadSnapshot extends LitElement {
public hass!: HomeAssistant;
@internalProperty() public value: string | null = null;
@internalProperty() private _uploading = false;
public render(): TemplateResult {
return html`
<ha-file-upload
.uploading=${this._uploading}
.icon=${mdiFolderUpload}
accept="application/x-tar"
label="Upload snapshot"
@file-picked=${this._uploadFile}
auto-open-file-dialog
></ha-file-upload>
`;
}
private async _uploadFile(ev) {
const file = ev.detail.files[0];
if (!["application/x-tar"].includes(file.type)) {
showAlertDialog(this, {
title: "Unsupported file format",
text: "Please choose a Home Assistant snapshot file (.tar)",
confirmText: "ok",
});
return;
}
this._uploading = true;
try {
const snapshot = await uploadSnapshot(this.hass, file);
fireEvent(this, "snapshot-uploaded", { snapshot: snapshot.data });
} catch (err) {
showAlertDialog(this, {
title: "Upload failed",
text: err.toString(),
confirmText: "ok",
});
} finally {
this._uploading = false;
}
}
}
declare global {
interface HTMLElementTagNameMap {
"hassio-upload-snapshot": HassioUploadSnapshot;
}
}

View File

@@ -10,6 +10,7 @@ import {
} from "lit-element";
import { atLeastVersion } from "../../../src/common/config/version";
import { navigate } from "../../../src/common/navigate";
import { compare } from "../../../src/common/string/compare";
import "../../../src/components/ha-card";
import { HassioAddonInfo } from "../../../src/data/hassio/addon";
import { haStyle } from "../../../src/resources/styles";
@@ -21,25 +22,27 @@ import { hassioStyle } from "../resources/hassio-style";
class HassioAddons extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property() public addons?: HassioAddonInfo[];
@property({ attribute: false }) public addons?: HassioAddonInfo[];
protected render(): TemplateResult {
return html`
<div class="content">
<h1>Add-ons</h1>
<div class="card-group">
${!this.addons
${!this.addons?.length
? html`
<ha-card>
<div class="card-content">
You don't have any add-ons installed yet. Head over to
<a href="#" @click=${this._openStore}>the add-on store</a>
<button class="link" @click=${this._openStore}>
the add-on store
</button>
to get started!
</div>
</ha-card>
`
: this.addons
.sort((a, b) => (a.name > b.name ? 1 : -1))
.sort((a, b) => compare(a.name, b.name))
.map(
(addon) => html`
<ha-card .addon=${addon} @click=${this._addonTapped}>

View File

@@ -39,7 +39,8 @@ import type { HomeAssistant } from "../../../../src/types";
import { HassioNetworkDialogParams } from "./show-dialog-network";
@customElement("dialog-hassio-network")
export class DialogHassioNetwork extends LitElement implements HassDialog {
export class DialogHassioNetwork extends LitElement
implements HassDialog<HassioNetworkDialogParams> {
@property({ attribute: false }) public hass!: HomeAssistant;
@internalProperty() private _prosessing = false;

View File

@@ -39,7 +39,7 @@ class HassioRepositoriesDialog extends LitElement {
@property({ attribute: false })
private _dialogParams?: HassioRepositoryDialogParams;
@query("#repository_input") private _optionInput?: PaperInputElement;
@query("#repository_input", true) private _optionInput?: PaperInputElement;
@internalProperty() private _opened = false;
@@ -91,7 +91,7 @@ class HassioRepositoriesDialog extends LitElement {
title="Remove"
@click=${this._removeRepository}
>
<ha-svg-icon path=${mdiDelete}></ha-svg-icon>
<ha-svg-icon .path=${mdiDelete}></ha-svg-icon>
</mwc-icon-button>
</paper-item>
`;

View File

@@ -0,0 +1,107 @@
import { mdiClose } from "@mdi/js";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/ha-header-bar";
import { HassDialog } from "../../../../src/dialogs/make-dialog-manager";
import { haStyleDialog } from "../../../../src/resources/styles";
import type { HomeAssistant } from "../../../../src/types";
import "../../components/hassio-upload-snapshot";
import { HassioSnapshotUploadDialogParams } from "./show-dialog-snapshot-upload";
@customElement("dialog-hassio-snapshot-upload")
export class DialogHassioSnapshotUpload extends LitElement
implements HassDialog<HassioSnapshotUploadDialogParams> {
@property({ attribute: false }) public hass!: HomeAssistant;
@internalProperty() private _params?: HassioSnapshotUploadDialogParams;
public async showDialog(
params: HassioSnapshotUploadDialogParams
): Promise<void> {
this._params = params;
await this.updateComplete;
}
public closeDialog(): void {
if (this._params && !this._params.onboarding) {
if (this._params.reloadSnapshot) {
this._params.reloadSnapshot();
}
}
this._params = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
protected render(): TemplateResult {
if (!this._params) {
return html``;
}
return html`
<ha-dialog
open
scrimClickAction
escapeKeyAction
hideActions
.heading=${true}
@closed=${this.closeDialog}
>
<div slot="heading">
<ha-header-bar>
<span slot="title">
Upload snapshot
</span>
<mwc-icon-button slot="actionItems" dialogAction="cancel">
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
</mwc-icon-button>
</ha-header-bar>
</div>
<hassio-upload-snapshot
@snapshot-uploaded=${this._snapshotUploaded}
.hass=${this.hass}
></hassio-upload-snapshot>
</ha-dialog>
`;
}
private _snapshotUploaded(ev) {
const snapshot = ev.detail.snapshot;
this._params?.showSnapshot(snapshot.slug);
this.closeDialog();
}
static get styles(): CSSResult[] {
return [
haStyleDialog,
css`
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);
}
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"dialog-hassio-snapshot-upload": DialogHassioSnapshotUpload;
}
}

View File

@@ -1,5 +1,5 @@
import "@material/mwc-button";
import { mdiDelete, mdiDownload, mdiHistory } from "@mdi/js";
import { mdiClose, mdiDelete, mdiDownload, mdiHistory } from "@mdi/js";
import { PaperCheckboxElement } from "@polymer/paper-checkbox/paper-checkbox";
import "@polymer/paper-input/paper-input";
import {
@@ -12,7 +12,8 @@ import {
property,
TemplateResult,
} from "lit-element";
import { createCloseHeading } from "../../../../src/components/ha-dialog";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/ha-header-bar";
import "../../../../src/components/ha-svg-icon";
import { getSignedPath } from "../../../../src/data/auth";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
@@ -22,7 +23,7 @@ import {
} from "../../../../src/data/hassio/snapshot";
import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box";
import { PolymerChangedEvent } from "../../../../src/polymer-types";
import { haStyleDialog } from "../../../../src/resources/styles";
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { HassioSnapshotDialogParams } from "./show-dialog-hassio-snapshot";
@@ -75,6 +76,8 @@ class HassioSnapshotDialog extends LitElement {
@internalProperty() private _error?: string;
@internalProperty() private _onboarding = false;
@internalProperty() private _snapshot?: HassioSnapshotDetail;
@internalProperty() private _folders!: FolderItem[];
@@ -90,13 +93,14 @@ class HassioSnapshotDialog extends LitElement {
public async showDialog(params: HassioSnapshotDialogParams) {
this._snapshot = await fetchHassioSnapshotInfo(this.hass, params.slug);
this._folders = _computeFolders(
this._snapshot.folders
this._snapshot?.folders
).sort((a: FolderItem, b: FolderItem) => (a.name > b.name ? 1 : -1));
this._addons = _computeAddons(
this._snapshot.addons
this._snapshot?.addons
).sort((a: AddonItem, b: AddonItem) => (a.name > b.name ? 1 : -1));
this._dialogParams = params;
this._onboarding = params.onboarding ?? false;
}
protected render(): TemplateResult {
@@ -104,12 +108,17 @@ class HassioSnapshotDialog extends LitElement {
return html``;
}
return html`
<ha-dialog
open
stacked
@closing=${this._closeDialog}
.heading=${createCloseHeading(this.hass, this._computeName)}
>
<ha-dialog open stacked @closing=${this._closeDialog} .heading=${true}>
<div slot="heading">
<ha-header-bar>
<span slot="title">
${this._computeName}
</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"
@@ -182,17 +191,21 @@ class HassioSnapshotDialog extends LitElement {
${this._error ? html` <p class="error">Error: ${this._error}</p> ` : ""}
<div>Actions:</div>
<mwc-button @click=${this._downloadClicked} slot="primaryAction">
<ha-svg-icon path=${mdiDownload} class="icon"></ha-svg-icon>
Download Snapshot
</mwc-button>
${!this._onboarding
? html`<mwc-button
@click=${this._downloadClicked}
slot="primaryAction"
>
<ha-svg-icon .path=${mdiDownload} class="icon"></ha-svg-icon>
Download Snapshot
</mwc-button>`
: ""}
<mwc-button
@click=${this._partialRestoreClicked}
slot="secondaryAction"
>
<ha-svg-icon path=${mdiHistory} class="icon"></ha-svg-icon>
<ha-svg-icon .path=${mdiHistory} class="icon"></ha-svg-icon>
Restore Selected
</mwc-button>
${this._snapshot.type === "full"
@@ -201,21 +214,30 @@ class HassioSnapshotDialog extends LitElement {
@click=${this._fullRestoreClicked}
slot="secondaryAction"
>
<ha-svg-icon path=${mdiHistory} class="icon"></ha-svg-icon>
<ha-svg-icon .path=${mdiHistory} class="icon"></ha-svg-icon>
Wipe &amp; restore
</mwc-button>
`
: ""}
<mwc-button @click=${this._deleteClicked} slot="secondaryAction">
<ha-svg-icon path=${mdiDelete} class="icon warning"></ha-svg-icon>
<span class="warning">Delete Snapshot</span>
</mwc-button>
${!this._onboarding
? html`<mwc-button
@click=${this._deleteClicked}
slot="secondaryAction"
>
<ha-svg-icon
.path=${mdiDelete}
class="icon warning"
></ha-svg-icon>
<span class="warning">Delete Snapshot</span>
</mwc-button>`
: ""}
</ha-dialog>
`;
}
static get styles(): CSSResult[] {
return [
haStyle,
haStyleDialog,
css`
paper-checkbox {
@@ -242,6 +264,18 @@ class HassioSnapshotDialog extends LitElement {
.no-margin-top {
margin-top: 0;
}
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);
}
}
`,
];
}
@@ -272,6 +306,8 @@ class HassioSnapshotDialog extends LitElement {
if (
!(await showConfirmationDialog(this, {
title: "Are you sure you want partially to restore this snapshot?",
confirmText: "restore",
dismissText: "cancel",
}))
) {
return;
@@ -300,22 +336,31 @@ class HassioSnapshotDialog extends LitElement {
data.password = this._snapshotPassword;
}
this.hass
.callApi(
"POST",
if (!this._onboarding) {
this.hass
.callApi(
"POST",
`hassio/snapshots/${this._snapshot!.slug}/restore/partial`,
data
)
.then(
() => {
alert("Snapshot restored!");
this._closeDialog();
},
(error) => {
this._error = error.body.message;
}
);
`hassio/snapshots/${this._snapshot!.slug}/restore/partial`,
data
)
.then(
() => {
alert("Snapshot restored!");
this._closeDialog();
},
(error) => {
this._error = error.body.message;
}
);
} else {
fireEvent(this, "restoring");
fetch(`/api/hassio/snapshots/${this._snapshot!.slug}/restore/partial`, {
method: "POST",
body: JSON.stringify(data),
});
this._closeDialog();
}
}
private async _fullRestoreClicked() {
@@ -323,6 +368,8 @@ class HassioSnapshotDialog extends LitElement {
!(await showConfirmationDialog(this, {
title:
"Are you sure you want to wipe your system and restore this snapshot?",
confirmText: "restore",
dismissText: "cancel",
}))
) {
return;
@@ -331,28 +378,38 @@ class HassioSnapshotDialog extends LitElement {
const data = this._snapshot!.protected
? { password: this._snapshotPassword }
: undefined;
this.hass
.callApi(
"POST",
`hassio/snapshots/${this._snapshot!.slug}/restore/full`,
data
)
.then(
() => {
alert("Snapshot restored!");
this._closeDialog();
},
(error) => {
this._error = error.body.message;
}
);
if (!this._onboarding) {
this.hass
.callApi(
"POST",
`hassio/snapshots/${this._snapshot!.slug}/restore/full`,
data
)
.then(
() => {
alert("Snapshot restored!");
this._closeDialog();
},
(error) => {
this._error = error.body.message;
}
);
} else {
fireEvent(this, "restoring");
fetch(`/api/hassio/snapshots/${this._snapshot!.slug}/restore/full`, {
method: "POST",
body: JSON.stringify(data),
});
this._closeDialog();
}
}
private async _deleteClicked() {
if (
!(await showConfirmationDialog(this, {
title: "Are you sure you want to delete this snapshot?",
confirmText: "delete",
dismissText: "cancel",
}))
) {
return;
@@ -363,7 +420,9 @@ class HassioSnapshotDialog extends LitElement {
.callApi("POST", `hassio/snapshots/${this._snapshot!.slug}/remove`)
.then(
() => {
this._dialogParams!.onDelete();
if (this._dialogParams!.onDelete) {
this._dialogParams!.onDelete();
}
this._closeDialog();
},
(error) => {
@@ -384,6 +443,19 @@ class HassioSnapshotDialog extends LitElement {
return;
}
if (window.location.href.includes("ui.nabu.casa")) {
const confirm = await showConfirmationDialog(this, {
title: "Potential slow download",
text:
"Downloading snapshots over the Nabu Casa URL will take some time, it is recomended to use your local URL instead, do you want to continue?",
confirmText: "continue",
dismissText: "cancel",
});
if (!confirm) {
return;
}
}
const name = this._computeName.replace(/[^a-z0-9]+/gi, "_");
const a = document.createElement("a");
a.href = signedPath.path;

View File

@@ -2,7 +2,8 @@ import { fireEvent } from "../../../../src/common/dom/fire_event";
export interface HassioSnapshotDialogParams {
slug: string;
onDelete: () => void;
onDelete?: () => void;
onboarding?: boolean;
}
export const showHassioSnapshotDialog = (

View File

@@ -0,0 +1,22 @@
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "./dialog-hassio-snapshot-upload";
export interface HassioSnapshotUploadDialogParams {
showSnapshot: (slug: string) => void;
reloadSnapshot?: () => Promise<void>;
onboarding?: boolean;
}
export const showSnapshotUploadDialog = (
element: HTMLElement,
dialogParams: HassioSnapshotUploadDialogParams
): void => {
fireEvent(element, "show-dialog", {
dialogTag: "dialog-hassio-snapshot-upload",
dialogImport: () =>
import(
/* webpackChunkName: "dialog-hassio-snapshot-upload" */ "./dialog-hassio-snapshot-upload"
),
dialogParams,
});
};

View File

@@ -8,7 +8,7 @@ export const supervisorTabs: PageNavigation[] = [
iconPath: mdiViewDashboard,
},
{
name: "Add-on store",
name: "Add-on Store",
path: `/hassio/store`,
iconPath: mdiStore,
},

View File

@@ -57,7 +57,7 @@ class HassioIngressView extends LitElement {
aria-label=${this.hass.localize("ui.sidebar.sidebar_toggle")}
@click=${this._toggleMenu}
>
<ha-svg-icon path=${mdiMenu}></ha-svg-icon>
<ha-svg-icon .path=${mdiMenu}></ha-svg-icon>
</mwc-icon-button>
<div class="main-title">${this._addon.name}</div>
</div>

View File

@@ -1,6 +1,12 @@
import "@material/mwc-button";
import "@material/mwc-icon-button";
import { mdiPackageVariant, mdiPackageVariantClosed, mdiReload } from "@mdi/js";
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
import "@material/mwc-list/mwc-list-item";
import {
mdiDotsVertical,
mdiPackageVariant,
mdiPackageVariantClosed,
} from "@mdi/js";
import "@polymer/paper-checkbox/paper-checkbox";
import type { PaperCheckboxElement } from "@polymer/paper-checkbox/paper-checkbox";
import "@polymer/paper-input/paper-input";
@@ -19,8 +25,10 @@ import {
PropertyValues,
TemplateResult,
} from "lit-element";
import { atLeastVersion } from "../../../src/common/config/version";
import { fireEvent } from "../../../src/common/dom/fire_event";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-button-menu";
import "../../../src/components/ha-card";
import "../../../src/components/ha-svg-icon";
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
@@ -39,7 +47,9 @@ import { PolymerChangedEvent } from "../../../src/polymer-types";
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant, Route } from "../../../src/types";
import "../components/hassio-card-content";
import "../components/hassio-upload-snapshot";
import { showHassioSnapshotDialog } from "../dialogs/snapshot/show-dialog-hassio-snapshot";
import { showSnapshotUploadDialog } from "../dialogs/snapshot/show-dialog-snapshot-upload";
import { supervisorTabs } from "../hassio-tabs";
import { hassioStyle } from "../resources/hassio-style";
@@ -101,18 +111,27 @@ class HassioSnapshots extends LitElement {
.tabs=${supervisorTabs}
>
<span slot="header">Snapshots</span>
<mwc-icon-button
<ha-button-menu
corner="BOTTOM_START"
slot="toolbar-icon"
aria-label="Reload snapshots"
@click=${this.refreshData}
@action=${this._handleAction}
>
<ha-svg-icon path=${mdiReload}></ha-svg-icon>
</mwc-icon-button>
<mwc-icon-button slot="trigger" alt="menu">
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
</mwc-icon-button>
<mwc-list-item>
Reload
</mwc-list-item>
${atLeastVersion(this.hass.config.version, 0, 116)
? html`<mwc-list-item>
Upload snapshot
</mwc-list-item>`
: ""}
</ha-button-menu>
<div class="content">
<h1>
Create snapshot
Create Snapshot
</h1>
<p class="description">
Snapshots allow you to easily backup and restore all data of your
@@ -200,7 +219,7 @@ class HassioSnapshots extends LitElement {
</ha-card>
</div>
<h1>Available snapshots</h1>
<h1>Available Snapshots</h1>
<div class="card-group">
${this._snapshots === undefined
? undefined
@@ -257,6 +276,17 @@ class HassioSnapshots extends LitElement {
}
}
private _handleAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
this.refreshData();
break;
case 1:
this._showUploadSnapshotDialog();
break;
}
}
private _handleTextValueChanged(ev: PolymerChangedEvent<string>) {
const input = ev.currentTarget as PaperInputElement;
this[`_${input.name}`] = ev.detail.value;
@@ -362,6 +392,17 @@ class HassioSnapshots extends LitElement {
});
}
private _showUploadSnapshotDialog() {
showSnapshotUploadDialog(this, {
showSnapshot: (slug: string) =>
showHassioSnapshotDialog(this, {
slug,
onDelete: () => this._updateSnapshots(),
}),
reloadSnapshot: () => this.refreshData(),
});
}
static get styles(): CSSResultArray {
return [
haStyle,

View File

@@ -87,7 +87,7 @@ class HassioHostInfo extends LitElement {
${this.hostInfo.features.includes("network")
? html` <ha-settings-row>
<span slot="heading">
IP address
IP Address
</span>
<span slot="description">
${primaryIpAddress}
@@ -103,7 +103,7 @@ class HassioHostInfo extends LitElement {
<ha-settings-row>
<span slot="heading">
Operating system
Operating System
</span>
<span slot="description">
${this.hostInfo.operating_system}
@@ -221,7 +221,7 @@ class HassioHostInfo extends LitElement {
});
} catch (err) {
showAlertDialog(this, {
title: "Failed to get Hardware list",
title: "Failed to get hardware list",
text: extractApiErrorMessage(err),
});
}
@@ -324,7 +324,7 @@ class HassioHostInfo extends LitElement {
private async _changeHostnameClicked(): Promise<void> {
const curHostname: string = this.hostInfo.hostname;
const hostname = await showPromptDialog(this, {
title: "Change hostname",
title: "Change Hostname",
inputLabel: "Please enter a new hostname:",
inputType: "string",
defaultValue: curHostname,

View File

@@ -51,7 +51,7 @@ class HassioSupervisorInfo extends LitElement {
</ha-settings-row>
<ha-settings-row>
<span slot="heading">
Newest version
Newest Version
</span>
<span slot="description">
${this.supervisorInfo.version_latest}
@@ -98,7 +98,7 @@ class HassioSupervisorInfo extends LitElement {
${this.supervisorInfo?.supported
? html` <ha-settings-row three-line>
<span slot="heading">
Share diagnostics
Share Diagnostics
</span>
<div slot="description" class="diagnostics-description">
Share crash reports and diagnostic information.
@@ -135,7 +135,7 @@ class HassioSupervisorInfo extends LitElement {
<div class="card-actions">
<ha-progress-button
@click=${this._supervisorReload}
title="Reload parts of the supervisor."
title="Reload parts of the supervisor"
>
Reload
</ha-progress-button>
@@ -212,7 +212,7 @@ class HassioSupervisorInfo extends LitElement {
button.progress = true;
const confirmed = await showConfirmationDialog(this, {
title: "Update supervisor",
title: "Update Supervisor",
text: `Are you sure you want to update supervisor to version ${this.supervisorInfo.version_latest}?`,
confirmText: "update",
dismissText: "cancel",

View File

@@ -76,7 +76,7 @@ class HassioSupervisorLog extends LitElement {
${this.hass.userData?.showAdvanced
? html`
<paper-dropdown-menu
label="Log provider"
label="Log Provider"
@iron-select=${this._setLogProvider}
>
<paper-listbox

View File

@@ -0,0 +1,186 @@
import "@material/mwc-button";
import "@material/mwc-list/mwc-list-item";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { classMap } from "lit-html/directives/class-map";
import memoizeOne from "memoize-one";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-bar";
import "../../../src/components/ha-button-menu";
import "../../../src/components/ha-card";
import "../../../src/components/ha-settings-row";
import { fetchHassioStats, HassioStats } from "../../../src/data/hassio/common";
import { HassioHostInfo } from "../../../src/data/hassio/host";
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant } from "../../../src/types";
import {
getValueInPercentage,
roundWithOneDecimal,
} from "../../../src/util/calculate";
import { bytesToString } from "../../../src/util/bytes-to-string";
import { hassioStyle } from "../resources/hassio-style";
@customElement("hassio-system-metrics")
class HassioSystemMetrics extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property() public hostInfo!: HassioHostInfo;
@internalProperty() private _supervisorMetrics?: HassioStats;
@internalProperty() private _coreMetrics?: HassioStats;
protected render(): TemplateResult | void {
const metrics = [
{
description: "Core CPU Usage",
value: this._coreMetrics?.cpu_percent,
},
{
description: "Core RAM Usage",
value: this._coreMetrics?.memory_percent,
tooltip: `${bytesToString(
this._coreMetrics?.memory_usage
)}/${bytesToString(this._coreMetrics?.memory_limit)}`,
},
{
description: "Supervisor CPU Usage",
value: this._supervisorMetrics?.cpu_percent,
},
{
description: "Supervisor RAM Usage",
value: this._supervisorMetrics?.memory_percent,
tooltip: `${bytesToString(
this._supervisorMetrics?.memory_usage
)}/${bytesToString(this._supervisorMetrics?.memory_limit)}`,
},
{
description: "Used Space",
value: this._getUsedSpace(this.hostInfo),
tooltip: `${
this.hostInfo.disk_used
} GB/${this.hostInfo.disk_total} GB`,
},
];
return html`
<ha-card header="System Metrics">
<div class="card-content">
${metrics.map((metric) =>
this._renderMetric(
metric.description,
metric.value ?? 0,
metric.tooltip
)
)}
</div>
</ha-card>
`;
}
protected firstUpdated(): void {
this._loadData();
}
private _renderMetric(
description: string,
value: number,
tooltip?: string
): TemplateResult {
const roundedValue = roundWithOneDecimal(value);
return html`<ha-settings-row>
<span slot="heading">
${description}
</span>
<div slot="description" title="${tooltip ?? ""}">
<span class="value">
${roundedValue}%
</span>
<ha-bar
class="${classMap({
"target-warning": roundedValue > 50,
"target-critical": roundedValue > 85,
})}"
.value=${value}
></ha-bar>
</div>
</ha-settings-row>`;
}
private _getUsedSpace = memoizeOne((hostInfo: HassioHostInfo) =>
roundWithOneDecimal(
getValueInPercentage(hostInfo.disk_used, 0, hostInfo.disk_total)
)
);
private async _loadData(): Promise<void> {
const [supervisor, core] = await Promise.all([
fetchHassioStats(this.hass, "supervisor"),
fetchHassioStats(this.hass, "core"),
]);
this._supervisorMetrics = supervisor;
this._coreMetrics = core;
}
static get styles(): CSSResult[] {
return [
haStyle,
hassioStyle,
css`
ha-card {
height: 100%;
justify-content: space-between;
flex-direction: column;
display: flex;
}
ha-settings-row {
padding: 0;
height: 54px;
width: 100%;
}
ha-settings-row > div[slot="description"] {
white-space: normal;
color: var(--secondary-text-color);
display: flex;
justify-content: space-between;
}
ha-bar {
--ha-bar-primary-color: var(
--hassio-bar-ok-color,
var(--success-color)
);
}
.target-warning {
--ha-bar-primary-color: var(
--hassio-bar-warning-color,
var(--warning-color)
);
}
.target-critical {
--ha-bar-primary-color: var(
--hassio-bar-critical-color,
var(--error-color)
);
}
.value {
width: 42px;
padding-right: 4px;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"hassio-system-metrics": HassioSystemMetrics;
}
}

View File

@@ -23,6 +23,7 @@ import { hassioStyle } from "../resources/hassio-style";
import "./hassio-host-info";
import "./hassio-supervisor-info";
import "./hassio-supervisor-log";
import "./hassio-system-metrics";
@customElement("hassio-system")
class HassioSystem extends LitElement {
@@ -64,6 +65,10 @@ class HassioSystem extends LitElement {
.hostInfo=${this.hostInfo}
.hassOsInfo=${this.hassOsInfo}
></hassio-host-info>
<hassio-system-metrics
.hass=${this.hass}
.hostInfo=${this.hostInfo}
></hassio-system-metrics>
</div>
<hassio-supervisor-log .hass=${this.hass}></hassio-supervisor-log>
</div>

View File

@@ -28,24 +28,24 @@
"@fullcalendar/daygrid": "5.1.0",
"@fullcalendar/interaction": "5.1.0",
"@fullcalendar/list": "5.1.0",
"@material/chips": "=8.0.0-canary.096a7a066.0",
"@material/circular-progress": "=8.0.0-canary.a78ceb112.0",
"@material/mwc-button": "^0.18.0",
"@material/mwc-checkbox": "^0.18.0",
"@material/mwc-dialog": "^0.18.0",
"@material/mwc-fab": "^0.18.0",
"@material/mwc-formfield": "^0.18.0",
"@material/mwc-icon-button": "^0.18.0",
"@material/mwc-list": "^0.18.0",
"@material/mwc-menu": "^0.18.0",
"@material/mwc-radio": "^0.18.0",
"@material/mwc-ripple": "^0.18.0",
"@material/mwc-switch": "^0.18.0",
"@material/mwc-tab": "^0.18.0",
"@material/mwc-tab-bar": "^0.18.0",
"@material/top-app-bar": "=8.0.0-canary.096a7a066.0",
"@mdi/js": "5.5.55",
"@mdi/svg": "5.5.55",
"@material/chips": "=8.0.0-canary.774dcfc8e.0",
"@material/mwc-button": "^0.19.0",
"@material/mwc-checkbox": "^0.19.0",
"@material/mwc-circular-progress": "^0.19.0",
"@material/mwc-dialog": "^0.19.0",
"@material/mwc-fab": "^0.19.0",
"@material/mwc-formfield": "^0.19.0",
"@material/mwc-icon-button": "^0.19.0",
"@material/mwc-list": "^0.19.0",
"@material/mwc-menu": "^0.19.0",
"@material/mwc-radio": "^0.19.0",
"@material/mwc-ripple": "^0.19.0",
"@material/mwc-switch": "^0.19.0",
"@material/mwc-tab": "^0.19.0",
"@material/mwc-tab-bar": "^0.19.0",
"@material/top-app-bar": "=8.0.0-canary.774dcfc8e.0",
"@mdi/js": "5.6.55",
"@mdi/svg": "5.6.55",
"@polymer/app-layout": "^3.0.2",
"@polymer/app-route": "^3.0.2",
"@polymer/app-storage": "^3.0.2",
@@ -88,11 +88,11 @@
"chartjs-chart-timeline": "^0.3.0",
"codemirror": "^5.49.0",
"comlink": "^4.3.0",
"core-js": "^3.6.5",
"cpx": "^1.5.0",
"cropperjs": "^1.5.7",
"deep-clone-simple": "^1.1.1",
"deep-freeze": "^0.0.1",
"es6-object-assign": "^1.1.0",
"fecha": "^4.2.0",
"fuse.js": "^6.0.0",
"google-timezones-json": "^1.0.2",
@@ -103,8 +103,8 @@
"js-yaml": "^3.13.1",
"leaflet": "^1.4.0",
"leaflet-draw": "^1.0.4",
"lit-element": "^2.3.1",
"lit-html": "^1.2.1",
"lit-element": "^2.4.0",
"lit-html": "^1.3.0",
"lit-virtualizer": "^0.4.2",
"marked": "^1.1.1",
"mdn-polyfills": "^5.16.0",
@@ -112,6 +112,7 @@
"node-vibrant": "^3.1.5",
"proxy-polyfill": "^0.3.1",
"punycode": "^2.1.1",
"qrcode": "^1.4.4",
"regenerator-runtime": "^0.13.2",
"resize-observer-polyfill": "^1.5.1",
"roboto-fontface": "^0.10.0",
@@ -128,22 +129,23 @@
"xss": "^1.0.6"
},
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/plugin-external-helpers": "^7.8.3",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-decorators": "^7.8.3",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
"@babel/plugin-proposal-object-rest-spread": "^7.9.5",
"@babel/plugin-proposal-optional-chaining": "^7.9.0",
"@babel/core": "^7.11.6",
"@babel/plugin-external-helpers": "^7.10.4",
"@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/plugin-proposal-decorators": "^7.10.5",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
"@babel/plugin-proposal-object-rest-spread": "^7.11.0",
"@babel/plugin-proposal-optional-chaining": "^7.11.0",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.9.5",
"@babel/preset-typescript": "^7.9.0",
"@babel/plugin-syntax-import-meta": "^7.10.4",
"@babel/preset-env": "^7.11.5",
"@babel/preset-typescript": "^7.10.4",
"@rollup/plugin-commonjs": "^11.1.0",
"@rollup/plugin-json": "^4.0.3",
"@rollup/plugin-node-resolve": "^7.1.3",
"@rollup/plugin-replace": "^2.3.2",
"@types/chai": "^4.1.7",
"@types/chromecast-caf-receiver": "^3.0.12",
"@types/chromecast-caf-receiver": "^5.0.11",
"@types/codemirror": "^0.0.97",
"@types/hls.js": "^0.12.3",
"@types/js-yaml": "^3.12.1",
@@ -154,8 +156,8 @@
"@types/mocha": "^7.0.2",
"@types/resize-observer-browser": "^0.1.3",
"@types/webspeechapi": "^0.0.29",
"@typescript-eslint/eslint-plugin": "^2.28.0",
"@typescript-eslint/parser": "^2.28.0",
"@typescript-eslint/eslint-plugin": "^4.4.0",
"@typescript-eslint/parser": "^4.4.0",
"babel-loader": "^8.1.0",
"chai": "^4.2.0",
"del": "^4.0.0",
@@ -180,7 +182,7 @@
"html-minifier": "^4.0.0",
"husky": "^1.3.1",
"lint-staged": "^8.1.5",
"lit-analyzer": "^1.2.0",
"lit-analyzer": "^1.2.1",
"lodash.template": "^4.5.0",
"magic-string": "^0.25.7",
"map-stream": "^0.0.7",
@@ -201,29 +203,24 @@
"source-map-url": "^0.4.0",
"systemjs": "^6.3.2",
"terser-webpack-plugin": "^3.0.6",
"ts-lit-plugin": "^1.2.0",
"ts-lit-plugin": "^1.2.1",
"ts-mocha": "^7.0.0",
"typescript": "^3.8.3",
"typescript": "^4.0.3",
"vinyl-buffer": "^1.0.1",
"vinyl-source-stream": "^2.0.0",
"webpack": "^4.40.2",
"webpack-cli": "^3.3.9",
"webpack": "5.0.0-rc.3",
"webpack-cli": "4.0.0-rc.0",
"webpack-dev-server": "^3.10.3",
"webpack-manifest-plugin": "^2.0.4",
"workbox-build": "^5.1.3",
"worker-plugin": "^4.0.3"
"webpack-manifest-plugin": "3.0.0-rc.0",
"workbox-build": "^5.1.3"
},
"_comment": "Polymer fixed to 3.1 because 3.2 throws on logbook page",
"_comment_2": "Fix in https://github.com/Polymer/polymer/pull/5569",
"resolutions": {
"@webcomponents/webcomponentsjs": "^2.2.10",
"@polymer/polymer": "3.1.0",
"lit-html": "1.2.1",
"lit-element": "2.3.1",
"@material/animation": "8.0.0-canary.096a7a066.0",
"@material/base": "8.0.0-canary.096a7a066.0",
"@material/feature-targeting": "8.0.0-canary.096a7a066.0",
"@material/theme": "8.0.0-canary.096a7a066.0"
"lit-html": "1.3.0",
"lit-element": "2.4.0"
},
"main": "src/home-assistant.js",
"husky": {

View File

@@ -24,7 +24,6 @@
"filesToIgnore": [
"**/*.html",
"**/src/panels/config/js/**/*.js",
"**/ha-paper-slider.js",
"**/ha-iconset-svg.js",
"**/ha-script-editor.js",
"**/ha-automation-editor.js",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 B

After

Width:  |  Height:  |  Size: 258 B

View File

@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name="home-assistant-frontend",
version="20200917.0",
version="20201001.0",
description="The Home Assistant frontend",
url="https://github.com/home-assistant/home-assistant-polymer",
author="The Home Assistant Authors",

View File

@@ -200,7 +200,7 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
private _redirect(authCode: string) {
// OAuth 2: 3.1.2 we need to retain query component of a redirect URI
let url = this.redirectUri!!;
let url = this.redirectUri!;
if (!url.includes("?")) {
url += "?";
} else if (!url.endsWith("&")) {

View File

@@ -7,6 +7,66 @@
/** Icon to use when no icon specified for domain. */
export const DEFAULT_DOMAIN_ICON = "hass:bookmark";
/** Icons for each domain */
export const FIXED_DOMAIN_ICONS = {
alert: "hass:alert",
alexa: "hass:amazon-alexa",
air_quality: "hass:air-filter",
automation: "hass:robot",
calendar: "hass:calendar",
camera: "hass:video",
climate: "hass:thermostat",
configurator: "hass:cog",
conversation: "hass:text-to-speech",
counter: "hass:counter",
device_tracker: "hass:account",
fan: "hass:fan",
google_assistant: "hass:google-assistant",
group: "hass:google-circles-communities",
homeassistant: "hass:home-assistant",
homekit: "hass:home-automation",
image_processing: "hass:image-filter-frames",
input_boolean: "hass:toggle-switch-outline",
input_datetime: "hass:calendar-clock",
input_number: "hass:ray-vertex",
input_select: "hass:format-list-bulleted",
input_text: "hass:form-textbox",
light: "hass:lightbulb",
mailbox: "hass:mailbox",
notify: "hass:comment-alert",
persistent_notification: "hass:bell",
person: "hass:account",
plant: "hass:flower",
proximity: "hass:apple-safari",
remote: "hass:remote",
scene: "hass:palette",
script: "hass:script-text",
sensor: "hass:eye",
simple_alarm: "hass:bell",
sun: "hass:white-balance-sunny",
switch: "hass:flash",
timer: "hass:timer-outline",
updater: "hass:cloud-upload",
vacuum: "hass:robot-vacuum",
water_heater: "hass:thermometer",
weather: "hass:weather-cloudy",
zone: "hass:map-marker-radius",
};
export const FIXED_DEVICE_CLASS_ICONS = {
current: "hass:current-ac",
energy: "hass:flash",
humidity: "hass:water-percent",
illuminance: "hass:brightness-5",
temperature: "hass:thermometer",
pressure: "hass:gauge",
power: "hass:flash",
power_factor: "hass:angle-acute",
signal_strength: "hass:wifi",
timestamp: "hass:clock",
voltage: "hass:sine-wave",
};
/** Domains that have a state card. */
export const DOMAINS_WITH_CARD = [
"climate",
@@ -63,6 +123,10 @@ export const DOMAINS_MORE_INFO_NO_HISTORY = ["camera", "configurator", "scene"];
/** States that we consider "off". */
export const STATES_OFF = ["closed", "locked", "off"];
/** Binary States */
export const BINARY_STATE_ON = "on";
export const BINARY_STATE_OFF = "off";
/** Domains where we allow toggle in Lovelace. */
export const DOMAINS_TOGGLE = new Set([
"fan",

View File

@@ -38,13 +38,11 @@ export default function relativeTime(
roundedDelta = Math.round(delta);
}
const timeDesc = localize(
`ui.components.relative_time.duration.${unit}`,
return localize(
options.includeTense === false
? `ui.components.relative_time.duration.${unit}`
: `ui.components.relative_time.${tense}_duration.${unit}`,
"count",
roundedDelta
);
return options.includeTense === false
? timeDesc
: localize(`ui.components.relative_time.${tense}`, "time", timeDesc);
}

View File

@@ -2,9 +2,9 @@ import { HassEntity } from "home-assistant-js-websocket";
/** Return an icon representing a binary sensor state. */
export const binarySensorIcon = (state: HassEntity) => {
const is_off = state.state && state.state === "off";
switch (state.attributes.device_class) {
export const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {
const is_off = state === "off";
switch (stateObj?.attributes.device_class) {
case "battery":
return is_off ? "hass:battery" : "hass:battery-outline";
case "battery_charging":
@@ -17,8 +17,9 @@ export const binarySensorIcon = (state: HassEntity) => {
return is_off ? "hass:door-closed" : "hass:door-open";
case "garage_door":
return is_off ? "hass:garage" : "hass:garage-open";
case "gas":
case "power":
return is_off ? "hass:power-plug-off" : "hass:power-plug";
case "gas":
case "problem":
case "safety":
case "smoke":

View File

@@ -9,14 +9,17 @@ import { computeStateDomain } from "./compute_state_domain";
export const computeStateDisplay = (
localize: LocalizeFunc,
stateObj: HassEntity,
language: string
language: string,
state?: string
): string => {
if (stateObj.state === UNKNOWN || stateObj.state === UNAVAILABLE) {
return localize(`state.default.${stateObj.state}`);
const compareState = state !== undefined ? state : stateObj.state;
if (compareState === UNKNOWN || compareState === UNAVAILABLE) {
return localize(`state.default.${compareState}`);
}
if (stateObj.attributes.unit_of_measurement) {
return `${stateObj.state} ${stateObj.attributes.unit_of_measurement}`;
return `${compareState} ${stateObj.attributes.unit_of_measurement}`;
}
const domain = computeStateDomain(stateObj);
@@ -56,7 +59,7 @@ export const computeStateDisplay = (
}
if (domain === "humidifier") {
if (stateObj.state === "on" && stateObj.attributes.humidity) {
if (compareState === "on" && stateObj.attributes.humidity) {
return `${stateObj.attributes.humidity}%`;
}
}
@@ -65,11 +68,11 @@ export const computeStateDisplay = (
// Return device class translation
(stateObj.attributes.device_class &&
localize(
`component.${domain}.state.${stateObj.attributes.device_class}.${stateObj.state}`
`component.${domain}.state.${stateObj.attributes.device_class}.${compareState}`
)) ||
// Return default translation
localize(`component.${domain}.state._.${stateObj.state}`) ||
localize(`component.${domain}.state._.${compareState}`) ||
// We don't know! Return the raw state.
stateObj.state
compareState
);
};

View File

@@ -1,13 +1,12 @@
/** Return an icon representing a cover state. */
import { HassEntity } from "home-assistant-js-websocket";
import { domainIcon } from "./domain_icon";
export const coverIcon = (state: HassEntity): string => {
const open = state.state !== "closed";
export const coverIcon = (state?: string, stateObj?: HassEntity): string => {
const open = state !== "closed";
switch (state.attributes.device_class) {
switch (stateObj?.attributes.device_class) {
case "garage":
switch (state.state) {
switch (state) {
case "opening":
return "hass:arrow-up-box";
case "closing":
@@ -18,7 +17,7 @@ export const coverIcon = (state: HassEntity): string => {
return "hass:garage-open";
}
case "gate":
switch (state.state) {
switch (state) {
case "opening":
case "closing":
return "hass:gate-arrow-right";
@@ -32,7 +31,7 @@ export const coverIcon = (state: HassEntity): string => {
case "damper":
return open ? "hass:circle" : "hass:circle-slice-8";
case "shutter":
switch (state.state) {
switch (state) {
case "opening":
return "hass:arrow-up-box";
case "closing":
@@ -44,7 +43,7 @@ export const coverIcon = (state: HassEntity): string => {
}
case "blind":
case "curtain":
switch (state.state) {
switch (state) {
case "opening":
return "hass:arrow-up-box";
case "closing":
@@ -55,7 +54,7 @@ export const coverIcon = (state: HassEntity): string => {
return "hass:blinds-open";
}
case "window":
switch (state.state) {
switch (state) {
case "opening":
return "hass:arrow-up-box";
case "closing":
@@ -65,7 +64,16 @@ export const coverIcon = (state: HassEntity): string => {
default:
return "hass:window-open";
}
}
switch (state) {
case "opening":
return "hass:arrow-up-box";
case "closing":
return "hass:arrow-down-box";
case "closed":
return "hass:window-closed";
default:
return domainIcon("cover", state.state);
return "hass:window-open";
}
};

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