From ef18f9eac99dd8b5bc04fc1349ce4cde9f46c946 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 21 Mar 2019 14:56:57 -0700 Subject: [PATCH 01/29] Upgrade lit element to 2.1.0 (#2990) * UPgrade lit element * Fix yarn resolving * Upgrade mwc --- package.json | 6 +-- yarn.lock | 136 ++++++++++++++++++++++++++++----------------------- 2 files changed, 77 insertions(+), 65 deletions(-) diff --git a/package.json b/package.json index 062911b143..618a216359 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,8 @@ "author": "Paulus Schoutsen (http://paulusschoutsen.nl)", "license": "Apache-2.0", "dependencies": { - "@material/mwc-button": "^0.3.6", - "@material/mwc-ripple": "^0.3.6", + "@material/mwc-button": "^0.4.0", + "@material/mwc-ripple": "^0.4.0", "@mdi/svg": "^3.0.39", "@polymer/app-layout": "^3.0.1", "@polymer/app-localize-behavior": "^3.0.1", @@ -79,7 +79,7 @@ "jquery": "^3.3.1", "js-yaml": "^3.12.0", "leaflet": "^1.3.4", - "lit-element": "^2.0.0", + "lit-element": "^2.1.0", "lit-html": "^1.0.0", "marked": "^0.6.0", "mdn-polyfills": "^5.12.0", diff --git a/yarn.lock b/yarn.lock index 8d5ab06c8a..0b82218a5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -728,35 +728,42 @@ log-update "^2.3.0" strip-ansi "^3.0.1" -"@material/animation@^0.40.1": - version "0.40.1" - resolved "https://registry.yarnpkg.com/@material/animation/-/animation-0.40.1.tgz#c5ff31e7d7e17324a0045e889d3530b150b9fcec" - integrity sha512-HtxFUw04EHg4S6pXfTA3Z0wKxnNDNcDhe1Np2Y2geo+lAk2Hb7m8yCL/GaL9o2I/eRYsgUXC0U7+Mk74GCz3zw== +"@material/animation@^0.41.0": + version "0.41.0" + resolved "https://registry.yarnpkg.com/@material/animation/-/animation-0.41.0.tgz#315b45b32e1aeebee8a4cf555b8ad52076d09ddd" + integrity sha512-yYAwJbX3Q2AFd4dr6IYOsWLQy2HN8zWOFVl9AbUXunjzTfJCa/ecfXCriaT6qkmoNoHeTdJHRrsQJZC5GsPvzA== -"@material/base@^0.40.1": - version "0.40.1" - resolved "https://registry.yarnpkg.com/@material/base/-/base-0.40.1.tgz#a0d8e19cee98dae0f96dbf0887a14b3f7acd2aac" - integrity sha512-vrbOK8hONVCYgURQ9h7nkXvMdYnZVVNmAfFFijF8fbWQdwnoPcNTdqV6RoQlhBEqHYHQqLNfdUDlznAPKLclGQ== +"@material/base@^0.41.0": + version "0.41.0" + resolved "https://registry.yarnpkg.com/@material/base/-/base-0.41.0.tgz#badadce711b4c25b1eb889a5e7581e32cd07c421" + integrity sha512-tEyzwBRu3d1H120SfKsDVYZHcqT5lKohh/7cWKR93aAaPDkSvjpKJIjyu2yuSkjpDduVZGzVocYbOvhUKhhzXQ== -"@material/button@^0.40.0": - version "0.40.1" - resolved "https://registry.yarnpkg.com/@material/button/-/button-0.40.1.tgz#b5a8657f7d3783d7fc0936f95d0187bdb0319eae" - integrity sha512-xLNjq9zySnpZAP4UynyeXnnlLXf3iIA/6ilecwgF4d2ooUmNXcRdlRa8wGYT36JHsCfsP3AeZOjoTZUcmaiejw== +"@material/button@^0.44.0": + version "0.44.1" + resolved "https://registry.yarnpkg.com/@material/button/-/button-0.44.1.tgz#2a0bc0e6961128ace81e050770695c4aaad7f3bd" + integrity sha512-+eI0nI2zkxZOanPfeWzZPoQDbv2NqgUhUhPxERKoXEqkyJIne7gWRYMHqHjKPctsD2xmzgqGmGCLcrvhgFZ+FQ== dependencies: - "@material/elevation" "^0.40.1" - "@material/ripple" "^0.40.1" - "@material/rtl" "^0.40.1" - "@material/shape" "^0.40.1" - "@material/theme" "^0.40.1" - "@material/typography" "^0.40.1" + "@material/elevation" "^0.44.1" + "@material/feature-targeting" "^0.44.1" + "@material/ripple" "^0.44.1" + "@material/rtl" "^0.42.0" + "@material/shape" "^0.44.1" + "@material/theme" "^0.43.0" + "@material/typography" "^0.44.1" -"@material/elevation@^0.40.1": - version "0.40.1" - resolved "https://registry.yarnpkg.com/@material/elevation/-/elevation-0.40.1.tgz#beb17eb90bde94459c41cd826c2de13f13b10b25" - integrity sha512-VD9ii90WzI+t4df08A9hQIsYLH/N+85a2Mqo10CNVZLZYW5fDOwFH/h7553aNoAuSHKPcGCLdyav9J9oC6TSaQ== +"@material/elevation@^0.44.1": + version "0.44.1" + resolved "https://registry.yarnpkg.com/@material/elevation/-/elevation-0.44.1.tgz#19efa293e195b00141711899e3c3fde6a3670454" + integrity sha512-Gr2x/FHysM4ty7sctLPT48pw7YItLZvhXsB4ZzXpdhuy7QshxllBW9NGlAMffzrmNu16MTl3ouGzbhArUYz4jw== dependencies: - "@material/animation" "^0.40.1" - "@material/theme" "^0.40.1" + "@material/animation" "^0.41.0" + "@material/feature-targeting" "^0.44.1" + "@material/theme" "^0.43.0" + +"@material/feature-targeting@^0.44.1": + version "0.44.1" + resolved "https://registry.yarnpkg.com/@material/feature-targeting/-/feature-targeting-0.44.1.tgz#afafc80294e5efab94bee31a187273d43d34979a" + integrity sha512-90cc7njn4aHbH9UxY8qgZth1W5JgOgcEdWdubH1t7sFkwqFxS5g3zgxSBt46TygFBVIXNZNq35Xmg80wgqO7Pg== "@material/mwc-base@^0.3.6": version "0.3.6" @@ -766,15 +773,15 @@ lit-element "^2.0.0-rc.2" lit-html "^1.0.0-rc.2" -"@material/mwc-button@^0.3.6": - version "0.3.6" - resolved "https://registry.yarnpkg.com/@material/mwc-button/-/mwc-button-0.3.6.tgz#86a05fe27ad365fd5f7d98d4840ef0def5f72096" - integrity sha512-ueIyVqSklgMFvlVJFszzlQSwDBvCQtM7FXWBpMGPiUFbzyESb1Wy3e7K0RaeHWzWolUrq9INl9Tt+15i1hnBhA== +"@material/mwc-button@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@material/mwc-button/-/mwc-button-0.4.0.tgz#e1e4b23ced20a641e04ea7c35fe36e4aa190879e" + integrity sha512-308Lrol26bgauUwzSo/RzW9o6Aglff6YTpxsbNi3+bR4FIh20MpYxo6umKG8ix9xhezZ7YQFD0PR3JLLRUZJEg== dependencies: - "@material/button" "^0.40.0" + "@material/button" "^0.44.0" "@material/mwc-base" "^0.3.6" "@material/mwc-icon" "^0.3.6" - "@material/mwc-ripple" "^0.3.6" + "@material/mwc-ripple" "^0.4.0" "@material/mwc-icon@^0.3.6": version "0.3.6" @@ -783,43 +790,48 @@ dependencies: "@material/mwc-base" "^0.3.6" -"@material/mwc-ripple@^0.3.6": - version "0.3.6" - resolved "https://registry.yarnpkg.com/@material/mwc-ripple/-/mwc-ripple-0.3.6.tgz#27d7748e6d1cf45e2ce299d0786440217bf0b3c9" - integrity sha512-fCqIoHX5M7qW2iOitEIlJF0TBl1IhzHpXb1lroXBv1JlGGYWWSd5m+v7ZSJU3Apc8s/IkPsDDCk1vSHv6VyOwA== +"@material/mwc-ripple@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@material/mwc-ripple/-/mwc-ripple-0.4.0.tgz#42b3b3c17e55d576deceb20e955f87e68d2615bb" + integrity sha512-KaNR4QSleKYNb97drVqM+TEmxgR7/ClJSXeK1rGcbvDAaE+3vx5wlPW1Ems23eLqSsFNntgy43wPbRkMjogIew== dependencies: "@material/mwc-base" "^0.3.6" - "@material/ripple" "^0.40.0" + "@material/ripple" "^0.44.0" lit-html "^1.0.0" -"@material/ripple@^0.40.0", "@material/ripple@^0.40.1": - version "0.40.1" - resolved "https://registry.yarnpkg.com/@material/ripple/-/ripple-0.40.1.tgz#57cbc689303b48282229cb9b62556af7442e852a" - integrity sha512-sndeTS4VHa0v1UGj7MNcxMCuO9LJ1DjoL1EjE6BH3Lm3M1MnXJHdsBo2CgPbU/FI84tt6+eyHGOYPdPrEDJhCA== +"@material/ripple@^0.44.0", "@material/ripple@^0.44.1": + version "0.44.1" + resolved "https://registry.yarnpkg.com/@material/ripple/-/ripple-0.44.1.tgz#79cb2ddf1f998498d877d3e3c46b50fed6f13b01" + integrity sha512-prJ1p3bR+GvwAtJgtdeIixsnRVApN3bizGnX7upKoqxsqbBDHj84JxaO8EsG9bjruG/LJu8Fb6WKKdIp2oXHTA== dependencies: - "@material/animation" "^0.40.1" - "@material/base" "^0.40.1" - "@material/theme" "^0.40.1" + "@material/animation" "^0.41.0" + "@material/base" "^0.41.0" + "@material/feature-targeting" "^0.44.1" + "@material/theme" "^0.43.0" -"@material/rtl@^0.40.1": - version "0.40.1" - resolved "https://registry.yarnpkg.com/@material/rtl/-/rtl-0.40.1.tgz#5b0d973e3c6f8e2ea3656c06ada37ba2fedfa206" - integrity sha512-Pk6Iw1/KrhWZoZtkDsPMDUW0bm7Z1zeXb3MTQRCFmjf1wU5cRxgOTtuoZLcJqlcKGppLAzJL/TJV3E7KEiuL0A== +"@material/rtl@^0.42.0": + version "0.42.0" + resolved "https://registry.yarnpkg.com/@material/rtl/-/rtl-0.42.0.tgz#1836e78186c2d8b996f6fbf97adab203535335bc" + integrity sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w== -"@material/shape@^0.40.1": - version "0.40.1" - resolved "https://registry.yarnpkg.com/@material/shape/-/shape-0.40.1.tgz#bd4224902896c3d45fab353d788fe6c4866483a8" - integrity sha512-o1pw5+s/jWqsKbUAkCCaEcB8XLqJ4FlZhYfSvxZ88WRw9zoWOt9iQMMP82wLWhUX1DSzpNRI8BAD7aNLK6yRlA== +"@material/shape@^0.44.1": + version "0.44.1" + resolved "https://registry.yarnpkg.com/@material/shape/-/shape-0.44.1.tgz#ff4d5d42b07c5781306677bffee43234b756ea8e" + integrity sha512-8mCDQmyTEhDK+HX8Tap2Lc82QlVySlXU8zDCNkWoIn1ge+UnRezSDjE4y4P1ABegN5PrkJZPartuQ1U0ttIYXw== + dependencies: + "@material/feature-targeting" "^0.44.1" -"@material/theme@^0.40.1": - version "0.40.1" - resolved "https://registry.yarnpkg.com/@material/theme/-/theme-0.40.1.tgz#3cc3f1bf87ee9581df03e347a1979e53ae617221" - integrity sha512-cH1CsGIDisEQ2oroZhLTypV0Ir00x3WIwFXnPo7qv3832tuIDkZY623U3rUax6KNPz4Hh1j0tNpTwgrNZwvwWA== +"@material/theme@^0.43.0": + version "0.43.0" + resolved "https://registry.yarnpkg.com/@material/theme/-/theme-0.43.0.tgz#6d9fa113c82e841817882172c152d60d2d203ca6" + integrity sha512-/zndZL6EihI18v2mYd4O8xvOBAAXmLeHyHVK28LozSAaJ9okQgD25wq5Ktk95oMTmPIC+rH66KcK6371ivNk8g== -"@material/typography@^0.40.1": - version "0.40.1" - resolved "https://registry.yarnpkg.com/@material/typography/-/typography-0.40.1.tgz#68ecb767f7c54ca2f4053cccdd1c4a0198e60f9b" - integrity sha512-LkW2tAsId8zGKxGA5VIFXV/D1h4vCHQIuALRMaDpHbNGffgr2ubtJNvCh2EQkm19MTv4igVLEjn1Svh0dXcTpA== +"@material/typography@^0.44.1": + version "0.44.1" + resolved "https://registry.yarnpkg.com/@material/typography/-/typography-0.44.1.tgz#a94f01172f9122180bc2ce0aa55658183a35590d" + integrity sha512-wMXHusg+Lp5Fdgoj3m0c+Lt6GCeGSh3EPRtQ1TQ2bwdBa0et2FqBaQRgXoq3tVmr0O/7unTfa0DoXlh4nVp1wA== + dependencies: + "@material/feature-targeting" "^0.44.1" "@mdi/svg@^3.0.39": version "3.3.92" @@ -8530,10 +8542,10 @@ listr@^0.14.2: p-map "^2.0.0" rxjs "^6.3.3" -lit-element@^2.0.0, lit-element@^2.0.0-rc.2: - version "2.0.1" - resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-2.0.1.tgz#9ec5871d3b64487f432c7c071df80ef031d7091b" - integrity sha512-2bu3B2ZYUZgntvOgu3i5mRK8geo45CLUwxwJEYK54hyednoJasjiTZPB13NBg1D+hNM2JfmWTWJnh1QEUQv7zw== +lit-element@^2.0.0-rc.2, lit-element@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-2.1.0.tgz#85bc3f1da0227f4b13de8a1be978229b9fa327e9" + integrity sha512-0z/KHm1xZweivfOVRr8AKR06+D3k02u15m9s4jkuRdnGe5wfmEwePzrQQBsSZNILdnfJvfo3TJOeGhBCVZaPbw== dependencies: lit-html "^1.0.0" From 20ee3452dc2371f1415cfaf9f6d4eaa19c0be47d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 22 Mar 2019 10:38:40 -0700 Subject: [PATCH 02/29] Fix sidebar when user is slow to load (#2993) --- src/components/ha-sidebar.ts | 18 ++++++------------ src/types.ts | 2 +- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/components/ha-sidebar.ts b/src/components/ha-sidebar.ts index 48ebff59e5..98d0a5e097 100644 --- a/src/components/ha-sidebar.ts +++ b/src/components/ha-sidebar.ts @@ -26,19 +26,13 @@ const computePanels = (hass: HomeAssistant) => { if (!panels) { return []; } - const isAdmin = hass.user.is_admin; + const sortValue = { map: 1, logbook: 2, history: 3, }; - const result: Panel[] = []; - - Object.values(panels).forEach((panel) => { - if (panel.title && (panel.component_name !== "config" || isAdmin)) { - result.push(panel); - } - }); + const result: Panel[] = Object.values(panels).filter((panel) => panel.title); result.sort((a, b) => { const aBuiltIn = a.component_name in sortValue; @@ -133,9 +127,8 @@ class HaSidebar extends LitElement { : html``} - ${!hass.user.is_admin - ? "" - : html` + ${hass.user && hass.user.is_admin + ? html`
@@ -192,7 +185,8 @@ class HaSidebar extends LitElement {
- `} + ` + : ""} `; } diff --git a/src/types.ts b/src/types.ts index 317f12f2bc..099fe66574 100644 --- a/src/types.ts +++ b/src/types.ts @@ -137,7 +137,7 @@ export interface HomeAssistant { dockedSidebar: boolean; moreInfoEntityId: string; - user: CurrentUser; + user?: CurrentUser; callService: ( domain: string, service: string, From 6bf9ea5699a63ec4b2ec3cd69e73deab9086bdd3 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Fri, 22 Mar 2019 13:55:52 -0500 Subject: [PATCH 03/29] =?UTF-8?q?=E2=9C=A8=20entity-button=20show/hide=20i?= =?UTF-8?q?con/name=20(#2936)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lovelace/cards/hui-entity-button-card.ts | 38 +++++++++++++------ .../hui-entity-button-card-editor.ts | 31 ++++++++++++++- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/panels/lovelace/cards/hui-entity-button-card.ts b/src/panels/lovelace/cards/hui-entity-button-card.ts index cc0b7fdfbe..25b79be422 100644 --- a/src/panels/lovelace/cards/hui-entity-button-card.ts +++ b/src/panels/lovelace/cards/hui-entity-button-card.ts @@ -31,7 +31,9 @@ import { DOMAINS_TOGGLE } from "../../../common/const"; export interface Config extends LovelaceCardConfig { entity: string; name?: string; + snow_name?: boolean; icon?: string; + show_icon?: boolean; theme?: string; tap_action?: ActionConfig; hold_action?: ActionConfig; @@ -48,6 +50,8 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard { return { tap_action: { action: "toggle" }, hold_action: { action: "more-info" }, + show_icon: true, + show_name: true, }; } @@ -68,6 +72,8 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard { theme: "default", hold_action: { action: "more-info" }, ...config, + show_icon: true, + show_name: true, }; if (DOMAINS_TOGGLE.has(computeDomain(config.entity))) { @@ -126,18 +132,26 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard { @ha-hold="${this._handleHold}" .longPress="${longPress()}" > - - - ${this._config.name || computeStateName(stateObj)} - + ${this._config.show_icon + ? html` + + ` + : ""} + ${this._config.show_name + ? html` + + ${this._config.name || computeStateName(stateObj)} + + ` + : ""} `; diff --git a/src/panels/lovelace/editor/config-elements/hui-entity-button-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-entity-button-card-editor.ts index 7318a1f270..93ecd9498a 100644 --- a/src/panels/lovelace/editor/config-elements/hui-entity-button-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-entity-button-card-editor.ts @@ -28,7 +28,9 @@ const cardConfigStruct = struct({ type: "string", entity: "string?", name: "string?", + show_name: "boolean?", icon: "string?", + show_icon: "boolean?", tap_action: struct.optional(actionConfigStruct), hold_action: struct.optional(actionConfigStruct), theme: "string?", @@ -54,10 +56,18 @@ export class HuiEntityButtonCardEditor extends LitElement return this._config!.name || ""; } + get _show_name(): boolean { + return this._config!.show_name || true; + } + get _icon(): string { return this._config!.icon || ""; } + get _show_icon(): boolean { + return this._config!.show_icon || true; + } + get _tap_action(): ActionConfig { return this._config!.tap_action || { action: "more-info" }; } @@ -101,6 +111,20 @@ export class HuiEntityButtonCardEditor extends LitElement @value-changed="${this._valueChanged}" > +
+ Show Name? + Show Icon? +
Date: Fri, 22 Mar 2019 14:42:30 -0500 Subject: [PATCH 04/29] Fix typo (#2999) Fixes https://github.com/home-assistant/home-assistant-polymer/issues/2997 --- src/panels/lovelace/cards/hui-plant-status-card.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/lovelace/cards/hui-plant-status-card.ts b/src/panels/lovelace/cards/hui-plant-status-card.ts index c31d5ce90a..0304e9d307 100644 --- a/src/panels/lovelace/cards/hui-plant-status-card.ts +++ b/src/panels/lovelace/cards/hui-plant-status-card.ts @@ -91,7 +91,7 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard { style="background-image:url(${stateObj.attributes.entity_picture})" >
- ${this._config.title || computeStateName(stateObj)} + ${this._config.name || computeStateName(stateObj)}
From 86940f4d42f16f3622b54bd110feda2b6e789864 Mon Sep 17 00:00:00 2001 From: heckler Date: Fri, 22 Mar 2019 22:06:17 -0300 Subject: [PATCH 05/29] Edited the delete message on removeEntry to match the resource type (#3000) --- src/panels/config/person/ha-config-person.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/panels/config/person/ha-config-person.ts b/src/panels/config/person/ha-config-person.ts index bc9ea04ca2..470e9de8b5 100644 --- a/src/panels/config/person/ha-config-person.ts +++ b/src/panels/config/person/ha-config-person.ts @@ -180,9 +180,9 @@ class HaConfigPerson extends LitElement { }, removeEntry: async () => { if ( - !confirm(`Are you sure you want to delete this area? + !confirm(`Are you sure you want to delete this person? -All devices in this area will become unassigned.`) +All devices belonging to this person will become unassigned.`) ) { return false; } From 45189c91634513a8c12e3ac74ce3c8eaa3317c2f Mon Sep 17 00:00:00 2001 From: yosilevy <37745463+yosilevy@users.noreply.github.com> Date: Sat, 23 Mar 2019 20:06:35 +0200 Subject: [PATCH 06/29] Media player RTL fixes (#3001) --- src/cards/ha-media_player-card.js | 6 +++++- src/components/ha-paper-slider.js | 5 +++++ .../more-info/controls/more-info-media_player.js | 11 +++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/cards/ha-media_player-card.js b/src/cards/ha-media_player-card.js index cb068c3afe..d54176a832 100644 --- a/src/cards/ha-media_player-card.js +++ b/src/cards/ha-media_player-card.js @@ -132,6 +132,10 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) { height: 44px; } + .playback-controls { + direction: ltr; + } + paper-icon-button { opacity: var(--dark-primary-opacity); } @@ -186,7 +190,7 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) { class="self-center secondary" > -
+
.slider-knob > .slider-knob-inner::after { + -webkit-transform: scale(1) translate(0, -17px) scaleX(-1) !important; + transform: scale(1) translate(0, -17px) scaleX(-1) !important; + } `; tpl.content.appendChild(styleEl); return tpl; diff --git a/src/dialogs/more-info/controls/more-info-media_player.js b/src/dialogs/more-info/controls/more-info-media_player.js index 0ce7af7a71..d78540d0c4 100644 --- a/src/dialogs/more-info/controls/more-info-media_player.js +++ b/src/dialogs/more-info/controls/more-info-media_player.js @@ -14,6 +14,7 @@ import attributeClassNames from "../../../common/entity/attribute_class_names"; import isComponentLoaded from "../../../common/config/is_component_loaded"; import EventsMixin from "../../../mixins/events-mixin"; import LocalizeMixin from "../../../mixins/localize-mixin"; +import { computeRTLDirection } from "../../../common/util/compute_rtl"; /* * @appliesMixin LocalizeMixin @@ -137,6 +138,7 @@ class MoreInfoMediaPlayer extends LocalizeMixin(EventsMixin(PolymerElement)) { on-change="volumeSliderChanged" class="flex" ignore-bar-touch="" + dir="{{rtl}}" >
@@ -233,6 +235,11 @@ class MoreInfoMediaPlayer extends LocalizeMixin(EventsMixin(PolymerElement)) { type: String, value: "", }, + + rtl: { + type: String, + computed: "_computeRTLDirection(hass)", + }, }; } @@ -425,6 +432,10 @@ class MoreInfoMediaPlayer extends LocalizeMixin(EventsMixin(PolymerElement)) { this.ttsMessage = ""; this.$.ttsInput.focus(); } + + _computeRTLDirection(hass) { + return computeRTLDirection(hass); + } } customElements.define("more-info-media_player", MoreInfoMediaPlayer); From 8aa501b7bd4a5c25ecddde5b02542e965ffb9e0d Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Sat, 23 Mar 2019 11:08:00 -0700 Subject: [PATCH 07/29] Add Icelandic :flag_is: support (#3003) --- src/translations/translationMetadata.json | 3 +++ translations/da.json | 14 +++++++------- translations/he.json | 4 ++-- translations/is.json | 11 +++++++++++ translations/nn.json | 11 ++++++++--- 5 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 translations/is.json diff --git a/src/translations/translationMetadata.json b/src/translations/translationMetadata.json index ad5be46a17..bb18f04ba3 100644 --- a/src/translations/translationMetadata.json +++ b/src/translations/translationMetadata.json @@ -76,6 +76,9 @@ "it": { "nativeName": "Italiano" }, + "is": { + "nativeName": "Íslenska" + }, "ja": { "nativeName": "日本語" }, diff --git a/translations/da.json b/translations/da.json index 4cb3a2a6fc..8a9c0b7b7c 100644 --- a/translations/da.json +++ b/translations/da.json @@ -611,13 +611,13 @@ } }, "area_registry": { - "caption": "Område registrering", + "caption": "Områderegistrering", "description": "Oversigt over alle områder i dit hjem.", "picker": { - "header": "Område registrering", + "header": "Områderegistrering", "introduction": "Områder bruges til at organisere hvor enhederne er. Disse oplysninger vil blive brugt i Home Assistant til at hjælpe dig med at organisere din grænseflade, tilladelser og integrationer med andre systemer.", "introduction2": "Hvis du vil placere enheder i et område, skal du bruge linket herunder til at navigere til integrationssiden og derefter klikke på en konfigureret integration for at komme til enhedskortene.", - "integrations_page": "Integrations side", + "integrations_page": "Integrationsside", "no_areas": "Du ikke har ingen områder endnu!", "create_area": "OPRET OMRÅDE" }, @@ -631,14 +631,14 @@ } }, "entity_registry": { - "caption": "Enheds registrering", + "caption": "Enhedsregistrering", "description": "Oversigt over alle kendte enheder.", "picker": { - "header": "Enheds registrering", + "header": "Enhedsregistrering", "unavailable": "(utilgængelig)", "introduction": "Home Assistant opbevarer en registrering over hver unikke enhed det nogensinde har set. Hver af disse enheder vil have et registrerings ID tildelt som er forbeholdt netop denne enhed.", "introduction2": "Brug enhedsregistrering til at overskrive navnet, ændre enheds ID eller fjerne enheden fra Home Assistant. Bemærk at fjernelse af enhedens registrering ikke fjerner enheden. For at gøre det skal du følge linket herunder og fjerne det fra integrationssiden.", - "integrations_page": "Integrations side" + "integrations_page": "Integrationsside" }, "editor": { "unavailable": "Denne enhed er ikke tilgængelig i øjeblikket.", @@ -1143,7 +1143,7 @@ "hassio": "Hass.io", "homeassistant": "Home Assistant", "lovelace": "Lovelace", - "system_health": "System sundhed", + "system_health": "Systemsundhed", "person": "Person" }, "attribute": { diff --git a/translations/he.json b/translations/he.json index 57bf0942dd..43d14f146c 100644 --- a/translations/he.json +++ b/translations/he.json @@ -133,8 +133,8 @@ "climate": { "off": "כבוי", "on": "דלוק", - "heat": "חום", - "cool": "קריר", + "heat": "חימום", + "cool": "קרור", "idle": "ממתין", "auto": "אוטומטי", "dry": "יבש", diff --git a/translations/is.json b/translations/is.json new file mode 100644 index 0000000000..be26cc4508 --- /dev/null +++ b/translations/is.json @@ -0,0 +1,11 @@ +{ + "panel": { + "config": "Stillingar", + "states": "Yfirlit", + "map": "Kort", + "logbook": "Logbók", + "history": "Saga", + "mailbox": "Pósthólf", + "shopping_list": "Innkaupalisti" + } +} \ No newline at end of file diff --git a/translations/nn.json b/translations/nn.json index 5d7f67a86f..ca41f40be5 100644 --- a/translations/nn.json +++ b/translations/nn.json @@ -616,7 +616,8 @@ "header": "Områderegister", "introduction": "Områda vert brukt til å organisere kvar einingar er. Denne informasjonen vil bli brukt av Home Assistant for å hjelpe deg å organisere brukargrensesnittet, løyver og integrasjoner med andre system.", "introduction2": "For å plassere ei eining i eit område, bruk linken under for å navigere til integrasjonssida og trykk deretter på konfigurer integrasjon for å opne einingskortet.", - "integrations_page": "Integrasjonsside" + "integrations_page": "Integrasjonsside", + "no_areas": "Ser ut til at du ikkje har noko område endå!" }, "no_areas": "Ser ut til at du ikkje har noko område endå!", "create_area": "LAG OMRÅDE", @@ -633,7 +634,7 @@ "picker": { "header": "Oppføringsregisteret", "unavailable": "(utilgjengeleg)", - "introduction": "Home Assistant har eit register over alle oppføringane den nokon gang har sett som kan unikt identifiserast. KVar av desse oppføringane har ein eigen oppføringsidentifikasjon som er reservert for akkuratt denne oppføringa.", + "introduction": "Home Assistant har eit register over alle oppføringane den nokon gang har sett som kan unikt identifiserast. Kvar av desse oppføringane har ein eigen oppføringsidentifikasjon som er reservert for akkuratt denne oppføringa.", "introduction2": "Bruk oppføringsregisteret til å skrive over namn, endre oppføringsidentifikasjonane eller fjerne oppføringar frå Home Assistant. Merk deg at å fjerne oppføringa i oppføringregisteret ikkje fjernar sjølve oppføringa. For å gjere dette, gå vidare inn på linken under og fjern oppføringa i integrasjonssida.", "integrations_page": "Integrasjonsside" }, @@ -830,7 +831,8 @@ "data": { "name": "Namn", "username": "Brukarnamn", - "password": "Passord" + "password": "Passord", + "password_confirm": "Stadfest passord" }, "create_account": "Lag konto", "error": { @@ -1156,5 +1158,8 @@ "auto": "Auto" } } + }, + "groups": { + "system-admin": "Administratorer" } } \ No newline at end of file From e2a9cf0d3c09b4e335ad70f66d3acb159db65737 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Sat, 23 Mar 2019 13:09:30 -0500 Subject: [PATCH 08/29] Handle unavailable entity in conditional-card (#2996) * Handle unavailable entity in conditional-card * cleanup --- src/panels/lovelace/common/validate-condition.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/panels/lovelace/common/validate-condition.ts b/src/panels/lovelace/common/validate-condition.ts index 7775cafa40..e50707d871 100644 --- a/src/panels/lovelace/common/validate-condition.ts +++ b/src/panels/lovelace/common/validate-condition.ts @@ -11,13 +11,11 @@ export function checkConditionsMet( hass: HomeAssistant ): boolean { return conditions.every((c) => { - if (!(c.entity in hass.states)) { - return false; - } - if (c.state) { - return hass.states[c.entity].state === c.state; - } - return hass!.states[c.entity].state !== c.state_not; + const state = hass.states[c.entity] + ? hass!.states[c.entity].state + : "unavailable"; + + return c.state ? state === c.state : state !== c.state_not; }); } From 702c17d658672a649329084cd7c781fba24d663f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 23 Mar 2019 11:41:36 -0700 Subject: [PATCH 09/29] Convert custom panel to typescript (#2991) * Convert custom panel to typescript * Address comments --- src/data/panel_custom.ts | 8 ++ src/entrypoints/custom-panel.js | 80 -------------- src/entrypoints/custom-panel.ts | 97 ++++++++++++++++ ...{ha-panel-custom.js => ha-panel-custom.ts} | 104 +++++++++--------- src/types.ts | 3 + ...ment.js => create-custom-panel-element.ts} | 4 +- ...d-custom-panel.js => load-custom-panel.ts} | 4 +- ...ties.js => set-custom-panel-properties.ts} | 4 +- webpack.config.js | 4 +- 9 files changed, 168 insertions(+), 140 deletions(-) create mode 100644 src/data/panel_custom.ts delete mode 100644 src/entrypoints/custom-panel.js create mode 100644 src/entrypoints/custom-panel.ts rename src/panels/custom/{ha-panel-custom.js => ha-panel-custom.ts} (52%) rename src/util/custom-panel/{create-custom-panel-element.js => create-custom-panel-element.ts} (78%) rename src/util/custom-panel/{load-custom-panel.js => load-custom-panel.ts} (93%) rename src/util/custom-panel/{set-custom-panel-properties.js => set-custom-panel-properties.ts} (71%) diff --git a/src/data/panel_custom.ts b/src/data/panel_custom.ts new file mode 100644 index 0000000000..7f8ad4a29e --- /dev/null +++ b/src/data/panel_custom.ts @@ -0,0 +1,8 @@ +export interface CustomPanelConfig { + name: string; + embed_iframe: boolean; + trust_external: boolean; + js_url?: string; + module_url?: string; + html_url?: string; +} diff --git a/src/entrypoints/custom-panel.js b/src/entrypoints/custom-panel.js deleted file mode 100644 index 1d064943ce..0000000000 --- a/src/entrypoints/custom-panel.js +++ /dev/null @@ -1,80 +0,0 @@ -import { loadJS } from "../common/dom/load_resource"; -import loadCustomPanel from "../util/custom-panel/load-custom-panel"; -import createCustomPanelElement from "../util/custom-panel/create-custom-panel-element"; -import setCustomPanelProperties from "../util/custom-panel/set-custom-panel-properties"; - -const webComponentsSupported = - "customElements" in window && - "import" in document.createElement("link") && - "content" in document.createElement("template"); - -let es5Loaded = null; - -window.loadES5Adapter = () => { - if (!es5Loaded) { - es5Loaded = Promise.all([ - loadJS(`${__STATIC_PATH__}custom-elements-es5-adapter.js`).catch(), - import(/* webpackChunkName: "compat" */ "./compatibility"), - ]); - } - return es5Loaded; -}; - -let root = null; - -function setProperties(properties) { - if (root === null) return; - setCustomPanelProperties(root, properties); -} - -function initialize(panel, properties) { - const style = document.createElement("style"); - style.innerHTML = "body{margin:0}"; - document.head.appendChild(style); - - const config = panel.config._panel_custom; - let start = Promise.resolve(); - - if (!webComponentsSupported) { - start = start.then(() => loadJS("/static/webcomponents-bundle.js")); - } - - if (__BUILD__ === "es5") { - // Load ES5 adapter. Swallow errors as it raises errors on old browsers. - start = start.then(() => window.loadES5Adapter()); - } - - start - .then(() => loadCustomPanel(config)) - // If our element is using es5, let it finish loading that and define element - // This avoids elements getting upgraded after being added to the DOM - .then(() => es5Loaded || Promise.resolve()) - .then( - () => { - root = createCustomPanelElement(config); - - const forwardEvent = (ev) => - window.parent.customPanel.fire(ev.type, ev.detail); - root.addEventListener("hass-toggle-menu", forwardEvent); - window.addEventListener("location-changed", (ev) => - window.parent.customPanel.navigate( - window.location.pathname, - ev.detail ? ev.detail.replace : false - ) - ); - setProperties(Object.assign({ panel }, properties)); - document.body.appendChild(root); - }, - (err) => { - // eslint-disable-next-line - console.error(err, panel); - alert(`Unable to load the panel source: ${err}.`); - } - ); -} - -document.addEventListener( - "DOMContentLoaded", - () => window.parent.customPanel.registerIframe(initialize, setProperties), - { once: true } -); diff --git a/src/entrypoints/custom-panel.ts b/src/entrypoints/custom-panel.ts new file mode 100644 index 0000000000..f5c9c463e5 --- /dev/null +++ b/src/entrypoints/custom-panel.ts @@ -0,0 +1,97 @@ +import { loadJS } from "../common/dom/load_resource"; +import { loadCustomPanel } from "../util/custom-panel/load-custom-panel"; +import { createCustomPanelElement } from "../util/custom-panel/create-custom-panel-element"; +import { setCustomPanelProperties } from "../util/custom-panel/set-custom-panel-properties"; +import { fireEvent } from "../common/dom/fire_event"; +import { navigate } from "../common/navigate"; +import { PolymerElement } from "@polymer/polymer"; +import { Panel } from "../types"; +import { CustomPanelConfig } from "../data/panel_custom"; + +declare global { + interface Window { + loadES5Adapter: () => Promise; + } +} + +const webComponentsSupported = + "customElements" in window && + "import" in document.createElement("link") && + "content" in document.createElement("template"); + +let es5Loaded: Promise | undefined; + +window.loadES5Adapter = () => { + if (!es5Loaded) { + es5Loaded = Promise.all([ + loadJS(`${__STATIC_PATH__}custom-elements-es5-adapter.js`).catch(), + import(/* webpackChunkName: "compat" */ "./compatibility"), + ]); + } + return es5Loaded; +}; + +let panelEl: HTMLElement | PolymerElement | undefined; + +function setProperties(properties) { + if (!panelEl) { + return; + } + setCustomPanelProperties(panelEl, properties); +} + +function initialize(panel: Panel, properties: {}) { + const style = document.createElement("style"); + style.innerHTML = "body{margin:0}"; + document.head.appendChild(style); + + const config = panel.config!._panel_custom as CustomPanelConfig; + let start: Promise = Promise.resolve(); + + if (!webComponentsSupported) { + start = start.then(() => loadJS("/static/webcomponents-bundle.js")); + } + + if (__BUILD__ === "es5") { + // Load ES5 adapter. Swallow errors as it raises errors on old browsers. + start = start.then(() => window.loadES5Adapter()); + } + + start + .then(() => loadCustomPanel(config)) + // If our element is using es5, let it finish loading that and define element + // This avoids elements getting upgraded after being added to the DOM + .then(() => es5Loaded || Promise.resolve()) + .then( + () => { + panelEl = createCustomPanelElement(config); + + const forwardEvent = (ev) => { + if (window.parent.customPanel) { + fireEvent(window.parent.customPanel, ev.type, ev.detail); + } + }; + panelEl!.addEventListener("hass-toggle-menu", forwardEvent); + window.addEventListener("location-changed", (ev: any) => + navigate( + window.parent.customPanel, + window.location.pathname, + ev.detail ? ev.detail.replace : false + ) + ); + setProperties({ panel, ...properties }); + document.body.appendChild(panelEl!); + }, + (err) => { + // tslint:disable-next-line + console.error(err, panel); + alert(`Unable to load the panel source: ${err}.`); + } + ); +} + +document.addEventListener( + "DOMContentLoaded", + () => window.parent.customPanel!.registerIframe(initialize, setProperties), + { once: true } +); diff --git a/src/panels/custom/ha-panel-custom.js b/src/panels/custom/ha-panel-custom.ts similarity index 52% rename from src/panels/custom/ha-panel-custom.js rename to src/panels/custom/ha-panel-custom.ts index 7571d697c5..55bb613ad6 100644 --- a/src/panels/custom/ha-panel-custom.js +++ b/src/panels/custom/ha-panel-custom.ts @@ -1,50 +1,69 @@ -import { PolymerElement } from "@polymer/polymer/polymer-element"; +import { property, PropertyValues, UpdatingElement } from "lit-element"; +import { loadCustomPanel } from "../../util/custom-panel/load-custom-panel"; +import { createCustomPanelElement } from "../../util/custom-panel/create-custom-panel-element"; +import { setCustomPanelProperties } from "../../util/custom-panel/set-custom-panel-properties"; +import { HomeAssistant, Route, Panel } from "../../types"; +import { CustomPanelConfig } from "../../data/panel_custom"; -import EventsMixin from "../../mixins/events-mixin"; -import NavigateMixin from "../../mixins/navigate-mixin"; -import loadCustomPanel from "../../util/custom-panel/load-custom-panel"; -import createCustomPanelElement from "../../util/custom-panel/create-custom-panel-element"; -import setCustomPanelProperties from "../../util/custom-panel/set-custom-panel-properties"; +declare global { + interface Window { + customPanel: HaPanelCustom | undefined; + } +} -/* - * Mixins are used by ifram to communicate with main frontend. - * @appliesMixin EventsMixin - * @appliesMixin NavigateMixin - */ -class HaPanelCustom extends NavigateMixin(EventsMixin(PolymerElement)) { - static get properties() { - return { - hass: Object, - narrow: Boolean, - route: Object, - panel: { - type: Object, - observer: "_panelChanged", - }, - }; +export class HaPanelCustom extends UpdatingElement { + @property() public hass!: HomeAssistant; + @property() public narrow!: boolean; + @property() public route!: Route; + @property() public panel!: Panel; + private _setProperties?: (props: {}) => void | undefined; + + public registerIframe(initialize, setProperties) { + initialize(this.panel, { + hass: this.hass, + narrow: this.narrow, + route: this.route, + }); + this._setProperties = setProperties; } - static get observers() { - return ["_dataChanged(hass, narrow, route)"]; + public disconnectedCallback() { + super.disconnectedCallback(); + this._cleanupPanel(); } - constructor() { - super(); - this._setProperties = null; + protected updated(changedProps: PropertyValues) { + if (changedProps.has("panel")) { + // Clean up old things if we had a panel + if (changedProps.get("panel")) { + this._cleanupPanel(); + } + this._createPanel(this.panel); + return; + } + if (!this._setProperties) { + return; + } + const props = {}; + for (const key of changedProps.keys()) { + props[key] = this[key]; + } + this._setProperties(props); } - _panelChanged(panel) { - // Clean up + private _cleanupPanel() { delete window.customPanel; - this._setProperties = null; + this._setProperties = undefined; while (this.lastChild) { this.removeChild(this.lastChild); } + } - const config = panel.config._panel_custom; + private _createPanel(panel: Panel) { + const config = panel.config!._panel_custom as CustomPanelConfig; const tempA = document.createElement("a"); - tempA.href = config.html_url || config.js_url || config.module_url; + tempA.href = config.html_url || config.js_url || config.module_url || ""; if ( !config.trust_external && @@ -96,32 +115,13 @@ It will have access to all data in Home Assistant. `.trim(); - const iframeDoc = this.querySelector("iframe").contentWindow.document; + const iframeDoc = this.querySelector("iframe")!.contentWindow!.document; iframeDoc.open(); iframeDoc.write( `` ); iframeDoc.close(); } - - disconnectedCallback() { - super.disconnectedCallback(); - delete window.customPanel; - } - - _dataChanged(hass, narrow, route) { - if (!this._setProperties) return; - this._setProperties({ hass, narrow, route }); - } - - registerIframe(initialize, setProperties) { - initialize(this.panel, { - hass: this.hass, - narrow: this.narrow, - route: this.route, - }); - this._setProperties = setProperties; - } } customElements.define("ha-panel-custom", HaPanelCustom); diff --git a/src/types.ts b/src/types.ts index 099fe66574..33665a4594 100644 --- a/src/types.ts +++ b/src/types.ts @@ -15,10 +15,13 @@ declare global { var __DEMO__: boolean; var __BUILD__: "latest" | "es5"; var __VERSION__: string; + var __STATIC_PATH__: string; } declare global { interface Window { + // Custom panel entry point url + customPanelJS: string; ShadyCSS: { nativeCss: boolean; nativeShadow: boolean; diff --git a/src/util/custom-panel/create-custom-panel-element.js b/src/util/custom-panel/create-custom-panel-element.ts similarity index 78% rename from src/util/custom-panel/create-custom-panel-element.js rename to src/util/custom-panel/create-custom-panel-element.ts index 4969c179de..d4a23699b4 100644 --- a/src/util/custom-panel/create-custom-panel-element.js +++ b/src/util/custom-panel/create-custom-panel-element.ts @@ -1,8 +1,8 @@ -export default function createCustomPanelElement(panelConfig) { +export const createCustomPanelElement = (panelConfig) => { // Legacy support. Custom panels used to have to define element ha-panel-{name} const tagName = "html_url" in panelConfig ? `ha-panel-${panelConfig.name}` : panelConfig.name; return document.createElement(tagName); -} +}; diff --git a/src/util/custom-panel/load-custom-panel.js b/src/util/custom-panel/load-custom-panel.ts similarity index 93% rename from src/util/custom-panel/load-custom-panel.js rename to src/util/custom-panel/load-custom-panel.ts index 54614810aa..08b399d591 100644 --- a/src/util/custom-panel/load-custom-panel.js +++ b/src/util/custom-panel/load-custom-panel.ts @@ -3,7 +3,7 @@ import { loadJS, loadModule } from "../../common/dom/load_resource"; // Make sure we only import every JS-based panel once (HTML import has this built-in) const JS_CACHE = {}; -export default function loadCustomPanel(panelConfig) { +export const loadCustomPanel = (panelConfig): Promise => { if (panelConfig.html_url) { const toLoad = [ import(/* webpackChunkName: "import-href-polyfill" */ "../../resources/html-import/import-href"), @@ -29,4 +29,4 @@ export default function loadCustomPanel(panelConfig) { return loadModule(panelConfig.module_url); } return Promise.reject("No valid url found in panel config."); -} +}; diff --git a/src/util/custom-panel/set-custom-panel-properties.js b/src/util/custom-panel/set-custom-panel-properties.ts similarity index 71% rename from src/util/custom-panel/set-custom-panel-properties.js rename to src/util/custom-panel/set-custom-panel-properties.ts index f54996cd5d..3aa8271ef8 100644 --- a/src/util/custom-panel/set-custom-panel-properties.js +++ b/src/util/custom-panel/set-custom-panel-properties.ts @@ -1,4 +1,4 @@ -export default function setCustomPanelProperties(root, properties) { +export const setCustomPanelProperties = (root, properties) => { if ("setProperties" in root) { root.setProperties(properties); } else { @@ -6,4 +6,4 @@ export default function setCustomPanelProperties(root, properties) { root[key] = properties[key]; }); } -} +}; diff --git a/webpack.config.js b/webpack.config.js index e723bd58d7..7e61e7f290 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -44,7 +44,7 @@ function createConfig(isProdBuild, latestBuild) { onboarding: "./src/entrypoints/onboarding.ts", core: "./src/entrypoints/core.ts", compatibility: "./src/entrypoints/compatibility.js", - "custom-panel": "./src/entrypoints/custom-panel.js", + "custom-panel": "./src/entrypoints/custom-panel.ts", "hass-icons": "./src/entrypoints/hass-icons.js", }; @@ -156,7 +156,7 @@ function createConfig(isProdBuild, latestBuild) { include: [ /core.ts$/, /app.js$/, - /custom-panel.js$/, + /custom-panel.ts$/, /hass-icons.js$/, /\.chunk\.js$/, ], From 3b8f8f818919ba95f5ce2a8109d5cf59b9f6dbd4 Mon Sep 17 00:00:00 2001 From: yosilevy <37745463+yosilevy@users.noreply.github.com> Date: Sun, 24 Mar 2019 05:30:26 +0200 Subject: [PATCH 10/29] Climate RTL fixes (#3002) --- src/components/ha-climate-control.js | 1 + src/components/ha-climate-state.js | 10 ++++++++-- src/dialogs/more-info/controls/more-info-climate.js | 13 +++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/components/ha-climate-control.js b/src/components/ha-climate-control.js index 20c7131373..2a1218ca0f 100644 --- a/src/components/ha-climate-control.js +++ b/src/components/ha-climate-control.js @@ -25,6 +25,7 @@ class HaClimateControl extends EventsMixin(PolymerElement) { #target_temperature { @apply --layout-self-center; font-size: 200%; + direction: ltr; } .control-buttons { font-size: 200%; diff --git a/src/components/ha-climate-state.js b/src/components/ha-climate-state.js index 73562392d9..27693bded9 100644 --- a/src/components/ha-climate-state.js +++ b/src/components/ha-climate-state.js @@ -29,18 +29,24 @@ class HaClimateState extends LocalizeMixin(PolymerElement) { font-weight: bold; text-transform: capitalize; } + + .unit { + display: inline-block; + direction: ltr; + }
- [[computeTarget(hass, stateObj)]] +
[[computeTarget(hass, stateObj)]]
`; diff --git a/src/dialogs/more-info/controls/more-info-climate.js b/src/dialogs/more-info/controls/more-info-climate.js index eac739b482..529cad6d6b 100644 --- a/src/dialogs/more-info/controls/more-info-climate.js +++ b/src/dialogs/more-info/controls/more-info-climate.js @@ -17,6 +17,7 @@ import { supportsFeature } from "../../../common/entity/supports-feature"; import EventsMixin from "../../../mixins/events-mixin"; import LocalizeMixin from "../../../mixins/localize-mixin"; +import { computeRTLDirection } from "../../../common/util/compute_rtl"; /* * @appliesMixin EventsMixin @@ -84,6 +85,7 @@ class MoreInfoClimate extends LocalizeMixin(EventsMixin(PolymerElement)) { width: 90px; font-size: 200%; margin: auto; + direction: ltr; } ha-climate-control.range-control-left, @@ -181,6 +183,7 @@ class MoreInfoClimate extends LocalizeMixin(EventsMixin(PolymerElement)) { value="[[stateObj.attributes.humidity]]" on-change="targetHumiditySliderChanged" ignore-bar-touch="" + dir="[[rtl]]" >
@@ -314,6 +317,12 @@ class MoreInfoClimate extends LocalizeMixin(EventsMixin(PolymerElement)) { awayToggleChecked: Boolean, auxToggleChecked: Boolean, onToggleChecked: Boolean, + + rtl: { + type: String, + value: "ltr", + computed: "_computeRTLDirection(hass)", + }, }; } @@ -557,6 +566,10 @@ class MoreInfoClimate extends LocalizeMixin(EventsMixin(PolymerElement)) { _localizeFanMode(localize, mode) { return localize(`state_attributes.climate.fan_mode.${mode}`) || mode; } + + _computeRTLDirection(hass) { + return computeRTLDirection(hass); + } } customElements.define("more-info-climate", MoreInfoClimate); From 324f0bb8a29e62b96203d1c93b376068a7a01c88 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Sun, 24 Mar 2019 01:10:55 -0500 Subject: [PATCH 11/29] warning-element (#3006) * warning-element * add warning-element to picture-glance * add glance-card --- src/panels/lovelace/cards/hui-glance-card.ts | 10 +++--- .../lovelace/cards/hui-picture-glance-card.ts | 12 ++++++- .../components/hui-warning-element.ts | 36 +++++++++++++++++++ .../elements/hui-state-badge-element.ts | 10 +++--- .../elements/hui-state-icon-element.ts | 10 +++--- .../elements/hui-state-label-element.ts | 10 +++--- 6 files changed, 67 insertions(+), 21 deletions(-) create mode 100644 src/panels/lovelace/components/hui-warning-element.ts diff --git a/src/panels/lovelace/cards/hui-glance-card.ts b/src/panels/lovelace/cards/hui-glance-card.ts index 35a643ba01..8ec574c234 100644 --- a/src/panels/lovelace/cards/hui-glance-card.ts +++ b/src/panels/lovelace/cards/hui-glance-card.ts @@ -25,7 +25,7 @@ import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import "../../../components/entity/state-badge"; import "../../../components/ha-card"; import "../../../components/ha-icon"; -import "../components/hui-warning"; +import "../components/hui-warning-element"; export interface ConfigEntity extends EntityConfig { tap_action?: ActionConfig; @@ -184,13 +184,13 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` - ${this.hass!.localize( + + )} + > `; } diff --git a/src/panels/lovelace/cards/hui-picture-glance-card.ts b/src/panels/lovelace/cards/hui-picture-glance-card.ts index 17c13ed494..5306a9c4a7 100644 --- a/src/panels/lovelace/cards/hui-picture-glance-card.ts +++ b/src/panels/lovelace/cards/hui-picture-glance-card.ts @@ -24,6 +24,8 @@ import stateIcon from "../../../common/entity/state_icon"; import "../../../components/ha-card"; import "../../../components/ha-icon"; import "../components/hui-image"; +import "../components/hui-warning-element"; + import { handleClick } from "../common/handle-click"; import { fireEvent } from "../../../common/dom/fire_event"; import { toggleEntity } from "../common/entity/toggle-entity"; @@ -138,7 +140,15 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard { const stateObj = this.hass!.states[entityConf.entity]; if (!stateObj) { - return html``; + return html` + + `; } return html` diff --git a/src/panels/lovelace/components/hui-warning-element.ts b/src/panels/lovelace/components/hui-warning-element.ts new file mode 100644 index 0000000000..b6495ec0fc --- /dev/null +++ b/src/panels/lovelace/components/hui-warning-element.ts @@ -0,0 +1,36 @@ +import { + html, + LitElement, + TemplateResult, + CSSResult, + css, + customElement, + property, +} from "lit-element"; + +import "../../../components/ha-icon"; + +@customElement("hui-warning-element") +export class HuiWarningElement extends LitElement { + @property() public label?: string; + + protected render(): TemplateResult | void { + return html` + + `; + } + + static get styles(): CSSResult { + return css` + ha-icon { + color: #fce588; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-warning-element": HuiWarningElement; + } +} diff --git a/src/panels/lovelace/elements/hui-state-badge-element.ts b/src/panels/lovelace/elements/hui-state-badge-element.ts index 6d452a1928..3a73c9e0c6 100644 --- a/src/panels/lovelace/elements/hui-state-badge-element.ts +++ b/src/panels/lovelace/elements/hui-state-badge-element.ts @@ -7,7 +7,7 @@ import { } from "lit-element"; import "../../../components/entity/ha-state-label-badge"; -import "../components/hui-warning"; +import "../components/hui-warning-element"; import computeStateName from "../../../common/entity/compute_state_name"; import { LovelaceElement, LovelaceElementConfig } from "./types"; @@ -40,13 +40,13 @@ export class HuiStateBadgeElement extends LitElement if (!stateObj) { return html` - ${this.hass.localize( + + )}" + > `; } diff --git a/src/panels/lovelace/elements/hui-state-icon-element.ts b/src/panels/lovelace/elements/hui-state-icon-element.ts index df9ddac572..bd7fd773ff 100644 --- a/src/panels/lovelace/elements/hui-state-icon-element.ts +++ b/src/panels/lovelace/elements/hui-state-icon-element.ts @@ -9,7 +9,7 @@ import { } from "lit-element"; import "../../../components/entity/state-badge"; -import "../components/hui-warning"; +import "../components/hui-warning-element"; import { computeTooltip } from "../common/compute-tooltip"; import { handleClick } from "../common/handle-click"; @@ -46,13 +46,13 @@ export class HuiStateIconElement extends LitElement implements LovelaceElement { if (!stateObj) { return html` - ${this.hass.localize( + + )} + > `; } diff --git a/src/panels/lovelace/elements/hui-state-label-element.ts b/src/panels/lovelace/elements/hui-state-label-element.ts index 5decd2d415..3cbf939a75 100644 --- a/src/panels/lovelace/elements/hui-state-label-element.ts +++ b/src/panels/lovelace/elements/hui-state-label-element.ts @@ -9,7 +9,7 @@ import { } from "lit-element"; import "../../../components/entity/ha-state-label-badge"; -import "../components/hui-warning"; +import "../components/hui-warning-element"; import computeStateDisplay from "../../../common/entity/compute_state_display"; import { computeTooltip } from "../common/compute-tooltip"; @@ -49,13 +49,13 @@ class HuiStateLabelElement extends LitElement implements LovelaceElement { if (!stateObj) { return html` - ${this.hass.localize( + + )} + > `; } From 9a2207b5cb76eea24bcff340ff017d4e6f9b3b80 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Mon, 25 Mar 2019 09:40:04 -0500 Subject: [PATCH 12/29] badge warning (#3009) --- src/components/entity/ha-state-label-badge.ts | 115 +++++++++--------- src/translations/en.json | 4 +- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/src/components/entity/ha-state-label-badge.ts b/src/components/entity/ha-state-label-badge.ts index 5222f79adf..afe0df84ac 100644 --- a/src/components/entity/ha-state-label-badge.ts +++ b/src/components/entity/ha-state-label-badge.ts @@ -2,11 +2,17 @@ import { LitElement, html, PropertyValues, - PropertyDeclarations, TemplateResult, + css, + CSSResult, + customElement, + property, } from "lit-element"; + import { HassEntity } from "home-assistant-js-websocket"; import { classMap } from "lit-html/directives/class-map"; +import { fireEvent } from "../../common/dom/fire_event"; +import { HomeAssistant } from "../../types"; import computeStateDomain from "../../common/entity/compute_state_domain"; import computeStateName from "../../common/entity/compute_state_name"; @@ -14,21 +20,20 @@ import domainIcon from "../../common/entity/domain_icon"; import stateIcon from "../../common/entity/state_icon"; import timerTimeRemaining from "../../common/entity/timer_time_remaining"; import secondsToDuration from "../../common/datetime/seconds_to_duration"; -import { fireEvent } from "../../common/dom/fire_event"; -import { HomeAssistant } from "../../types"; import "../ha-label-badge"; -/* - * @appliesMixin LocalizeMixin - * @appliesMixin EventsMixin - */ +@customElement("ha-state-label-badge") export class HaStateLabelBadge extends LitElement { - public hass?: HomeAssistant; - public state?: HassEntity; + @property() public hass?: HomeAssistant; + + @property() public state?: HassEntity; + + @property() private _timerTimeRemaining?: number; + private _connected?: boolean; + private _updateRemaining?: number; - private _timerTimeRemaining?: number; public connectedCallback(): void { super.connectedCallback(); @@ -47,15 +52,20 @@ export class HaStateLabelBadge extends LitElement { if (!state) { return html` - ${this.renderStyle()} - + `; } const domain = computeStateDomain(state); return html` - ${this.renderStyle()} { @@ -201,48 +203,47 @@ export class HaStateLabelBadge extends LitElement { this._timerTimeRemaining = timerTimeRemaining(stateObj); } - private renderStyle(): TemplateResult { - return html` - + .grey { + --ha-label-badge-color: var(--label-badge-grey, var(--paper-grey-500)); + } + + .warning { + --ha-label-badge-color: var(--label-badge-yellow, #fce588); + } `; } } @@ -252,5 +253,3 @@ declare global { "ha-state-label-badge": HaStateLabelBadge; } } - -customElements.define("ha-state-label-badge", HaStateLabelBadge); diff --git a/src/translations/en.json b/src/translations/en.json index 67b7033392..1ec7543e42 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -332,7 +332,9 @@ "state_badge": { "default": { "unknown": "Unk", - "unavailable": "Unavai" + "unavailable": "Unavai", + "error": "Error", + "entity_not_found": "Entity Not Found" }, "alarm_control_panel": { "armed": "Armed", From 435b7d9cee05de897278e46053c132847d5a0454 Mon Sep 17 00:00:00 2001 From: Petro31 <35082313+Petro31@users.noreply.github.com> Date: Mon, 25 Mar 2019 23:15:38 -0400 Subject: [PATCH 13/29] Fix for vertical button spacing on alarm card (#3017) Vertical spacing on button card doesn't have padding when 3 or more buttons are present and the card size is small. Small PR. --- src/panels/lovelace/cards/hui-alarm-panel-card.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/lovelace/cards/hui-alarm-panel-card.ts b/src/panels/lovelace/cards/hui-alarm-panel-card.ts index 7fadfbf954..921c0f4640 100644 --- a/src/panels/lovelace/cards/hui-alarm-panel-card.ts +++ b/src/panels/lovelace/cards/hui-alarm-panel-card.ts @@ -305,7 +305,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard { .actions mwc-button { min-width: calc(var(--base-unit) * 9); - margin: 0 4px; + margin: 0 4px 4px; } mwc-button#disarm { From 669358bf1ad5085eb224012778fb9b015b3bde64 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Mon, 25 Mar 2019 23:26:32 -0400 Subject: [PATCH 14/29] ZHA add devices page (#2969) * zha add device page add device join dialog stub update dialog stub fix spinner add messages and devices to dialog dialog updates update dialog update dialog add debug info fix reference add header update dialog test zha gateway message subscription add device join dialog stub add messages and devices to dialog dialog updates update dialog add debug info update dialog start transitioning to a page instead of a dialog fix import subpage update router remove old dialog handle remove dialog parts make add button call navigate change extract page add devices page cleanup * update device join page * auto scroll log * update css and add device page layout * fix padding * fix missing imports * fix imports * add -> permit * left justify device cards to prevent jumping * conditionally display entity ids * cleanup * fix vertical alignment * review comments * fix manufacturer overrides --- src/data/zha.ts | 3 +- src/panels/config/ha-panel-config.ts | 4 +- src/panels/config/zha/ha-config-zha.ts | 41 +-- src/panels/config/zha/types.ts | 8 +- src/panels/config/zha/zha-add-devices-page.ts | 246 ++++++++++++++ src/panels/config/zha/zha-binding.ts | 22 +- .../config/zha/zha-cluster-attributes.ts | 48 ++- src/panels/config/zha/zha-cluster-commands.ts | 33 +- src/panels/config/zha/zha-clusters.ts | 27 +- src/panels/config/zha/zha-config-panel.ts | 70 ++++ src/panels/config/zha/zha-device-card.ts | 304 ++++++++++++++++-- src/panels/config/zha/zha-network.ts | 69 ++-- src/panels/config/zha/zha-node.ts | 253 ++++----------- src/translations/en.json | 13 +- 14 files changed, 822 insertions(+), 319 deletions(-) create mode 100644 src/panels/config/zha/zha-add-devices-page.ts create mode 100644 src/panels/config/zha/zha-config-panel.ts diff --git a/src/data/zha.ts b/src/data/zha.ts index bdb965e5bd..87ac9a3a88 100644 --- a/src/data/zha.ts +++ b/src/data/zha.ts @@ -16,6 +16,7 @@ export interface ZHADevice { manufacturer_code: number; device_reg_id: string; user_given_name: string; + area_id: string; } export interface Attribute { @@ -42,7 +43,7 @@ export interface ReadAttributeServiceData { cluster_id: number; cluster_type: string; attribute: number; - manufacturer: number; + manufacturer?: number; } export const reconfigureNode = ( diff --git a/src/panels/config/ha-panel-config.ts b/src/panels/config/ha-panel-config.ts index 0d78f87168..052c12aea3 100644 --- a/src/panels/config/ha-panel-config.ts +++ b/src/panels/config/ha-panel-config.ts @@ -73,9 +73,9 @@ class HaPanelConfig extends HassRouterPage { import(/* webpackChunkName: "panel-config-users" */ "./users/ha-config-users"), }, zha: { - tag: "ha-config-zha", + tag: "zha-config-panel", load: () => - import(/* webpackChunkName: "panel-config-zha" */ "./zha/ha-config-zha"), + import(/* webpackChunkName: "panel-config-zha" */ "./zha/zha-config-panel"), }, zwave: { tag: "ha-config-zwave", diff --git a/src/panels/config/zha/ha-config-zha.ts b/src/panels/config/zha/ha-config-zha.ts index 1708b9f5a8..0c96d858a5 100755 --- a/src/panels/config/zha/ha-config-zha.ts +++ b/src/panels/config/zha/ha-config-zha.ts @@ -1,26 +1,26 @@ -import "@polymer/app-layout/app-header/app-header"; -import "@polymer/app-layout/app-toolbar/app-toolbar"; +import "../../../components/ha-paper-icon-button-arrow-prev"; +import "../../../layouts/hass-subpage"; +import "./zha-binding"; +import "./zha-cluster-attributes"; +import "./zha-cluster-commands"; +import "./zha-network"; +import "./zha-node"; +import "@polymer/paper-icon-button/paper-icon-button"; + import { + CSSResult, html, LitElement, property, PropertyValues, TemplateResult, - CSSResult, } from "lit-element"; -import "@polymer/paper-icon-button/paper-icon-button"; + import { HASSDomEvent } from "../../../common/dom/fire_event"; -import { Cluster, ZHADevice, fetchBindableDevices } from "../../../data/zha"; -import "../../../layouts/ha-app-layout"; -import "../../../components/ha-paper-icon-button-arrow-prev"; +import { Cluster, fetchBindableDevices, ZHADevice } from "../../../data/zha"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; import { ZHAClusterSelectedParams, ZHADeviceSelectedParams } from "./types"; -import "./zha-cluster-attributes"; -import "./zha-cluster-commands"; -import "./zha-network"; -import "./zha-node"; -import "./zha-binding"; export class HaConfigZha extends LitElement { @property() public hass?: HomeAssistant; @@ -38,16 +38,7 @@ export class HaConfigZha extends LitElement { protected render(): TemplateResult | void { return html` - - - - -
Zigbee Home Automation
-
-
- + ` : ""} -
+ `; } @@ -117,10 +108,6 @@ export class HaConfigZha extends LitElement { static get styles(): CSSResult[] { return [haStyle]; } - - private _onBackTapped(): void { - history.back(); - } } declare global { diff --git a/src/panels/config/zha/types.ts b/src/panels/config/zha/types.ts index 5e531c98aa..c785614efb 100644 --- a/src/panels/config/zha/types.ts +++ b/src/panels/config/zha/types.ts @@ -8,6 +8,12 @@ export interface ItemSelectedEvent { target?: PickerTarget; } +export interface ZHADeviceRemovedEvent { + detail?: { + device?: ZHADevice; + }; +} + export interface ChangeEvent { detail?: { value?: any; @@ -22,7 +28,7 @@ export interface SetAttributeServiceData { cluster_type: string; attribute: number; value: any; - manufacturer: number; + manufacturer?: number; } export interface IssueCommandServiceData { diff --git a/src/panels/config/zha/zha-add-devices-page.ts b/src/panels/config/zha/zha-add-devices-page.ts new file mode 100644 index 0000000000..9ebcce185a --- /dev/null +++ b/src/panels/config/zha/zha-add-devices-page.ts @@ -0,0 +1,246 @@ +import "../../../components/ha-service-description"; +import "../../../components/ha-textarea"; +import "../../../layouts/hass-subpage"; +import "./zha-device-card"; +import "@material/mwc-button"; +import "@polymer/paper-icon-button/paper-icon-button"; +import "@polymer/paper-spinner/paper-spinner"; + +import { + css, + CSSResult, + customElement, + html, + LitElement, + property, + TemplateResult, +} from "lit-element"; + +import { ZHADevice } from "../../../data/zha"; +import { haStyle } from "../../../resources/styles"; +import { HomeAssistant } from "../../../types"; + +@customElement("zha-add-devices-page") +class ZHAAddDevicesPage extends LitElement { + @property() public hass!: HomeAssistant; + @property() public isWide?: boolean; + @property() private _error?: string; + @property() private _discoveredDevices: ZHADevice[] = []; + @property() private _formattedEvents: string = ""; + @property() private _active: boolean = false; + @property() private _showHelp: boolean = false; + private _addDevicesTimeoutHandle: any = undefined; + private _subscribed?: Promise<() => Promise>; + + public connectedCallback(): void { + super.connectedCallback(); + this._subscribe(); + } + + public disconnectedCallback(): void { + super.disconnectedCallback(); + this._unsubscribe(); + this._error = undefined; + this._discoveredDevices = []; + this._formattedEvents = ""; + } + + protected render(): TemplateResult | void { + return html` + + ${this._active + ? html` +

+ + ${this.hass!.localize( + "ui.panel.config.zha.add_device_page.spinner" + )} +

+ ` + : html` +
+ + Search again + + + ${this._showHelp + ? html` + + ` + : ""} +
+ `} + ${this._error + ? html` +
${this._error}
+ ` + : ""} +
+
+ ${this._discoveredDevices.length < 1 + ? html` +
+

+ ${this.hass!.localize( + "ui.panel.config.zha.add_device_page.discovery_text" + )} +

+
+ ` + : html` + ${this._discoveredDevices.map( + (device) => html` + + ` + )} + `} +
+ + +
+ `; + } + + private _handleMessage(message: any): void { + if (message.type === "log_output") { + this._formattedEvents += message.log_entry.message + "\n"; + if (this.shadowRoot) { + const textArea = this.shadowRoot.querySelector("ha-textarea"); + if (textArea) { + textArea.scrollTop = textArea.scrollHeight; + } + } + } + if (message.type && message.type === "device_fully_initialized") { + this._discoveredDevices.push(message.device_info); + } + } + + private _unsubscribe(): void { + this._active = false; + if (this._addDevicesTimeoutHandle) { + clearTimeout(this._addDevicesTimeoutHandle); + } + if (this._subscribed) { + this._subscribed.then((unsub) => unsub()); + this._subscribed = undefined; + } + } + + private _subscribe(): void { + this._subscribed = this.hass!.connection.subscribeMessage( + (message) => this._handleMessage(message), + { type: "zha/devices/permit" } + ); + this._active = true; + this._addDevicesTimeoutHandle = setTimeout( + () => this._unsubscribe(), + 60000 + ); + } + + private _onHelpTap(): void { + this._showHelp = !this._showHelp; + } + + static get styles(): CSSResult[] { + return [ + haStyle, + css` + .discovery-text, + .content-header { + margin: 16px; + } + .content { + border-top: 1px solid var(--light-primary-color); + min-height: 500px; + display: flex; + flex-wrap: wrap; + padding: 4px; + justify-content: left; + overflow: scroll; + } + .error { + color: var(--google-red-500); + } + paper-spinner { + display: none; + margin-right: 20px; + margin-left: 16px; + } + paper-spinner[active] { + display: block; + float: left; + margin-right: 20px; + margin-left: 16px; + } + .card { + margin-left: 16px; + margin-right: 16px; + margin-bottom: 0px; + margin-top: 10px; + } + .events { + margin: 16px; + border-top: 1px solid var(--light-primary-color); + padding-top: 16px; + min-height: 200px; + max-height: 200px; + overflow: scroll; + } + .toggle-help-icon { + position: absolute; + margin-top: 16px; + margin-right: 16px; + top: -6px; + right: 0; + color: var(--primary-color); + } + ha-service-description { + margin-top: 16px; + margin-left: 16px; + display: block; + color: grey; + } + .search-button { + margin-top: 16px; + margin-left: 16px; + } + .help-text { + color: grey; + padding-left: 16px; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "zha-add-devices-page": ZHAAddDevicesPage; + } +} diff --git a/src/panels/config/zha/zha-binding.ts b/src/panels/config/zha/zha-binding.ts index 3394262a83..a2bc43c247 100644 --- a/src/panels/config/zha/zha-binding.ts +++ b/src/panels/config/zha/zha-binding.ts @@ -1,20 +1,26 @@ +import "../../../components/buttons/ha-call-service-button"; +import "../../../components/ha-service-description"; +import "../ha-config-section"; +import "@material/mwc-button/mwc-button"; +import "@polymer/paper-card/paper-card"; +import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; +import "@polymer/paper-icon-button/paper-icon-button"; +import "@polymer/paper-listbox/paper-listbox"; + import { + css, + CSSResult, + customElement, html, LitElement, property, PropertyValues, TemplateResult, - CSSResult, - css, - customElement, } from "lit-element"; -import "@polymer/paper-card/paper-card"; -import "../../../components/buttons/ha-call-service-button"; -import "../../../components/ha-service-description"; -import { ZHADevice, bindDevices, unbindDevices } from "../../../data/zha"; + +import { bindDevices, unbindDevices, ZHADevice } from "../../../data/zha"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; -import "../ha-config-section"; import { ItemSelectedEvent } from "./types"; @customElement("zha-binding-control") diff --git a/src/panels/config/zha/zha-cluster-attributes.ts b/src/panels/config/zha/zha-cluster-attributes.ts index c59126cbf2..10f4a3677e 100644 --- a/src/panels/config/zha/zha-cluster-attributes.ts +++ b/src/panels/config/zha/zha-cluster-attributes.ts @@ -1,17 +1,24 @@ +import "../../../components/buttons/ha-call-service-button"; +import "../../../components/ha-service-description"; +import "../ha-config-section"; +import "@material/mwc-button"; +import "@polymer/paper-card/paper-card"; +import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; +import "@polymer/paper-icon-button/paper-icon-button"; +import "@polymer/paper-input/paper-input"; +import "@polymer/paper-item/paper-item"; +import "@polymer/paper-listbox/paper-listbox"; + import { + css, + CSSResult, html, LitElement, PropertyDeclarations, PropertyValues, TemplateResult, - CSSResult, - css, } from "lit-element"; -import "@material/mwc-button"; -import "@polymer/paper-card/paper-card"; -import "@polymer/paper-icon-button/paper-icon-button"; -import "../../../components/buttons/ha-call-service-button"; -import "../../../components/ha-service-description"; + import { Attribute, Cluster, @@ -22,13 +29,12 @@ import { } from "../../../data/zha"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; -import "../ha-config-section"; +import { formatAsPaddedHex } from "./functions"; import { ChangeEvent, ItemSelectedEvent, SetAttributeServiceData, } from "./types"; -import { formatAsPaddedHex } from "./functions"; export class ZHAClusterAttributes extends LitElement { public hass?: HomeAssistant; @@ -115,7 +121,7 @@ export class ZHAClusterAttributes extends LitElement {
${this.showHelp ? html` -
+
Select an attribute to view or set its value
` @@ -152,6 +158,13 @@ export class ZHAClusterAttributes extends LitElement { Get Zigbee Attribute + ${this.showHelp + ? html` +
+ Get the value for the selected attribute +
+ ` + : ""} ` : ""} @@ -201,7 +215,7 @@ export class ZHAClusterAttributes extends LitElement { attribute: this._attributes[this._selectedAttributeIndex].id, manufacturer: this._manufacturerCodeOverride ? parseInt(this._manufacturerCodeOverride as string, 10) - : this.selectedNode!.manufacturer_code, + : undefined, }; } @@ -220,7 +234,7 @@ export class ZHAClusterAttributes extends LitElement { value: this._attributeValue, manufacturer: this._manufacturerCodeOverride ? parseInt(this._manufacturerCodeOverride as string, 10) - : this.selectedNode!.manufacturer_code, + : undefined, }; } @@ -312,6 +326,16 @@ export class ZHAClusterAttributes extends LitElement { [hidden] { display: none; } + .help-text { + color: grey; + padding-left: 28px; + padding-right: 28px; + padding-bottom: 16px; + } + .help-text2 { + color: grey; + padding: 16px; + } `, ]; } diff --git a/src/panels/config/zha/zha-cluster-commands.ts b/src/panels/config/zha/zha-cluster-commands.ts index 28a68af9ab..d8bbcac2e4 100644 --- a/src/panels/config/zha/zha-cluster-commands.ts +++ b/src/panels/config/zha/zha-cluster-commands.ts @@ -1,15 +1,23 @@ +import "../../../components/buttons/ha-call-service-button"; +import "../../../components/ha-service-description"; +import "../ha-config-section"; +import "@polymer/paper-card/paper-card"; +import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; +import "@polymer/paper-icon-button/paper-icon-button"; +import "@polymer/paper-input/paper-input"; +import "@polymer/paper-item/paper-item"; +import "@polymer/paper-listbox/paper-listbox"; + import { + css, + CSSResult, html, LitElement, PropertyDeclarations, PropertyValues, TemplateResult, - CSSResult, - css, } from "lit-element"; -import "@polymer/paper-card/paper-card"; -import "../../../components/buttons/ha-call-service-button"; -import "../../../components/ha-service-description"; + import { Cluster, Command, @@ -18,13 +26,12 @@ import { } from "../../../data/zha"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; -import "../ha-config-section"; +import { formatAsPaddedHex } from "./functions"; import { ChangeEvent, IssueCommandServiceData, ItemSelectedEvent, } from "./types"; -import { formatAsPaddedHex } from "./functions"; export class ZHAClusterCommands extends LitElement { public hass?: HomeAssistant; @@ -107,7 +114,7 @@ export class ZHAClusterCommands extends LitElement {
${this._showHelp ? html` -
Select a command to interact with
+
Select a command to interact with
` : ""} ${this._selectedCommandIndex !== -1 @@ -135,6 +142,7 @@ export class ZHAClusterCommands extends LitElement { .hass="${this.hass}" domain="zha" service="issue_zigbee_cluster_command" + class="help-text2" > ` : ""} @@ -242,7 +250,14 @@ export class ZHAClusterCommands extends LitElement { position: relative; } - .helpText { + .help-text { + color: grey; + padding-left: 28px; + padding-right: 28px; + padding-bottom: 16px; + } + + .help-text2 { color: grey; padding: 16px; } diff --git a/src/panels/config/zha/zha-clusters.ts b/src/panels/config/zha/zha-clusters.ts index bbabf3e2fa..512cc16d7d 100644 --- a/src/panels/config/zha/zha-clusters.ts +++ b/src/panels/config/zha/zha-clusters.ts @@ -1,22 +1,27 @@ +import "../../../components/buttons/ha-call-service-button"; +import "../../../components/ha-service-description"; +import "../ha-config-section"; +import "@polymer/paper-card/paper-card"; +import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; +import "@polymer/paper-item/paper-item"; +import "@polymer/paper-listbox/paper-listbox"; + import { + css, + CSSResult, html, LitElement, PropertyDeclarations, PropertyValues, TemplateResult, - CSSResult, - css, } from "lit-element"; -import "@polymer/paper-card/paper-card"; + import { fireEvent } from "../../../common/dom/fire_event"; -import "../../../components/buttons/ha-call-service-button"; -import "../../../components/ha-service-description"; import { Cluster, fetchClustersForZhaNode, ZHADevice } from "../../../data/zha"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; -import "../ha-config-section"; -import { ItemSelectedEvent } from "./types"; import { formatAsPaddedHex } from "./functions"; +import { ItemSelectedEvent } from "./types"; declare global { // for fire event @@ -90,7 +95,7 @@ export class ZHAClusters extends LitElement { ${this.showHelp ? html` -
+
Select cluster to view attributes and commands
` @@ -143,9 +148,11 @@ export class ZHAClusters extends LitElement { padding-right: 28px; padding-bottom: 10px; } - .helpText { + .help-text { color: grey; - padding: 16px; + padding-left: 28px; + padding-right: 28px; + padding-bottom: 16px; } `, ]; diff --git a/src/panels/config/zha/zha-config-panel.ts b/src/panels/config/zha/zha-config-panel.ts new file mode 100644 index 0000000000..114c0f20ff --- /dev/null +++ b/src/panels/config/zha/zha-config-panel.ts @@ -0,0 +1,70 @@ +import "../../../layouts/hass-loading-screen"; + +import { customElement, property } from "lit-element"; + +import { listenMediaQuery } from "../../../common/dom/media_query"; +import { + HassRouterPage, + RouterOptions, +} from "../../../layouts/hass-router-page"; +import { HomeAssistant } from "../../../types"; + +@customElement("zha-config-panel") +class ZHAConfigPanel extends HassRouterPage { + @property() public hass!: HomeAssistant; + @property() public _wideSidebar: boolean = false; + @property() public _wide: boolean = false; + + protected routerOptions: RouterOptions = { + defaultPage: "configuration", + cacheAll: true, + preloadAll: true, + routes: { + configuration: { + tag: "ha-config-zha", + load: () => + import(/* webpackChunkName: "zha-configuration-page" */ "./ha-config-zha"), + }, + add: { + tag: "zha-add-devices-page", + load: () => + import(/* webpackChunkName: "zha-add-devices-page" */ "./zha-add-devices-page"), + }, + }, + }; + + private _listeners: Array<() => void> = []; + + public connectedCallback(): void { + super.connectedCallback(); + this._listeners.push( + listenMediaQuery("(min-width: 1040px)", (matches) => { + this._wide = matches; + }) + ); + this._listeners.push( + listenMediaQuery("(min-width: 1296px)", (matches) => { + this._wideSidebar = matches; + }) + ); + } + + public disconnectedCallback(): void { + super.disconnectedCallback(); + while (this._listeners.length) { + this._listeners.pop()!(); + } + } + + protected updatePageEl(el): void { + el.route = this.routeTail; + el.hass = this.hass; + el.isWide = this.hass.dockedSidebar ? this._wideSidebar : this._wide; + } +} + +declare global { + interface HTMLElementTagNameMap { + "zha-config-panel": ZHAConfigPanel; + } +} diff --git a/src/panels/config/zha/zha-device-card.ts b/src/panels/config/zha/zha-device-card.ts index d68d724ecb..c37d3902d9 100644 --- a/src/panels/config/zha/zha-device-card.ts +++ b/src/panels/config/zha/zha-device-card.ts @@ -1,40 +1,123 @@ +import "../../../components/buttons/ha-call-service-button"; +import "../../../components/entity/state-badge"; +import "@material/mwc-button"; +import "@polymer/paper-card/paper-card"; +import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; +import "@polymer/paper-input/paper-input"; +import "@polymer/paper-item/paper-icon-item"; +import "@polymer/paper-item/paper-item"; +import "@polymer/paper-item/paper-item-body"; +import "@polymer/paper-listbox/paper-listbox"; + import { + css, + CSSResult, + customElement, html, LitElement, property, + PropertyValues, TemplateResult, - CSSResult, - css, } from "lit-element"; -import "@polymer/paper-item/paper-icon-item"; -import "@polymer/paper-item/paper-item-body"; -import "@polymer/paper-card/paper-card"; -import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; -import "@polymer/paper-item/paper-item"; -import "@polymer/paper-listbox/paper-listbox"; + import { fireEvent } from "../../../common/dom/fire_event"; +import compare from "../../../common/string/compare"; +import { + AreaRegistryEntry, + fetchAreaRegistry, +} from "../../../data/area_registry"; +import { + DeviceRegistryEntryMutableParams, + updateDeviceRegistryEntry, +} from "../../../data/device_registry"; +import { reconfigureNode, ZHADevice } from "../../../data/zha"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; +import { ItemSelectedEvent, NodeServiceData } from "./types"; -import "../../../components/entity/state-badge"; -import { ZHADevice } from "../../../data/zha"; +declare global { + // for fire event + interface HASSDomEvents { + "zha-device-removed": { + device?: ZHADevice; + }; + } +} +@customElement("zha-device-card") class ZHADeviceCard extends LitElement { @property() public hass?: HomeAssistant; @property() public narrow?: boolean; @property() public device?: ZHADevice; + @property() public showHelp: boolean = false; + @property() public showActions?: boolean; + @property() public isJoinPage?: boolean; + @property() private _serviceData?: NodeServiceData; + @property() private _areas: AreaRegistryEntry[] = []; + @property() private _selectedAreaIndex: number = -1; + + public firstUpdated(changedProperties: PropertyValues): void { + super.firstUpdated(changedProperties); + this.addEventListener("hass-service-called", (ev) => + this.serviceCalled(ev) + ); + this._serviceData = { + ieee_address: this.device!.ieee, + }; + fetchAreaRegistry(this.hass!).then((areas) => { + this._areas = areas.sort((a, b) => compare(a.name, b.name)); + }); + } + + protected updated(changedProperties: PropertyValues): void { + if (changedProperties.has("device")) { + this._selectedAreaIndex = + this._areas.findIndex((area) => area.area_id === this.device!.area_id) + + 1; + } + super.update(changedProperties); + } + + protected serviceCalled(ev): void { + // Check if this is for us + if (ev.detail.success && ev.detail.service === "remove") { + fireEvent(this, "zha-device-removed", { + device: this.device, + }); + } + } protected render(): TemplateResult | void { return html` - + + ${ + this.isJoinPage + ? html` +
+
${this.device!.model}
+
+ ${this.hass!.localize( + "ui.panel.config.integrations.config_entry.manuf", + "manufacturer", + this.device!.manufacturer + )} +
+
+ ` + : "" + }
-
IEEE:
-
${this.device!.ieee}
-
Quirk applied:
-
${this.device!.quirk_applied}
-
Quirk:
-
${this.device!.quirk_class}
+
IEEE:
+
${this.device!.ieee}
+ ${ + this.device!.quirk_applied + ? html` +
Quirk:
+
${this.device!.quirk_class}
+ ` + : "" + }
@@ -49,24 +132,145 @@ class ZHADeviceCard extends LitElement { .stateObj="${this.hass!.states[entity.entity_id]}" slot="item-icon" > - -
${entity.name}
-
${entity.entity_id}
-
+ ${!this.isJoinPage + ? html` + +
${entity.name}
+
+ ${entity.entity_id} +
+
+ ` + : ""} ` )}
+
+ +
+
+ + + + ${this.hass!.localize( + "ui.panel.config.integrations.config_entry.no_area" + )} + + + ${this._areas.map( + (entry) => html` + ${entry.name} + ` + )} + + +
+ ${ + this.showActions + ? html` +
+ Reconfigure Device + ${this.showHelp + ? html` +
+ ${this.hass!.localize( + "ui.panel.config.zha.services.reconfigure" + )} +
+ ` + : ""} + + Remove Device + ${this.showHelp + ? html` +
+ ${this.hass!.localize( + "ui.panel.config.zha.services.remove" + )} +
+ ` + : ""} +
+ ` + : "" + } + `; } + private async _onReconfigureNodeClick(): Promise { + if (this.hass) { + await reconfigureNode(this.hass, this.device!.ieee); + } + } + + private async _saveCustomName(event): Promise { + if (this.hass) { + const values: DeviceRegistryEntryMutableParams = { + name_by_user: event.target.value, + area_id: this.device!.area_id ? this.device!.area_id : undefined, + }; + + await updateDeviceRegistryEntry( + this.hass, + this.device!.device_reg_id, + values + ); + + this.device!.user_given_name = event.target.value; + } + } + private _openMoreInfo(ev: MouseEvent): void { fireEvent(this, "hass-more-info", { entityId: (ev.currentTarget as any).entity.entity_id, }); } + private async _selectedAreaChanged(event: ItemSelectedEvent) { + if (!this.device || !this._areas) { + return; + } + this._selectedAreaIndex = event!.target!.selected; + const area = this._areas[this._selectedAreaIndex - 1]; // account for No Area + if ( + (!area && !this.device.area_id) || + (area && area.area_id === this.device.area_id) + ) { + return; + } + + await updateDeviceRegistryEntry(this.hass!, this.device.device_reg_id, { + area_id: area ? area.area_id : undefined, + name_by_user: this.device!.user_given_name, + }); + } + static get styles(): CSSResult[] { return [ haStyle, @@ -74,29 +278,43 @@ class ZHADeviceCard extends LitElement { :host(:not([narrow])) .device-entities { max-height: 225px; overflow: auto; + display: flex; + flex-wrap: wrap; + padding: 4px; + justify-content: left; } paper-card { flex: 1 0 100%; padding-bottom: 10px; - min-width: 0; + min-width: 425px; } .device { width: 30%; } - .label { + .device .name { font-weight: bold; } + .device .manuf { + color: var(--secondary-text-color); + } + .extra-info { + margin-top: 8px; + } + .manuf, + .zha-info, + .entity-id { + color: var(--secondary-text-color); + } .info { - color: var(--secondary-text-color); - font-weight: bold; + margin-left: 16px; } dl dt { + padding-left: 12px; float: left; - width: 100px; + width: 50px; text-align: left; } dt dd { - margin-left: 10px; text-align: left; } paper-icon-item { @@ -104,6 +322,36 @@ class ZHADeviceCard extends LitElement { padding-top: 4px; padding-bottom: 4px; } + .editable { + padding-left: 28px; + padding-right: 28px; + padding-bottom: 10px; + } + .help-text { + color: grey; + padding: 16px; + } + .flex { + -ms-flex: 1 1 0.000000001px; + -webkit-flex: 1; + flex: 1; + -webkit-flex-basis: 0.000000001px; + flex-basis: 0.000000001px; + } + .node-picker { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + padding-left: 28px; + padding-right: 28px; + padding-bottom: 10px; + } `, ]; } @@ -114,5 +362,3 @@ declare global { "zha-device-card": ZHADeviceCard; } } - -customElements.define("zha-device-card", ZHADeviceCard); diff --git a/src/panels/config/zha/zha-network.ts b/src/panels/config/zha/zha-network.ts index 87cf043838..b6c92d694e 100644 --- a/src/panels/config/zha/zha-network.ts +++ b/src/panels/config/zha/zha-network.ts @@ -1,19 +1,22 @@ +import "../../../components/buttons/ha-call-service-button"; +import "../../../components/ha-service-description"; +import "../ha-config-section"; +import "@material/mwc-button"; +import "@polymer/paper-card/paper-card"; +import "@polymer/paper-icon-button/paper-icon-button"; + import { + css, + CSSResult, html, LitElement, PropertyDeclarations, TemplateResult, - CSSResult, - css, } from "lit-element"; -import "@material/mwc-button"; -import "@polymer/paper-card/paper-card"; -import "@polymer/paper-icon-button/paper-icon-button"; -import "../../../components/buttons/ha-call-service-button"; -import "../../../components/ha-service-description"; + +import { navigate } from "../../../common/navigate"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; -import "../ha-config-section"; export class ZHANetwork extends LitElement { public hass?: HomeAssistant; @@ -30,6 +33,7 @@ export class ZHANetwork extends LitElement { hass: {}, isWide: {}, _showHelp: {}, + _joinParams: {}, }; } @@ -37,29 +41,31 @@ export class ZHANetwork extends LitElement { return html`
- Network Management - + Network Management +
Commands that affect entire network -
- Permit - ${ - this._showHelp - ? html` - - ` - : "" - } +
+ + Add Devices + + ${this._showHelp + ? html` + + ` + : ""} +
`; @@ -69,6 +75,10 @@ export class ZHANetwork extends LitElement { this._showHelp = !this._showHelp; } + private _onAddDevicesClick() { + navigate(this, "add"); + } + static get styles(): CSSResult[] { return [ haStyle, @@ -102,6 +112,11 @@ export class ZHANetwork extends LitElement { [hidden] { display: none; } + + .help-text2 { + color: grey; + padding: 16px; + } `, ]; } diff --git a/src/panels/config/zha/zha-node.ts b/src/panels/config/zha/zha-node.ts index 959c7bc594..39ab5a1181 100644 --- a/src/panels/config/zha/zha-node.ts +++ b/src/panels/config/zha/zha-node.ts @@ -1,32 +1,30 @@ -import { - html, - LitElement, - PropertyDeclarations, - TemplateResult, - CSSResult, - PropertyValues, - css, -} from "lit-element"; +import "../../../components/buttons/ha-call-service-button"; +import "../../../components/ha-service-description"; +import "../ha-config-section"; +import "./zha-clusters"; +import "./zha-device-card"; import "@material/mwc-button"; import "@polymer/paper-card/paper-card"; import "@polymer/paper-icon-button/paper-icon-button"; import "@polymer/paper-input/paper-input"; import "@polymer/paper-item/paper-item"; import "@polymer/paper-listbox/paper-listbox"; + +import { + css, + CSSResult, + customElement, + html, + LitElement, + property, + TemplateResult, +} from "lit-element"; + import { fireEvent } from "../../../common/dom/fire_event"; -import "../../../components/buttons/ha-call-service-button"; -import "../../../components/ha-service-description"; +import { fetchDevices, ZHADevice } from "../../../data/zha"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; -import "../ha-config-section"; -import { ItemSelectedEvent, NodeServiceData, ChangeEvent } from "./types"; -import "./zha-clusters"; -import "./zha-device-card"; -import { - updateDeviceRegistryEntry, - DeviceRegistryEntryMutableParams, -} from "../../../data/device_registry"; -import { reconfigureNode, fetchDevices, ZHADevice } from "../../../data/zha"; +import { ItemSelectedEvent, ZHADeviceRemovedEvent } from "./types"; declare global { // for fire event @@ -37,60 +35,25 @@ declare global { } } +@customElement("zha-node") export class ZHANode extends LitElement { - public hass?: HomeAssistant; - public isWide?: boolean; - private _showHelp: boolean; - private _selectedNodeIndex: number; - private _selectedNode?: ZHADevice; - private _serviceData?: {}; - private _nodes: ZHADevice[]; - private _userSelectedName?: string; + @property() public hass?: HomeAssistant; + @property() public isWide?: boolean; + @property() private _showHelp: boolean = false; + @property() private _selectedDeviceIndex: number = -1; + @property() private _selectedDevice?: ZHADevice; + @property() private _nodes: ZHADevice[] = []; - constructor() { - super(); - this._showHelp = false; - this._selectedNodeIndex = -1; - this._nodes = []; - } - - static get properties(): PropertyDeclarations { - return { - hass: {}, - isWide: {}, - _showHelp: {}, - _selectedNodeIndex: {}, - _selectedNode: {}, - _entities: {}, - _serviceData: {}, - _nodes: {}, - _userSelectedName: {}, - }; - } - - public firstUpdated(changedProperties: PropertyValues): void { - super.firstUpdated(changedProperties); - if (this._nodes.length === 0) { - this._fetchDevices(); - } - this.addEventListener("hass-service-called", (ev) => - this.serviceCalled(ev) - ); - } - - protected serviceCalled(ev): void { - // Check if this is for us - if (ev.detail.success && ev.detail.service === "remove") { - this._selectedNodeIndex = -1; - this._fetchDevices(); - } + public connectedCallback(): void { + super.connectedCallback(); + this._fetchDevices(); } protected render(): TemplateResult | void { return html`
- Node Management + Device Management
- Run ZHA commands that affect a single node. Pick a node to see a list - of available commands.

Note: Sleepy (battery powered) + Run ZHA commands that affect a single device. Pick a device to see a + list of available commands.

Note: Sleepy (battery powered) devices need to be awake when executing commands against them. You can generally wake a sleepy device by triggering it.

Some devices such as Xiaomi sensors have a wake up button that you can @@ -108,11 +71,15 @@ export class ZHANode extends LitElement {
- + ${this._nodes.map( (entry) => html` @@ -128,95 +95,36 @@ export class ZHANode extends LitElement {
${this._showHelp ? html` -
- Select node to view per-node options +
+ Select device to view per-device options
` : ""} - ${this._selectedNodeIndex !== -1 + ${this._selectedDeviceIndex !== -1 ? html` ` : ""} - ${this._selectedNodeIndex !== -1 - ? html` -
- -
- ` - : ""} - ${this._selectedNodeIndex !== -1 ? this._renderNodeActions() : ""} - ${this._selectedNode ? this._renderClusters() : ""} + ${this._selectedDevice ? this._renderClusters() : ""} `; } - private _renderNodeActions(): TemplateResult { - return html` -
- Reconfigure Node - ${this._showHelp - ? html` -
- ${this.hass!.localize( - "ui.panel.config.zha.services.reconfigure" - )} -
- ` - : ""} - Remove Node - ${this._showHelp - ? html` - - ` - : ""} - Update Name - ${this._showHelp - ? html` -
- ${this.hass!.localize( - "ui.panel.config.zha.services.updateDeviceName" - )} -
- ` - : ""} -
- `; - } - private _renderClusters(): TemplateResult { return html` `; @@ -226,45 +134,10 @@ export class ZHANode extends LitElement { this._showHelp = !this._showHelp; } - private _selectedNodeChanged(event: ItemSelectedEvent): void { - this._selectedNodeIndex = event!.target!.selected; - this._selectedNode = this._nodes[this._selectedNodeIndex]; - this._userSelectedName = ""; - fireEvent(this, "zha-node-selected", { node: this._selectedNode }); - this._serviceData = this._computeNodeServiceData(); - } - - private async _onReconfigureNodeClick(): Promise { - if (this.hass) { - await reconfigureNode(this.hass, this._selectedNode!.ieee); - } - } - - private _onUserSelectedNameChanged(value: ChangeEvent): void { - this._userSelectedName = value.detail!.value; - } - - private async _onUpdateDeviceNameClick(): Promise { - if (this.hass) { - const values: DeviceRegistryEntryMutableParams = { - name_by_user: this._userSelectedName, - }; - - await updateDeviceRegistryEntry( - this.hass, - this._selectedNode!.device_reg_id, - values - ); - - this._selectedNode!.user_given_name = this._userSelectedName!; - this._userSelectedName = ""; - } - } - - private _computeNodeServiceData(): NodeServiceData { - return { - ieee_address: this._selectedNode!.ieee, - }; + private _selectedDeviceChanged(event: ItemSelectedEvent): void { + this._selectedDeviceIndex = event!.target!.selected; + this._selectedDevice = this._nodes[this._selectedDeviceIndex]; + fireEvent(this, "zha-node-selected", { node: this._selectedDevice }); } private async _fetchDevices() { @@ -273,6 +146,13 @@ export class ZHANode extends LitElement { }); } + private _onDeviceRemoved(event: ZHADeviceRemovedEvent): void { + this._selectedDeviceIndex = -1; + this._nodes.splice(this._nodes.indexOf(event.detail!.device!), 1); + this._selectedDevice = undefined; + fireEvent(this, "zha-node-selected", { node: this._selectedDevice }); + } + static get styles(): CSSResult[] { return [ haStyle, @@ -298,13 +178,10 @@ export class ZHANode extends LitElement { } .help-text { + color: grey; padding-left: 28px; padding-right: 28px; - } - - .helpText { - color: grey; - padding: 16px; + padding-bottom: 16px; } paper-card { @@ -355,12 +232,6 @@ export class ZHANode extends LitElement { right: 0; color: var(--primary-color); } - - .input-text { - padding-left: 28px; - padding-right: 28px; - padding-bottom: 10px; - } `, ]; } @@ -371,5 +242,3 @@ declare global { "zha-node": ZHANode; } } - -customElements.define("zha-node", ZHANode); diff --git a/src/translations/en.json b/src/translations/en.json index 1ec7543e42..afd77b714c 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -877,7 +877,18 @@ "description": "Zigbee Home Automation network management", "services": { "reconfigure": "Reconfigure ZHA device (heal device). Use this if you are having issues with the device. If the device in question is a battery powered device please ensure it is awake and accepting commands when you use this service.", - "updateDeviceName": "Set a custom name for this device in the device registry." + "updateDeviceName": "Set a custom name for this device in the device registry.", + "remove": "Remove a device from the ZigBee network." + }, + "device_card": { + "device_name_placeholder": "User given name", + "area_picker_label": "Area", + "update_name_button": "Update Name" + }, + "add_device_page": { + "header": "Zigbee Home Automation - Add Devices", + "spinner": "Searching for ZHA Zigbee devices...", + "discovery_text": "Discovered devices will show up here. Follow the instructions for your device(s) and place the device(s) in pairing mode." } }, "zwave": { From 004892e11ac01c106a7978fead9e19c4f94bc75a Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Tue, 26 Mar 2019 00:18:16 -0500 Subject: [PATCH 15/29] =?UTF-8?q?=F0=9F=94=A7=20Remove=20unnecessary=20re-?= =?UTF-8?q?renders=20(#3014)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🔧 Remove unnecessary re-renders * address review comments * address review comments --- .../lovelace/cards/hui-picture-entity-card.ts | 6 ++++ .../lovelace/cards/hui-picture-glance-card.ts | 34 +++++++++++++++++++ .../lovelace/cards/hui-plant-status-card.ts | 6 ++++ src/panels/lovelace/cards/hui-sensor-card.ts | 9 +++++ .../lovelace/elements/hui-icon-element.ts | 2 +- .../elements/hui-state-badge-element.ts | 6 ++++ .../elements/hui-state-icon-element.ts | 6 ++++ .../elements/hui-state-label-element.ts | 6 ++++ .../entity-rows/hui-climate-entity-row.ts | 6 ++++ .../entity-rows/hui-cover-entity-row.ts | 6 ++++ .../entity-rows/hui-group-entity-row.ts | 6 ++++ .../hui-input-number-entity-row.ts | 6 ++++ .../hui-input-select-entity-row.ts | 6 ++++ .../entity-rows/hui-input-text-entity-row.ts | 6 ++++ .../entity-rows/hui-lock-entity-row.ts | 6 ++++ .../hui-media-player-entity-row.ts | 6 ++++ .../entity-rows/hui-scene-entity-row.ts | 6 ++++ .../entity-rows/hui-script-entity-row.ts | 8 ++++- .../entity-rows/hui-sensor-entity-row.ts | 6 ++++ .../entity-rows/hui-text-entity-row.ts | 6 ++++ .../entity-rows/hui-timer-entity-row.ts | 9 +++++ .../entity-rows/hui-toggle-entity-row.ts | 6 ++++ .../special-rows/hui-call-service-row.ts | 2 +- 23 files changed, 163 insertions(+), 3 deletions(-) diff --git a/src/panels/lovelace/cards/hui-picture-entity-card.ts b/src/panels/lovelace/cards/hui-picture-entity-card.ts index b13ba4a60a..9a2334f923 100644 --- a/src/panels/lovelace/cards/hui-picture-entity-card.ts +++ b/src/panels/lovelace/cards/hui-picture-entity-card.ts @@ -6,6 +6,7 @@ import { property, css, CSSResult, + PropertyValues, } from "lit-element"; import { classMap } from "lit-html/directives/class-map"; @@ -23,6 +24,7 @@ import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace"; import { LovelaceCard } from "../types"; import { handleClick } from "../common/handle-click"; import { UNAVAILABLE } from "../../../data/entity"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; interface Config extends LovelaceCardConfig { entity: string; @@ -62,6 +64,10 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard { this._config = { show_name: true, show_state: true, ...config }; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/cards/hui-picture-glance-card.ts b/src/panels/lovelace/cards/hui-picture-glance-card.ts index 5306a9c4a7..f2de5b80e5 100644 --- a/src/panels/lovelace/cards/hui-picture-glance-card.ts +++ b/src/panels/lovelace/cards/hui-picture-glance-card.ts @@ -6,6 +6,7 @@ import { property, css, CSSResult, + PropertyValues, } from "lit-element"; import { classMap } from "lit-html/directives/class-map"; @@ -87,6 +88,39 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + if (changedProps.has("_config")) { + return true; + } + + const oldHass = changedProps.get("hass") as HomeAssistant | undefined; + if (!oldHass) { + return true; + } + + if (this._entitiesDialog) { + for (const entity of this._entitiesDialog) { + if ( + oldHass.states[entity.entity] !== this.hass!.states[entity.entity] + ) { + return true; + } + } + } + + if (this._entitiesToggle) { + for (const entity of this._entitiesToggle) { + if ( + oldHass.states[entity.entity] !== this.hass!.states[entity.entity] + ) { + return true; + } + } + } + + return false; + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/cards/hui-plant-status-card.ts b/src/panels/lovelace/cards/hui-plant-status-card.ts index 0304e9d307..80b7fa03bd 100644 --- a/src/panels/lovelace/cards/hui-plant-status-card.ts +++ b/src/panels/lovelace/cards/hui-plant-status-card.ts @@ -6,6 +6,7 @@ import { CSSResult, property, customElement, + PropertyValues, } from "lit-element"; import "../../../components/ha-card"; @@ -18,6 +19,7 @@ import { LovelaceCardEditor, LovelaceCard } from "../types"; import { HomeAssistant } from "../../../types"; import { LovelaceCardConfig } from "../../../data/lovelace"; import { fireEvent } from "../../../common/dom/fire_event"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; const SENSORS = { moisture: "hass:water", @@ -63,6 +65,10 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this.hass || !this._config) { return html``; diff --git a/src/panels/lovelace/cards/hui-sensor-card.ts b/src/panels/lovelace/cards/hui-sensor-card.ts index fa3770c3b5..ff6f980565 100644 --- a/src/panels/lovelace/cards/hui-sensor-card.ts +++ b/src/panels/lovelace/cards/hui-sensor-card.ts @@ -16,6 +16,7 @@ import { LovelaceCardConfig } from "../../../data/lovelace"; import { HomeAssistant } from "../../../types"; import { fireEvent } from "../../../common/dom/fire_event"; import { fetchRecent } from "../../../data/history"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import computeStateName from "../../../common/entity/compute_state_name"; @@ -272,6 +273,14 @@ class HuiSensorCard extends LitElement implements LovelaceCard { this._date = new Date(); } + protected shouldUpdate(changedProps: PropertyValues): boolean { + if (changedProps.has("_history")) { + return true; + } + + return hasConfigOrEntityChanged(this, changedProps); + } + protected updated(changedProps: PropertyValues) { super.updated(changedProps); if (!this._config || this._config.graph !== "line" || !this.hass) { diff --git a/src/panels/lovelace/elements/hui-icon-element.ts b/src/panels/lovelace/elements/hui-icon-element.ts index 87a4f959f3..489e9a6742 100644 --- a/src/panels/lovelace/elements/hui-icon-element.ts +++ b/src/panels/lovelace/elements/hui-icon-element.ts @@ -27,7 +27,7 @@ export interface Config extends LovelaceElementConfig { @customElement("hui-icon-element") export class HuiIconElement extends LitElement implements LovelaceElement { - @property() public hass?: HomeAssistant; + public hass?: HomeAssistant; @property() private _config?: Config; public setConfig(config: Config): void { diff --git a/src/panels/lovelace/elements/hui-state-badge-element.ts b/src/panels/lovelace/elements/hui-state-badge-element.ts index 3a73c9e0c6..6b191a678f 100644 --- a/src/panels/lovelace/elements/hui-state-badge-element.ts +++ b/src/panels/lovelace/elements/hui-state-badge-element.ts @@ -4,6 +4,7 @@ import { TemplateResult, customElement, property, + PropertyValues, } from "lit-element"; import "../../../components/entity/ha-state-label-badge"; @@ -12,6 +13,7 @@ import "../components/hui-warning-element"; import computeStateName from "../../../common/entity/compute_state_name"; import { LovelaceElement, LovelaceElementConfig } from "./types"; import { HomeAssistant } from "../../../types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; export interface Config extends LovelaceElementConfig { entity: string; @@ -31,6 +33,10 @@ export class HuiStateBadgeElement extends LitElement this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/elements/hui-state-icon-element.ts b/src/panels/lovelace/elements/hui-state-icon-element.ts index bd7fd773ff..59d57989cf 100644 --- a/src/panels/lovelace/elements/hui-state-icon-element.ts +++ b/src/panels/lovelace/elements/hui-state-icon-element.ts @@ -6,6 +6,7 @@ import { property, css, CSSResult, + PropertyValues, } from "lit-element"; import "../../../components/entity/state-badge"; @@ -17,6 +18,7 @@ import { longPress } from "../common/directives/long-press-directive"; import { LovelaceElement, LovelaceElementConfig } from "./types"; import { HomeAssistant } from "../../../types"; import { ActionConfig } from "../../../data/lovelace"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; export interface Config extends LovelaceElementConfig { entity: string; @@ -37,6 +39,10 @@ export class HuiStateIconElement extends LitElement implements LovelaceElement { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/elements/hui-state-label-element.ts b/src/panels/lovelace/elements/hui-state-label-element.ts index 3cbf939a75..87cc147ebe 100644 --- a/src/panels/lovelace/elements/hui-state-label-element.ts +++ b/src/panels/lovelace/elements/hui-state-label-element.ts @@ -6,6 +6,7 @@ import { property, css, CSSResult, + PropertyValues, } from "lit-element"; import "../../../components/entity/ha-state-label-badge"; @@ -18,6 +19,7 @@ import { longPress } from "../common/directives/long-press-directive"; import { LovelaceElement, LovelaceElementConfig } from "./types"; import { HomeAssistant } from "../../../types"; import { ActionConfig } from "../../../data/lovelace"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; interface Config extends LovelaceElementConfig { entity: string; @@ -40,6 +42,10 @@ class HuiStateLabelElement extends LitElement implements LovelaceElement { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-climate-entity-row.ts b/src/panels/lovelace/entity-rows/hui-climate-entity-row.ts index 586a29615f..c0596839a7 100644 --- a/src/panels/lovelace/entity-rows/hui-climate-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-climate-entity-row.ts @@ -6,6 +6,7 @@ import { css, CSSResult, customElement, + PropertyValues, } from "lit-element"; import "../../../components/ha-climate-state"; @@ -14,6 +15,7 @@ import "../components/hui-warning"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-climate-entity-row") class HuiClimateEntityRow extends LitElement implements EntityRow { @@ -29,6 +31,10 @@ class HuiClimateEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this.hass || !this._config) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts b/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts index 160c4d6760..f65a0e3ba4 100644 --- a/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts @@ -6,6 +6,7 @@ import { css, CSSResult, customElement, + PropertyValues, } from "lit-element"; import "../components/hui-generic-entity-row"; @@ -16,6 +17,7 @@ import "../components/hui-warning"; import { isTiltOnly } from "../../../util/cover-model"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-cover-entity-row") class HuiCoverEntityRow extends LitElement implements EntityRow { @@ -30,6 +32,10 @@ class HuiCoverEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-group-entity-row.ts b/src/panels/lovelace/entity-rows/hui-group-entity-row.ts index 165f4eb027..7a172b9a78 100644 --- a/src/panels/lovelace/entity-rows/hui-group-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-group-entity-row.ts @@ -4,6 +4,7 @@ import { TemplateResult, property, customElement, + PropertyValues, } from "lit-element"; import "../components/hui-generic-entity-row"; @@ -14,6 +15,7 @@ import computeStateDisplay from "../../../common/entity/compute_state_display"; import { DOMAINS_TOGGLE } from "../../../common/const"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-group-entity-row") class HuiGroupEntityRow extends LitElement implements EntityRow { @@ -28,6 +30,10 @@ class HuiGroupEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts index 12fd026996..2140fc3d14 100644 --- a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts @@ -6,6 +6,7 @@ import { customElement, css, CSSResult, + PropertyValues, } from "lit-element"; import "../components/hui-generic-entity-row"; @@ -16,6 +17,7 @@ import { computeRTLDirection } from "../../../common/util/compute_rtl"; import { EntityRow, EntityConfig } from "./types"; import { HomeAssistant } from "../../../types"; import { setValue } from "../../../data/input_text"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-input-number-entity-row") class HuiInputNumberEntityRow extends LitElement implements EntityRow { @@ -48,6 +50,10 @@ class HuiInputNumberEntityRow extends LitElement implements EntityRow { } } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts index ddb96a54a8..a17e16d314 100644 --- a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts @@ -6,6 +6,7 @@ import { css, CSSResult, customElement, + PropertyValues, } from "lit-element"; import { repeat } from "lit-html/directives/repeat"; import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; @@ -19,6 +20,7 @@ import computeStateName from "../../../common/entity/compute_state_name"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; import { setOption } from "../../../data/input-select"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-input-select-entity-row") class HuiInputSelectEntityRow extends LitElement implements EntityRow { @@ -34,6 +36,10 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this.hass || !this._config) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-input-text-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-text-entity-row.ts index 42376687cc..586441e16f 100644 --- a/src/panels/lovelace/entity-rows/hui-input-text-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-text-entity-row.ts @@ -4,6 +4,7 @@ import { TemplateResult, property, customElement, + PropertyValues, } from "lit-element"; import { PaperInputElement } from "@polymer/paper-input/paper-input"; @@ -13,6 +14,7 @@ import "../components/hui-warning"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; import { setValue } from "../../../data/input_text"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-input-text-entity-row") class HuiInputTextEntityRow extends LitElement implements EntityRow { @@ -27,6 +29,10 @@ class HuiInputTextEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts b/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts index 22d6fe6028..fd08fec0c4 100644 --- a/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts @@ -6,6 +6,7 @@ import { css, CSSResult, customElement, + PropertyValues, } from "lit-element"; import "../components/hui-generic-entity-row"; @@ -13,6 +14,7 @@ import "../components/hui-warning"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-lock-entity-row") class HuiLockEntityRow extends LitElement implements EntityRow { @@ -27,6 +29,10 @@ class HuiLockEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts index 28273dce7e..a3f3869cdd 100644 --- a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts @@ -6,6 +6,7 @@ import { CSSResult, property, customElement, + PropertyValues, } from "lit-element"; import "@polymer/paper-icon-button/paper-icon-button"; @@ -22,6 +23,7 @@ import { OFF_STATES, SUPPORT_PAUSE, } from "../../../data/media-player"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-media-player-entity-row") class HuiMediaPlayerEntityRow extends LitElement implements EntityRow { @@ -37,6 +39,10 @@ class HuiMediaPlayerEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this.hass || !this._config) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-scene-entity-row.ts b/src/panels/lovelace/entity-rows/hui-scene-entity-row.ts index a690adfc5c..38df289b59 100644 --- a/src/panels/lovelace/entity-rows/hui-scene-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-scene-entity-row.ts @@ -6,6 +6,7 @@ import { css, property, customElement, + PropertyValues, } from "lit-element"; import "../components/hui-generic-entity-row"; @@ -14,6 +15,7 @@ import "../components/hui-warning"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-scene-entity-row") class HuiSceneEntityRow extends LitElement implements EntityRow { @@ -28,6 +30,10 @@ class HuiSceneEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-script-entity-row.ts b/src/panels/lovelace/entity-rows/hui-script-entity-row.ts index 5d6dfe82ef..b11e144497 100644 --- a/src/panels/lovelace/entity-rows/hui-script-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-script-entity-row.ts @@ -6,6 +6,7 @@ import { CSSResult, css, customElement, + PropertyValues, } from "lit-element"; import "../components/hui-generic-entity-row"; @@ -14,10 +15,11 @@ import "../components/hui-warning"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-script-entity-row") class HuiScriptEntityRow extends LitElement implements EntityRow { - @property() public hass?: HomeAssistant; + public hass?: HomeAssistant; @property() private _config?: EntityConfig; @@ -28,6 +30,10 @@ class HuiScriptEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-sensor-entity-row.ts b/src/panels/lovelace/entity-rows/hui-sensor-entity-row.ts index 998ba9450c..96ec9b3a65 100644 --- a/src/panels/lovelace/entity-rows/hui-sensor-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-sensor-entity-row.ts @@ -6,6 +6,7 @@ import { CSSResult, css, customElement, + PropertyValues, } from "lit-element"; import "../components/hui-generic-entity-row"; @@ -14,6 +15,7 @@ import "../components/hui-warning"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; import computeStateDisplay from "../../../common/entity/compute_state_display"; @@ -34,6 +36,10 @@ class HuiSensorEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-text-entity-row.ts b/src/panels/lovelace/entity-rows/hui-text-entity-row.ts index 6c7e564262..eafd7f42c7 100644 --- a/src/panels/lovelace/entity-rows/hui-text-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-text-entity-row.ts @@ -6,6 +6,7 @@ import { CSSResult, css, customElement, + PropertyValues, } from "lit-element"; import "../components/hui-generic-entity-row"; @@ -14,6 +15,7 @@ import "../components/hui-warning"; import computeStateDisplay from "../../../common/entity/compute_state_display"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-text-entity-row") class HuiTextEntityRow extends LitElement implements EntityRow { @@ -28,6 +30,10 @@ class HuiTextEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts index 1bcd3e64ef..bbd27aa51b 100644 --- a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts @@ -15,6 +15,7 @@ import secondsToDuration from "../../../common/datetime/seconds_to_duration"; import { HomeAssistant } from "../../../types"; import { EntityConfig } from "./types"; import { HassEntity } from "home-assistant-js-websocket"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-timer-entity-row") class HuiTimerEntityRow extends LitElement { @@ -64,6 +65,14 @@ class HuiTimerEntityRow extends LitElement { `; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + if (changedProps.has("_timeRemaining")) { + return true; + } + + return hasConfigOrEntityChanged(this, changedProps); + } + protected updated(changedProps: PropertyValues) { super.updated(changedProps); diff --git a/src/panels/lovelace/entity-rows/hui-toggle-entity-row.ts b/src/panels/lovelace/entity-rows/hui-toggle-entity-row.ts index 0ac6a57ecc..22055d8316 100644 --- a/src/panels/lovelace/entity-rows/hui-toggle-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-toggle-entity-row.ts @@ -4,6 +4,7 @@ import { TemplateResult, customElement, property, + PropertyValues, } from "lit-element"; import "../components/hui-generic-entity-row"; @@ -14,6 +15,7 @@ import computeStateDisplay from "../../../common/entity/compute_state_display"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; @customElement("hui-toggle-entity-row") class HuiToggleEntityRow extends LitElement implements EntityRow { @@ -28,6 +30,10 @@ class HuiToggleEntityRow extends LitElement implements EntityRow { this._config = config; } + protected shouldUpdate(changedProps: PropertyValues): boolean { + return hasConfigOrEntityChanged(this, changedProps); + } + protected render(): TemplateResult | void { if (!this._config || !this.hass) { return html``; diff --git a/src/panels/lovelace/special-rows/hui-call-service-row.ts b/src/panels/lovelace/special-rows/hui-call-service-row.ts index 479f45d7e2..8226581b0b 100644 --- a/src/panels/lovelace/special-rows/hui-call-service-row.ts +++ b/src/panels/lovelace/special-rows/hui-call-service-row.ts @@ -17,7 +17,7 @@ import { HomeAssistant } from "../../../types"; @customElement("hui-call-service-row") class HuiCallServiceRow extends LitElement implements EntityRow { - @property() public hass?: HomeAssistant; + public hass?: HomeAssistant; @property() private _config?: CallServiceConfig; From 9a4215b5d52767810f7a62452fedabf1090d673a Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Tue, 26 Mar 2019 16:59:37 -0500 Subject: [PATCH 16/29] Upgrade mdi to 3.5.92 (#3007) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 618a216359..dd9ac63620 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "dependencies": { "@material/mwc-button": "^0.4.0", "@material/mwc-ripple": "^0.4.0", - "@mdi/svg": "^3.0.39", + "@mdi/svg": "3.5.95", "@polymer/app-layout": "^3.0.1", "@polymer/app-localize-behavior": "^3.0.1", "@polymer/app-route": "^3.0.2", diff --git a/yarn.lock b/yarn.lock index 0b82218a5a..954e3232a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -833,10 +833,10 @@ dependencies: "@material/feature-targeting" "^0.44.1" -"@mdi/svg@^3.0.39": - version "3.3.92" - resolved "https://registry.yarnpkg.com/@mdi/svg/-/svg-3.3.92.tgz#40a12670c46ed7673943b219e8410f90d0996e64" - integrity sha512-281S4dn6evXoT8b2yhTooYLiX53PBr7Z+A5snuoz6HspGrL6JSvedX2o7WhO6Cjt8aOi869HKNNZ/O7nUXrSsA== +"@mdi/svg@3.5.95": + version "3.5.95" + resolved "https://registry.yarnpkg.com/@mdi/svg/-/svg-3.5.95.tgz#9e5c3dda43957bb436b75d5e0f3f7e57d8d2efb7" + integrity sha512-OOHqPi6s6nEeOOvo9uZgdfLyTHGDiIXiAXtvIrCBbnU4mZFSHpskQUw7Yqmp/tluYzI6neLN5Dwy/vTusDcsdA== "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" From 44eaa3abad525196836ada4450c10b2b70e858d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Tue, 26 Mar 2019 23:31:43 +0100 Subject: [PATCH 17/29] A bit of cleanup in the card editor (#2984) * edit-card shouldn't need to know about the path * fix * Store config as object at all times, convert when necessary * Hidden is not a property of mwc-button. No need to hide anyway... --- .../card-editor/hui-dialog-edit-card.ts | 28 ++++- .../editor/card-editor/hui-edit-card.ts | 112 +++++++----------- 2 files changed, 65 insertions(+), 75 deletions(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts index 28651529ce..c0a058aeca 100644 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts @@ -12,6 +12,7 @@ import { LovelaceCardConfig } from "../../../../data/lovelace"; import "./hui-edit-card"; import "./hui-dialog-pick-card"; import { EditCardDialogParams } from "./show-edit-card-dialog"; +import { addCard, replaceCard } from "../config-util"; declare global { // for fire event @@ -32,19 +33,22 @@ export class HuiDialogEditCard extends LitElement { @property() private _cardConfig?: LovelaceCardConfig; + @property() private _newCard?: boolean; + constructor() { super(); this._cardPicked = this._cardPicked.bind(this); this._cancel = this._cancel.bind(this); + this._save = this._save.bind(this); } public async showDialog(params: EditCardDialogParams): Promise { this._params = params; + const [view, card] = params.path; + this._newCard = card !== undefined ? false : true; this._cardConfig = - params.path.length === 2 - ? (this._cardConfig = params.lovelace.config.views[ - params.path[0] - ].cards![params.path[1]]) + card !== undefined + ? params.lovelace.config.views[view].cards![card] : undefined; } @@ -66,9 +70,10 @@ export class HuiDialogEditCard extends LitElement { `; @@ -82,6 +87,19 @@ export class HuiDialogEditCard extends LitElement { this._params = undefined; this._cardConfig = undefined; } + + private async _save(cardConf: LovelaceCardConfig): Promise { + const lovelace = this._params!.lovelace; + await lovelace.saveConfig( + this._params!.path.length === 1 + ? addCard(lovelace.config, this._params!.path as [number], cardConf) + : replaceCard( + lovelace.config, + this._params!.path as [number, number], + cardConf + ) + ); + } } declare global { diff --git a/src/panels/lovelace/editor/card-editor/hui-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-edit-card.ts index 15644f5fa1..d44b13f41b 100644 --- a/src/panels/lovelace/editor/card-editor/hui-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-edit-card.ts @@ -33,10 +33,9 @@ import "./hui-card-preview"; // tslint:disable-next-line import { HuiCardPreview } from "./hui-card-preview"; import { LovelaceCardEditor, Lovelace } from "../../types"; -import { ConfigValue, ConfigError } from "../types"; +import { ConfigError } from "../types"; import { EntityConfig } from "../../entity-rows/types"; import { getCardElementTag } from "../../common/get-card-element-tag"; -import { addCard, replaceCard } from "../config-util"; import { afterNextRender } from "../../../../common/util/render-status"; declare global { @@ -58,15 +57,17 @@ export class HuiEditCard extends LitElement { public lovelace?: Lovelace; - public path?: [number] | [number, number]; - public closeDialog?: () => void; + public saveCard?: (cardConf: LovelaceCardConfig) => Promise; + + public newCard?: boolean; + @property() private _configElement?: LovelaceCardEditor | null; @property() private _uiEditor?: boolean; - @property() private _configValue?: ConfigValue; + @property() private _cardConfig?: LovelaceCardConfig; @property() private _configState?: string; @@ -76,8 +77,6 @@ export class HuiEditCard extends LitElement { @property() private _errorMsg?: TemplateResult; - private _cardType?: string; - private get _dialog(): PaperDialogElement { return this.shadowRoot!.querySelector("paper-dialog")!; } @@ -86,6 +85,20 @@ export class HuiEditCard extends LitElement { return this.shadowRoot!.querySelector("hui-card-preview")!; } + // tslint:disable-next-line + private __cardYaml: string | undefined; + + private get _cardYaml(): string | undefined { + if (!this.__cardYaml) { + this.__cardYaml = yaml.safeDump(this._cardConfig); + } + return this.__cardYaml; + } + + private set _cardYaml(yml: string | undefined) { + this.__cardYaml = yml; + } + public constructor() { super(); this._saving = false; @@ -98,7 +111,8 @@ export class HuiEditCard extends LitElement { return; } - this._configValue = { format: "yaml", value: undefined }; + this._cardConfig = undefined; + this._cardYaml = undefined; this._configState = "OK"; this._uiEditor = true; this._errorMsg = undefined; @@ -119,7 +133,7 @@ export class HuiEditCard extends LitElement { : html` @@ -162,7 +176,6 @@ export class HuiEditCard extends LitElement {
${this.hass!.localize("ui.common.cancel")} @@ -222,22 +234,9 @@ export class HuiEditCard extends LitElement { this._saving = true; - const cardConf: LovelaceCardConfig = - this._configValue!.format === "yaml" - ? yaml.safeLoad(this._configValue!.value!) - : this._configValue!.value!; - try { - const lovelace = this.lovelace!; - await lovelace.saveConfig( - this._creatingCard - ? addCard(lovelace.config, this.path as [number], cardConf) - : replaceCard( - lovelace.config, - this.path as [number, number], - cardConf - ) - ); + await this.saveCard!(this._cardConfig!); + this._cardYaml = undefined; this.closeDialog!(); } catch (err) { alert(`Saving failed: ${err.message}`); @@ -247,12 +246,9 @@ export class HuiEditCard extends LitElement { } private _handleYamlChanged(ev: CustomEvent): void { - this._configValue = { format: "yaml", value: ev.detail.value }; + this._cardConfig = yaml.safeLoad(ev.detail.value); try { - const config = yaml.safeLoad( - this._configValue.value - ) as LovelaceCardConfig; - this._updatePreview(config); + this._updatePreview(this._cardConfig!); this._configState = "OK"; } catch (err) { this._configState = "YAML_ERROR"; @@ -264,7 +260,7 @@ export class HuiEditCard extends LitElement { } private _handleUIConfigChanged(value: LovelaceCardConfig): void { - this._configValue = { format: "json", value }; + this._cardConfig = value; this._updatePreview(value); } @@ -294,35 +290,23 @@ export class HuiEditCard extends LitElement { } private async _toggleEditor(): Promise { - if (this._uiEditor && this._configValue!.format === "json") { - this._configValue = { - format: "yaml", - value: yaml.safeDump(this._configValue!.value), - }; - this._uiEditor = !this._uiEditor; - } else if (this._configElement && this._configValue!.format === "yaml") { - const yamlConfig = this._configValue!.value; - const cardConfig = yaml.safeLoad(yamlConfig) as LovelaceCardConfig; - this._uiEditor = !this._uiEditor; - if (cardConfig.type !== this._cardType) { - const succes = await this._loadConfigElement(cardConfig); - if (!succes) { - this._loadedDialog(); - } - this._cardType = cardConfig.type; + this._cardYaml = undefined; + if (this._uiEditor) { + this._uiEditor = false; + } else if (this._configElement) { + const success = await this._loadConfigElement(this._cardConfig!); + if (!success) { + this._loadedDialog(); } else { - this._configValue = { - format: "json", - value: cardConfig, - }; - this._configElement.setConfig(cardConfig); + this._uiEditor = true; + this._configElement.setConfig(this._cardConfig!); } } this._resizeDialog(); } private _isConfigValid(): boolean { - if (!this._configValue || !this._configValue.value) { + if (!this._cardConfig) { return false; } if (this._configState === "OK") { @@ -333,14 +317,10 @@ export class HuiEditCard extends LitElement { } private _isConfigChanged(): boolean { - if (this._creatingCard) { + if (this.newCard) { return true; } - const configValue = - this._configValue!.format === "yaml" - ? yaml.safeLoad(this._configValue!.value) - : this._configValue!.value; - return JSON.stringify(configValue) !== JSON.stringify(this.cardConfig); + return JSON.stringify(this._cardConfig) !== JSON.stringify(this.cardConfig); } private async _loadConfigElement(conf: LovelaceCardConfig): Promise { @@ -357,10 +337,11 @@ export class HuiEditCard extends LitElement { const elClass = customElements.get(tag); let configElement; + this._cardConfig = conf; + if (elClass && elClass.getConfigElement) { configElement = await elClass.getConfigElement(); } else { - this._configValue = { format: "yaml", value: yaml.safeDump(conf) }; this._updatePreview(conf); this._uiEditor = false; this._configElement = null; @@ -374,10 +355,6 @@ export class HuiEditCard extends LitElement { Your config is not supported by the UI editor:
${err.message}
Falling back to YAML editor. `; - this._configValue = { - format: "yaml", - value: yaml.safeDump(conf), - }; this._updatePreview(conf); this._uiEditor = false; this._configElement = null; @@ -388,17 +365,12 @@ export class HuiEditCard extends LitElement { configElement.addEventListener("config-changed", (ev) => this._handleUIConfigChanged(ev.detail.config) ); - this._configValue = { format: "json", value: conf }; this._configElement = configElement; await this.updateComplete; this._updatePreview(conf); return true; } - private get _creatingCard(): boolean { - return this.path!.length === 1; - } - private _openedChanged(ev): void { if (!ev.detail.value) { this.closeDialog!(); From 5080f4c2db5812234c1adb8e6806a49f7a03ef64 Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Wed, 27 Mar 2019 20:54:10 -0700 Subject: [PATCH 18/29] Allow auth provider bypass login form (#3025) --- src/auth/ha-auth-flow.js | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/auth/ha-auth-flow.js b/src/auth/ha-auth-flow.js index e07774c90b..ceb487a031 100644 --- a/src/auth/ha-auth-flow.js +++ b/src/auth/ha-auth-flow.js @@ -121,6 +121,12 @@ class HaAuthFlow extends localizeLiteMixin(PolymerElement) { const data = await response.json(); if (response.ok) { + // allow auth provider bypass the login form + if (data.type === "create_entry") { + this._redirect(data.result); + return; + } + this._updateStep(data); } else { this.setProperties({ @@ -138,6 +144,24 @@ class HaAuthFlow extends localizeLiteMixin(PolymerElement) { } } + _redirect(authCode) { + // OAuth 2: 3.1.2 we need to retain query component of a redirect URI + let url = this.redirectUri; + if (!url.includes("?")) { + url += "?"; + } else if (!url.endsWith("&")) { + url += "&"; + } + + url += `code=${encodeURIComponent(authCode)}`; + + if (this.oauth2State) { + url += `&state=${encodeURIComponent(this.oauth2State)}`; + } + + document.location = url; + } + _updateStep(step) { const props = { _step: step, @@ -229,21 +253,7 @@ class HaAuthFlow extends localizeLiteMixin(PolymerElement) { const newStep = await response.json(); if (newStep.type === "create_entry") { - // OAuth 2: 3.1.2 we need to retain query component of a redirect URI - let url = this.redirectUri; - if (!url.includes("?")) { - url += "?"; - } else if (!url.endsWith("&")) { - url += "&"; - } - - url += `code=${encodeURIComponent(newStep.result)}`; - - if (this.oauth2State) { - url += `&state=${encodeURIComponent(this.oauth2State)}`; - } - - document.location = url; + this._redirect(newStep.result); return; } this._updateStep(newStep); From c95a44c570fdadd16d5b7a9202884ca2873d65f3 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Wed, 27 Mar 2019 23:07:04 -0500 Subject: [PATCH 19/29] Consider "on" as valid media state (#3020) --- src/util/hass-media-player-model.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/util/hass-media-player-model.js b/src/util/hass-media-player-model.js index 10c32fc09d..79d837eeae 100644 --- a/src/util/hass-media-player-model.js +++ b/src/util/hass-media-player-model.js @@ -37,7 +37,9 @@ export default class MediaPlayerEntity { } get hasMediaControl() { - return ["playing", "paused", "unknown"].indexOf(this.stateObj.state) !== -1; + return ( + ["playing", "paused", "unknown", "on"].indexOf(this.stateObj.state) !== -1 + ); } get volumeSliderValue() { From b3f9432ae1bc53d4ebb91641e64469e5a543a151 Mon Sep 17 00:00:00 2001 From: yosilevy <37745463+yosilevy@users.noreply.github.com> Date: Thu, 28 Mar 2019 06:10:07 +0200 Subject: [PATCH 20/29] Tab fix in yaml-editor edit card (#3008) * Fixed tabs not working in yaml editor in edit card * Improved docs * Fixed comments * Added dependencies * Added typescript mapping * Fixed data type issue + removed depednency since it breaks the UI. Non final. * Added iron-overlay-behavior package * Added dependency * Update iron-overlay-behavior * Lint --- package.json | 4 +- .../lovelace/components/dialog/ha-dialog.ts | 26 ++++++ .../dialog/ha-iron-focusables-helper.js | 90 +++++++++++++++++++ .../lovelace/components/hui-yaml-editor.ts | 4 + .../editor/card-editor/hui-edit-card.ts | 13 +-- yarn.lock | 8 +- 6 files changed, 134 insertions(+), 11 deletions(-) create mode 100644 src/panels/lovelace/components/dialog/ha-dialog.ts create mode 100644 src/panels/lovelace/components/dialog/ha-iron-focusables-helper.js diff --git a/package.json b/package.json index dd9ac63620..d049b1ca4b 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "@polymer/iron-input": "^3.0.1", "@polymer/iron-label": "^3.0.1", "@polymer/iron-media-query": "^3.0.1", + "@polymer/iron-overlay-behavior": "^3.0.2", "@polymer/iron-pages": "^3.0.1", "@polymer/iron-resizable-behavior": "^3.0.1", "@polymer/neon-animation": "^3.0.1", @@ -167,7 +168,8 @@ "@webcomponents/webcomponentsjs": "^2.2.6", "@webcomponents/shadycss": "^1.9.0", "@vaadin/vaadin-overlay": "3.2.2", - "@vaadin/vaadin-lumo-styles": "1.3.0" + "@vaadin/vaadin-lumo-styles": "1.3.0", + "@polymer/iron-overlay-behavior": "^3.0.2" }, "main": "src/home-assistant.js", "husky": { diff --git a/src/panels/lovelace/components/dialog/ha-dialog.ts b/src/panels/lovelace/components/dialog/ha-dialog.ts new file mode 100644 index 0000000000..25be5b934e --- /dev/null +++ b/src/panels/lovelace/components/dialog/ha-dialog.ts @@ -0,0 +1,26 @@ +import "@polymer/paper-dialog/paper-dialog"; +import { mixinBehaviors } from "@polymer/polymer/lib/legacy/class"; +import { HaIronFocusablesHelper } from "./ha-iron-focusables-helper.js"; + +const paperDialogClass = customElements.get("paper-dialog"); + +// behavior that will override existing iron-overlay-behavior and call the fixed implementation +const haTabFixBehaviorImpl = { + get _focusableNodes() { + return HaIronFocusablesHelper.getTabbableNodes(this); + }, +}; + +// paper-dialog that uses the haTabFixBehaviorImpl behvaior +// export class HaPaperDialog extends paperDialogClass {} +export class HaPaperDialog extends mixinBehaviors( + [haTabFixBehaviorImpl], + paperDialogClass +) {} + +declare global { + interface HTMLElementTagNameMap { + "ha-paper-dialog": HaPaperDialog; + } +} +customElements.define("ha-paper-dialog", HaPaperDialog); diff --git a/src/panels/lovelace/components/dialog/ha-iron-focusables-helper.js b/src/panels/lovelace/components/dialog/ha-iron-focusables-helper.js new file mode 100644 index 0000000000..4ae78090e5 --- /dev/null +++ b/src/panels/lovelace/components/dialog/ha-iron-focusables-helper.js @@ -0,0 +1,90 @@ +/** +@license +Copyright (c) 2016 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at +http://polymer.github.io/LICENSE.txt The complete set of authors may be found at +http://polymer.github.io/AUTHORS.txt The complete set of contributors may be +found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as +part of the polymer project is also subject to an additional IP rights grant +found at http://polymer.github.io/PATENTS.txt +*/ +/* + Fixes issue with not using shadow dom properly in iron-overlay-behavior/icon-focusables-helper.js +*/ +import { dom } from "@polymer/polymer/lib/legacy/polymer.dom.js"; + +import { IronFocusablesHelper } from "@polymer/iron-overlay-behavior/iron-focusables-helper.js"; + +export const HaIronFocusablesHelper = { + /** + * Returns a sorted array of tabbable nodes, including the root node. + * It searches the tabbable nodes in the light and shadow dom of the chidren, + * sorting the result by tabindex. + * @param {!Node} node + * @return {!Array} + */ + getTabbableNodes: function(node) { + var result = []; + // If there is at least one element with tabindex > 0, we need to sort + // the final array by tabindex. + var needsSortByTabIndex = this._collectTabbableNodes(node, result); + if (needsSortByTabIndex) { + return IronFocusablesHelper._sortByTabIndex(result); + } + return result; + }, + + /** + * Searches for nodes that are tabbable and adds them to the `result` array. + * Returns if the `result` array needs to be sorted by tabindex. + * @param {!Node} node The starting point for the search; added to `result` + * if tabbable. + * @param {!Array} result + * @return {boolean} + * @private + */ + _collectTabbableNodes: function(node, result) { + // If not an element or not visible, no need to explore children. + if ( + node.nodeType !== Node.ELEMENT_NODE || + !IronFocusablesHelper._isVisible(node) + ) { + return false; + } + var element = /** @type {!HTMLElement} */ (node); + var tabIndex = IronFocusablesHelper._normalizedTabIndex(element); + var needsSort = tabIndex > 0; + if (tabIndex >= 0) { + result.push(element); + } + + // In ShadowDOM v1, tab order is affected by the order of distrubution. + // E.g. getTabbableNodes(#root) in ShadowDOM v1 should return [#A, #B]; + // in ShadowDOM v0 tab order is not affected by the distrubution order, + // in fact getTabbableNodes(#root) returns [#B, #A]. + //
+ // + // + // + // + // + // + //
+ // TODO(valdrin) support ShadowDOM v1 when upgrading to Polymer v2.0. + var children; + if (element.localName === "content" || element.localName === "slot") { + children = dom(element).getDistributedNodes(); + } else { + // ///////////////////////// + // Use shadow root if possible, will check for distributed nodes. + // THIS IS THE CHANGED LINE + children = dom(element.shadowRoot || element.root || element).children; + // ///////////////////////// + } + for (var i = 0; i < children.length; i++) { + // Ensure method is always invoked to collect tabbable children. + needsSort = this._collectTabbableNodes(children[i], result) || needsSort; + } + return needsSort; + }, +}; diff --git a/src/panels/lovelace/components/hui-yaml-editor.ts b/src/panels/lovelace/components/hui-yaml-editor.ts index d0efdf1eed..4f35f85d80 100644 --- a/src/panels/lovelace/components/hui-yaml-editor.ts +++ b/src/panels/lovelace/components/hui-yaml-editor.ts @@ -96,6 +96,10 @@ export class HuiYamlEditor extends HTMLElement { tabSize: 2, autofocus: true, viewportMargin: Infinity, + extraKeys: { + Tab: "indentMore", + "Shift-Tab": "indentLess", + }, gutters: this._hass && computeRTL(this._hass!) ? ["rtl-gutter", "CodeMirror-linenumbers"] diff --git a/src/panels/lovelace/editor/card-editor/hui-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-edit-card.ts index d44b13f41b..93ce59eaf2 100644 --- a/src/panels/lovelace/editor/card-editor/hui-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-edit-card.ts @@ -15,9 +15,10 @@ import { haStyleDialog } from "../../../../resources/styles"; import "@polymer/paper-spinner/paper-spinner"; import "@polymer/paper-dialog/paper-dialog"; +import "../../components/dialog/ha-dialog"; // This is not a duplicate import, one is for types, one is for element. // tslint:disable-next-line -import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog"; +import { HaPaperDialog } from "../../components/dialog/ha-dialog"; import "@material/mwc-button"; import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable"; import { HomeAssistant } from "../../../../types"; @@ -77,8 +78,8 @@ export class HuiEditCard extends LitElement { @property() private _errorMsg?: TemplateResult; - private get _dialog(): PaperDialogElement { - return this.shadowRoot!.querySelector("paper-dialog")!; + private get _dialog(): HaPaperDialog { + return this.shadowRoot!.querySelector("ha-paper-dialog")!; } private get _previewEl(): HuiCardPreview { @@ -147,7 +148,7 @@ export class HuiEditCard extends LitElement { } return html` - ` : ""} - + `; } @@ -218,7 +219,7 @@ export class HuiEditCard extends LitElement { private async _resizeDialog(): Promise { await this.updateComplete; - fireEvent(this._dialog, "iron-resize"); + fireEvent(this._dialog as HTMLElement, "iron-resize"); } private async _save(): Promise { diff --git a/yarn.lock b/yarn.lock index 954e3232a4..7ed5694ce9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1096,10 +1096,10 @@ dependencies: "@polymer/polymer" "^3.0.0" -"@polymer/iron-overlay-behavior@^3.0.0-pre.27": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@polymer/iron-overlay-behavior/-/iron-overlay-behavior-3.0.1.tgz#04746be26c7f0ac3b4e80ef363fcb478425dd677" - integrity sha512-7XDaPVmH90G/hiyWdwv0VG+E4B2xpiWGhql8ghHg7Ik1E4gNCZ7pdeTvjnawfycjrsod0ZezhKOFavYWAaXVxA== +"@polymer/iron-overlay-behavior@^3.0.0-pre.27", "@polymer/iron-overlay-behavior@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@polymer/iron-overlay-behavior/-/iron-overlay-behavior-3.0.2.tgz#6a12a3f4eab4721eb6978ed950be534c9c283983" + integrity sha512-j1qmt6mJHCwpe1mKOvqK5kcCUPQr5LSrlqpgRDbUuLgUfNJ/vGTipjrkBlfbEUagm5FEQdc1VLPLSQP6WVuP9g== dependencies: "@polymer/iron-a11y-keys-behavior" "^3.0.0-pre.26" "@polymer/iron-fit-behavior" "^3.0.0-pre.26" From 1d24b83e5ccfa87165521d3ebe71e3806e04a346 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Wed, 27 Mar 2019 23:10:55 -0500 Subject: [PATCH 21/29] Align configs (#3019) * Align configurations * cleanup * fix imports --- .../lovelace/cards/hui-alarm-panel-card.ts | 20 +- .../lovelace/cards/hui-conditional-card.ts | 10 +- .../lovelace/cards/hui-empty-state-card.ts | 9 +- .../lovelace/cards/hui-entities-card.ts | 21 +- .../lovelace/cards/hui-entity-button-card.ts | 18 +- .../lovelace/cards/hui-entity-filter-card.ts | 9 +- src/panels/lovelace/cards/hui-error-card.ts | 10 +- src/panels/lovelace/cards/hui-gauge-card.ts | 30 +-- src/panels/lovelace/cards/hui-glance-card.ts | 28 +-- src/panels/lovelace/cards/hui-iframe-card.ts | 12 +- src/panels/lovelace/cards/hui-light-card.ts | 28 +-- src/panels/lovelace/cards/hui-map-card.ts | 13 +- .../lovelace/cards/hui-markdown-card.ts | 11 +- .../lovelace/cards/hui-media-control-card.js | 5 - src/panels/lovelace/cards/hui-picture-card.ts | 12 +- .../cards/hui-picture-elements-card.ts | 17 +- .../lovelace/cards/hui-picture-entity-card.ts | 19 +- .../lovelace/cards/hui-picture-glance-card.ts | 30 +-- .../lovelace/cards/hui-plant-status-card.ts | 17 +- src/panels/lovelace/cards/hui-sensor-card.ts | 29 +-- .../lovelace/cards/hui-shopping-list-card.ts | 10 +- src/panels/lovelace/cards/hui-stack-card.ts | 10 +- .../lovelace/cards/hui-thermostat-card.ts | 12 +- .../cards/hui-weather-forecast-card.js | 6 - src/panels/lovelace/cards/types.ts | 200 ++++++++++++++++++ .../common/generate-lovelace-config.ts | 4 +- .../components/hui-generic-entity-row.ts | 8 +- .../hui-alarm-panel-card-editor.ts | 6 +- .../hui-entities-card-editor.ts | 16 +- .../hui-entity-button-card-editor.ts | 14 +- .../config-elements/hui-gauge-card-editor.ts | 12 +- .../config-elements/hui-glance-card-editor.ts | 14 +- .../config-elements/hui-iframe-card-editor.ts | 6 +- .../config-elements/hui-light-card-editor.ts | 12 +- .../config-elements/hui-map-card-editor.ts | 8 +- .../hui-markdown-card-editor.ts | 6 +- .../hui-media-control-card-editor.ts | 6 +- .../hui-picture-card-editor.ts | 10 +- .../hui-plant-status-card-editor.ts | 12 +- .../config-elements/hui-sensor-card-editor.ts | 12 +- .../hui-shopping-list-editor.ts | 6 +- .../hui-thermostat-card-editor.ts | 12 +- .../hui-weather-forecast-card-editor.ts | 10 +- .../elements/hui-conditional-element.ts | 17 +- .../lovelace/elements/hui-icon-element.ts | 15 +- .../lovelace/elements/hui-image-element.ts | 19 +- .../elements/hui-service-button-element.ts | 12 +- .../elements/hui-state-badge-element.ts | 10 +- .../elements/hui-state-icon-element.ts | 13 +- .../elements/hui-state-label-element.ts | 15 +- src/panels/lovelace/elements/types.ts | 51 +++++ .../entity-rows/hui-group-entity-row.ts | 1 + .../hui-input-select-entity-row.ts | 1 + .../entity-rows/hui-text-entity-row.ts | 1 + .../entity-rows/hui-timer-entity-row.ts | 1 + 55 files changed, 463 insertions(+), 453 deletions(-) create mode 100644 src/panels/lovelace/cards/types.ts diff --git a/src/panels/lovelace/cards/hui-alarm-panel-card.ts b/src/panels/lovelace/cards/hui-alarm-panel-card.ts index 921c0f4640..8b99421f7e 100644 --- a/src/panels/lovelace/cards/hui-alarm-panel-card.ts +++ b/src/panels/lovelace/cards/hui-alarm-panel-card.ts @@ -10,17 +10,17 @@ import { } from "lit-element"; import { classMap } from "lit-html/directives/class-map"; +import "../../../components/ha-card"; +import "../../../components/ha-label-badge"; +import "../components/hui-warning"; + import { LovelaceCard } from "../types"; import { HomeAssistant } from "../../../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; import { callAlarmAction, FORMAT_NUMBER, } from "../../../data/alarm_control_panel"; - -import "../../../components/ha-card"; -import "../../../components/ha-label-badge"; -import "../components/hui-warning"; +import { AlarmPanelCardConfig } from "./types"; const ICONS = { armed_away: "hass:shield-lock", @@ -34,12 +34,6 @@ const ICONS = { const BUTTONS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "clear"]; -export interface Config extends LovelaceCardConfig { - entity: string; - name?: string; - states?: string[]; -} - @customElement("hui-alarm-panel-card") class HuiAlarmPanelCard extends LitElement implements LovelaceCard { public static async getConfigElement() { @@ -53,7 +47,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: AlarmPanelCardConfig; @property() private _code?: string; @@ -69,7 +63,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard { : 8; } - public setConfig(config: Config): void { + public setConfig(config: AlarmPanelCardConfig): void { if ( !config || !config.entity || diff --git a/src/panels/lovelace/cards/hui-conditional-card.ts b/src/panels/lovelace/cards/hui-conditional-card.ts index c0c7e39d68..45907b3229 100644 --- a/src/panels/lovelace/cards/hui-conditional-card.ts +++ b/src/panels/lovelace/cards/hui-conditional-card.ts @@ -1,22 +1,16 @@ import { createCardElement } from "../common/create-card-element"; import { computeCardSize } from "../common/compute-card-size"; import { - Condition, checkConditionsMet, validateConditionalConfig, } from "../../lovelace/common/validate-condition"; import { HomeAssistant } from "../../../types"; import { LovelaceCard } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; - -interface Config extends LovelaceCardConfig { - card: LovelaceCardConfig; - conditions: Condition[]; -} +import { ConditionalCardConfig } from "./types"; class HuiConditionalCard extends HTMLElement implements LovelaceCard { private _hass?: HomeAssistant; - private _config?: Config; + private _config?: ConditionalCardConfig; private _card?: LovelaceCard; public setConfig(config) { diff --git a/src/panels/lovelace/cards/hui-empty-state-card.ts b/src/panels/lovelace/cards/hui-empty-state-card.ts index ed3553685f..4090fdffd8 100644 --- a/src/panels/lovelace/cards/hui-empty-state-card.ts +++ b/src/panels/lovelace/cards/hui-empty-state-card.ts @@ -11,13 +11,8 @@ import { import "@polymer/paper-card/paper-card"; import { LovelaceCard } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; import { HomeAssistant } from "../../../types"; - -export interface Config extends LovelaceCardConfig { - content: string; - title?: string; -} +import { EmptyStateCardConfig } from "./types"; @customElement("hui-empty-state-card") export class HuiEmptyStateCard extends LitElement implements LovelaceCard { @@ -27,7 +22,7 @@ export class HuiEmptyStateCard extends LitElement implements LovelaceCard { return 2; } - public setConfig(_config: Config): void { + public setConfig(_config: EmptyStateCardConfig): void { // tslint:disable-next-line } diff --git a/src/panels/lovelace/cards/hui-entities-card.ts b/src/panels/lovelace/cards/hui-entities-card.ts index 6b057ab09e..3ff8951ece 100644 --- a/src/panels/lovelace/cards/hui-entities-card.ts +++ b/src/panels/lovelace/cards/hui-entities-card.ts @@ -15,30 +15,15 @@ import "../components/hui-entities-toggle"; import { fireEvent } from "../../../common/dom/fire_event"; import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const"; import { HomeAssistant } from "../../../types"; -import { EntityConfig, EntityRow } from "../entity-rows/types"; +import { EntityRow } from "../entity-rows/types"; import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; import { processConfigEntities } from "../common/process-config-entities"; import { createRowElement } from "../common/create-row-element"; +import { EntitiesCardConfig, EntitiesCardEntityConfig } from "./types"; + import computeDomain from "../../../common/entity/compute_domain"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; -export interface EntitiesCardEntityConfig extends EntityConfig { - type?: string; - secondary_info?: "entity-id" | "last-changed"; - action_name?: string; - service?: string; - service_data?: object; - url?: string; -} - -export interface EntitiesCardConfig extends LovelaceCardConfig { - show_header_toggle?: boolean; - title?: string; - entities: EntitiesCardEntityConfig[]; - theme?: string; -} - @customElement("hui-entities-card") class HuiEntitiesCard extends LitElement implements LovelaceCard { public static async getConfigElement(): Promise { diff --git a/src/panels/lovelace/cards/hui-entity-button-card.ts b/src/panels/lovelace/cards/hui-entity-button-card.ts index 25b79be422..5178f1d1ab 100644 --- a/src/panels/lovelace/cards/hui-entity-button-card.ts +++ b/src/panels/lovelace/cards/hui-entity-button-card.ts @@ -21,23 +21,13 @@ import computeStateDomain from "../../../common/entity/compute_state_domain"; import computeStateName from "../../../common/entity/compute_state_name"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import computeDomain from "../../../common/entity/compute_domain"; + import { HomeAssistant, LightEntity } from "../../../types"; import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace"; import { longPress } from "../common/directives/long-press-directive"; import { handleClick } from "../common/handle-click"; import { DOMAINS_TOGGLE } from "../../../common/const"; - -export interface Config extends LovelaceCardConfig { - entity: string; - name?: string; - snow_name?: boolean; - icon?: string; - show_icon?: boolean; - theme?: string; - tap_action?: ActionConfig; - hold_action?: ActionConfig; -} +import { EntityButtonCardConfig } from "./types"; @customElement("hui-entity-button-card") class HuiEntityButtonCard extends LitElement implements LovelaceCard { @@ -57,13 +47,13 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: EntityButtonCardConfig; public getCardSize(): number { return 2; } - public setConfig(config: Config): void { + public setConfig(config: EntityButtonCardConfig): void { if (!isValidEntityId(config.entity)) { throw new Error("Invalid Entity"); } diff --git a/src/panels/lovelace/cards/hui-entity-filter-card.ts b/src/panels/lovelace/cards/hui-entity-filter-card.ts index 10126c2df2..15b8636224 100644 --- a/src/panels/lovelace/cards/hui-entity-filter-card.ts +++ b/src/panels/lovelace/cards/hui-entity-filter-card.ts @@ -4,14 +4,7 @@ import { LovelaceCard } from "../types"; import { LovelaceCardConfig } from "../../../data/lovelace"; import { EntityConfig } from "../entity-rows/types"; import { HomeAssistant } from "../../../types"; - -export interface EntityFilterCardConfig extends LovelaceCardConfig { - type: "entity-filter"; - entities: Array; - state_filter: string[]; - card: Partial; - show_empty?: boolean; -} +import { EntityFilterCardConfig } from "./types"; class EntityFilterCard extends HTMLElement implements LovelaceCard { public isPanel?: boolean; diff --git a/src/panels/lovelace/cards/hui-error-card.ts b/src/panels/lovelace/cards/hui-error-card.ts index 946f782a79..62bbfe4548 100644 --- a/src/panels/lovelace/cards/hui-error-card.ts +++ b/src/panels/lovelace/cards/hui-error-card.ts @@ -11,11 +11,7 @@ import { import { LovelaceCard } from "../types"; import { LovelaceCardConfig } from "../../../data/lovelace"; import { HomeAssistant } from "../../../types"; - -interface Config extends LovelaceCardConfig { - error: string; - origConfig: LovelaceCardConfig; -} +import { ErrorCardConfig } from "./types"; export const createErrorCardElement = (config) => { const el = document.createElement("hui-error-card"); @@ -33,13 +29,13 @@ export const createErrorCardConfig = (error, origConfig) => ({ export class HuiErrorCard extends LitElement implements LovelaceCard { public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: ErrorCardConfig; public getCardSize(): number { return 4; } - public setConfig(config: Config): void { + public setConfig(config: ErrorCardConfig): void { this._config = config; } diff --git a/src/panels/lovelace/cards/hui-gauge-card.ts b/src/panels/lovelace/cards/hui-gauge-card.ts index 96fcf946fe..677d8378d0 100644 --- a/src/panels/lovelace/cards/hui-gauge-card.ts +++ b/src/panels/lovelace/cards/hui-gauge-card.ts @@ -13,31 +13,15 @@ import { styleMap } from "lit-html/directives/style-map"; import "../../../components/ha-card"; import "../components/hui-warning"; -import { LovelaceCardConfig } from "../../../data/lovelace"; -import { HomeAssistant } from "../../../types"; -import { fireEvent } from "../../../common/dom/fire_event"; -import { hasConfigOrEntityChanged } from "../common/has-changed"; -import { LovelaceCard, LovelaceCardEditor } from "../types"; - import isValidEntityId from "../../../common/entity/valid_entity_id"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import computeStateName from "../../../common/entity/compute_state_name"; -export interface SeverityConfig { - green?: number; - yellow?: number; - red?: number; -} - -export interface Config extends LovelaceCardConfig { - entity: string; - name?: string; - unit?: string; - min?: number; - max?: number; - severity?: SeverityConfig; - theme?: string; -} +import { HomeAssistant } from "../../../types"; +import { fireEvent } from "../../../common/dom/fire_event"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; +import { LovelaceCard, LovelaceCardEditor } from "../types"; +import { GaugeCardConfig } from "./types"; export const severityMap = { red: "var(--label-badge-red)", @@ -58,7 +42,7 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: GaugeCardConfig; private _updated?: boolean; @@ -66,7 +50,7 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { return 2; } - public setConfig(config: Config): void { + public setConfig(config: GaugeCardConfig): void { if (!config || !config.entity) { throw new Error("Invalid card configuration"); } diff --git a/src/panels/lovelace/cards/hui-glance-card.ts b/src/panels/lovelace/cards/hui-glance-card.ts index 8ec574c234..21dd867d9f 100644 --- a/src/panels/lovelace/cards/hui-glance-card.ts +++ b/src/panels/lovelace/cards/hui-glance-card.ts @@ -10,14 +10,6 @@ import { } from "lit-element"; import { classMap } from "lit-html/directives/class-map"; -import { HomeAssistant } from "../../../types"; -import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace"; -import { longPress } from "../common/directives/long-press-directive"; -import { EntityConfig } from "../entity-rows/types"; -import { processConfigEntities } from "../common/process-config-entities"; -import { handleClick } from "../common/handle-click"; - import computeStateDisplay from "../../../common/entity/compute_state_display"; import computeStateName from "../../../common/entity/compute_state_name"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; @@ -27,20 +19,12 @@ import "../../../components/ha-card"; import "../../../components/ha-icon"; import "../components/hui-warning-element"; -export interface ConfigEntity extends EntityConfig { - tap_action?: ActionConfig; - hold_action?: ActionConfig; -} - -export interface GlanceCardConfig extends LovelaceCardConfig { - show_name?: boolean; - show_state?: boolean; - show_icon?: boolean; - title?: string; - theme?: string; - entities: ConfigEntity[]; - columns?: number; -} +import { HomeAssistant } from "../../../types"; +import { LovelaceCard, LovelaceCardEditor } from "../types"; +import { longPress } from "../common/directives/long-press-directive"; +import { processConfigEntities } from "../common/process-config-entities"; +import { handleClick } from "../common/handle-click"; +import { GlanceCardConfig, ConfigEntity } from "./types"; @customElement("hui-glance-card") export class HuiGlanceCard extends LitElement implements LovelaceCard { diff --git a/src/panels/lovelace/cards/hui-iframe-card.ts b/src/panels/lovelace/cards/hui-iframe-card.ts index e49e149d47..b74dc68cdb 100644 --- a/src/panels/lovelace/cards/hui-iframe-card.ts +++ b/src/panels/lovelace/cards/hui-iframe-card.ts @@ -11,14 +11,8 @@ import { import "../../../components/ha-card"; import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; import { styleMap } from "lit-html/directives/style-map"; - -export interface Config extends LovelaceCardConfig { - aspect_ratio?: string; - title?: string; - url: string; -} +import { IframeCardConfig } from "./types"; @customElement("hui-iframe-card") export class HuiIframeCard extends LitElement implements LovelaceCard { @@ -30,7 +24,7 @@ export class HuiIframeCard extends LitElement implements LovelaceCard { return { url: "https://www.home-assistant.io", aspect_ratio: "50%" }; } - @property() protected _config?: Config; + @property() protected _config?: IframeCardConfig; public getCardSize(): number { if (!this._config) { @@ -42,7 +36,7 @@ export class HuiIframeCard extends LitElement implements LovelaceCard { return 1 + aspectRatio / 25; } - public setConfig(config: Config): void { + public setConfig(config: IframeCardConfig): void { if (!config.url) { throw new Error("URL required"); } diff --git a/src/panels/lovelace/cards/hui-light-card.ts b/src/panels/lovelace/cards/hui-light-card.ts index 46ed51c616..9618e4a3bf 100644 --- a/src/panels/lovelace/cards/hui-light-card.ts +++ b/src/panels/lovelace/cards/hui-light-card.ts @@ -8,15 +8,6 @@ import { } from "lit-element"; import "@polymer/paper-icon-button/paper-icon-button"; -import { fireEvent } from "../../../common/dom/fire_event"; -import { styleMap } from "lit-html/directives/style-map"; -import { HomeAssistant, LightEntity } from "../../../types"; -import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; -import { hasConfigOrEntityChanged } from "../common/has-changed"; -import { loadRoundslider } from "../../../resources/jquery.roundslider.ondemand"; -import { toggleEntity } from "../common/entity/toggle-entity"; - import stateIcon from "../../../common/entity/state_icon"; import computeStateName from "../../../common/entity/compute_state_name"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; @@ -25,6 +16,15 @@ import "../../../components/ha-card"; import "../../../components/ha-icon"; import "../components/hui-warning"; +import { fireEvent } from "../../../common/dom/fire_event"; +import { styleMap } from "lit-html/directives/style-map"; +import { HomeAssistant, LightEntity } from "../../../types"; +import { LovelaceCard, LovelaceCardEditor } from "../types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; +import { loadRoundslider } from "../../../resources/jquery.roundslider.ondemand"; +import { toggleEntity } from "../common/entity/toggle-entity"; +import { LightCardConfig } from "./types"; + const lightConfig = { radius: 80, step: 1, @@ -40,12 +40,6 @@ const lightConfig = { animation: false, }; -export interface Config extends LovelaceCardConfig { - entity: string; - name?: string; - theme?: string; -} - @customElement("hui-light-card") export class HuiLightCard extends LitElement implements LovelaceCard { public static async getConfigElement(): Promise { @@ -58,7 +52,7 @@ export class HuiLightCard extends LitElement implements LovelaceCard { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: LightCardConfig; @property() private _roundSliderStyle?: TemplateResult; @@ -70,7 +64,7 @@ export class HuiLightCard extends LitElement implements LovelaceCard { return 2; } - public setConfig(config: Config): void { + public setConfig(config: LightCardConfig): void { if (!config.entity || config.entity.split(".")[0] !== "light") { throw new Error("Specify an entity from within the light domain."); } diff --git a/src/panels/lovelace/cards/hui-map-card.ts b/src/panels/lovelace/cards/hui-map-card.ts index b56c064de7..227304da45 100644 --- a/src/panels/lovelace/cards/hui-map-card.ts +++ b/src/panels/lovelace/cards/hui-map-card.ts @@ -21,20 +21,13 @@ import computeStateDomain from "../../../common/entity/compute_state_domain"; import computeStateName from "../../../common/entity/compute_state_name"; import debounce from "../../../common/util/debounce"; import parseAspectRatio from "../../../common/util/parse-aspect-ratio"; -import { HomeAssistant } from "../../../types"; import computeDomain from "../../../common/entity/compute_domain"; + +import { HomeAssistant } from "../../../types"; import { LovelaceCard } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; import { EntityConfig } from "../entity-rows/types"; import { processConfigEntities } from "../common/process-config-entities"; - -export interface MapCardConfig extends LovelaceCardConfig { - title: string; - aspect_ratio: string; - default_zoom?: number; - entities?: Array; - geo_location_sources?: string[]; -} +import { MapCardConfig } from "./types"; @customElement("hui-map-card") class HuiMapCard extends LitElement implements LovelaceCard { diff --git a/src/panels/lovelace/cards/hui-markdown-card.ts b/src/panels/lovelace/cards/hui-markdown-card.ts index 9f66d23952..35a92d9231 100644 --- a/src/panels/lovelace/cards/hui-markdown-card.ts +++ b/src/panels/lovelace/cards/hui-markdown-card.ts @@ -13,12 +13,7 @@ import "../../../components/ha-card"; import "../../../components/ha-markdown"; import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; - -export interface Config extends LovelaceCardConfig { - content: string; - title?: string; -} +import { MarkdownCardConfig } from "./types"; @customElement("hui-markdown-card") export class HuiMarkdownCard extends LitElement implements LovelaceCard { @@ -31,13 +26,13 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { return { content: " " }; } - @property() private _config?: Config; + @property() private _config?: MarkdownCardConfig; public getCardSize(): number { return this._config!.content.split("\n").length; } - public setConfig(config: Config): void { + public setConfig(config: MarkdownCardConfig): void { if (!config.content) { throw new Error("Invalid Configuration: Content Required"); } diff --git a/src/panels/lovelace/cards/hui-media-control-card.js b/src/panels/lovelace/cards/hui-media-control-card.js index dc78585aa4..3d38b9114f 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.js +++ b/src/panels/lovelace/cards/hui-media-control-card.js @@ -2,11 +2,6 @@ import "../../../cards/ha-media_player-card"; import LegacyWrapperCard from "./hui-legacy-wrapper-card"; -// should be interface when converted to TS -export const Config = { - entity: "", -}; - class HuiMediaControlCard extends LegacyWrapperCard { static async getConfigElement() { await import(/* webpackChunkName: "hui-media-control-card-editor" */ "../editor/config-elements/hui-media-control-card-editor"); diff --git a/src/panels/lovelace/cards/hui-picture-card.ts b/src/panels/lovelace/cards/hui-picture-card.ts index ac2b0128bb..4d6c4fda48 100644 --- a/src/panels/lovelace/cards/hui-picture-card.ts +++ b/src/panels/lovelace/cards/hui-picture-card.ts @@ -11,17 +11,11 @@ import { import "../../../components/ha-card"; import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace"; import { HomeAssistant } from "../../../types"; import { classMap } from "lit-html/directives/class-map"; import { handleClick } from "../common/handle-click"; import { longPress } from "../common/directives/long-press-directive"; - -export interface Config extends LovelaceCardConfig { - image?: string; - tap_action?: ActionConfig; - hold_action?: ActionConfig; -} +import { PictureCardConfig } from "./types"; @customElement("hui-picture-card") export class HuiPictureCard extends LitElement implements LovelaceCard { @@ -40,13 +34,13 @@ export class HuiPictureCard extends LitElement implements LovelaceCard { public hass?: HomeAssistant; - @property() protected _config?: Config; + @property() protected _config?: PictureCardConfig; public getCardSize(): number { return 3; } - public setConfig(config: Config): void { + public setConfig(config: PictureCardConfig): void { if (!config || !config.image) { throw new Error("Invalid Configuration: 'image' required"); } diff --git a/src/panels/lovelace/cards/hui-picture-elements-card.ts b/src/panels/lovelace/cards/hui-picture-elements-card.ts index 9f4ec65730..0aa673df83 100644 --- a/src/panels/lovelace/cards/hui-picture-elements-card.ts +++ b/src/panels/lovelace/cards/hui-picture-elements-card.ts @@ -9,25 +9,14 @@ import { } from "lit-element"; import { createStyledHuiElement } from "./picture-elements/create-styled-hui-element"; - import { LovelaceCard } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; import { HomeAssistant } from "../../../types"; import { LovelaceElementConfig, LovelaceElement } from "../elements/types"; - -interface Config extends LovelaceCardConfig { - title?: string; - image?: string; - camera_image?: string; - state_image?: {}; - aspect_ratio?: string; - entity?: string; - elements: LovelaceElementConfig[]; -} +import { PictureElementsCardConfig } from "./types"; @customElement("hui-picture-elements-card") class HuiPictureElementsCard extends LitElement implements LovelaceCard { - @property() private _config?: Config; + @property() private _config?: PictureElementsCardConfig; private _hass?: HomeAssistant; @@ -43,7 +32,7 @@ class HuiPictureElementsCard extends LitElement implements LovelaceCard { return 4; } - public setConfig(config: Config): void { + public setConfig(config: PictureElementsCardConfig): void { if (!config) { throw new Error("Invalid Configuration"); } else if ( diff --git a/src/panels/lovelace/cards/hui-picture-entity-card.ts b/src/panels/lovelace/cards/hui-picture-entity-card.ts index 9a2334f923..a65526e901 100644 --- a/src/panels/lovelace/cards/hui-picture-entity-card.ts +++ b/src/panels/lovelace/cards/hui-picture-entity-card.ts @@ -20,36 +20,23 @@ import computeStateName from "../../../common/entity/compute_state_name"; import { longPress } from "../common/directives/long-press-directive"; import { HomeAssistant } from "../../../types"; -import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace"; import { LovelaceCard } from "../types"; import { handleClick } from "../common/handle-click"; import { UNAVAILABLE } from "../../../data/entity"; import { hasConfigOrEntityChanged } from "../common/has-changed"; - -interface Config extends LovelaceCardConfig { - entity: string; - name?: string; - image?: string; - camera_image?: string; - state_image?: {}; - aspect_ratio?: string; - tap_action?: ActionConfig; - hold_action?: ActionConfig; - show_name?: boolean; - show_state?: boolean; -} +import { PictureEntityCardConfig } from "./types"; @customElement("hui-picture-entity-card") class HuiPictureEntityCard extends LitElement implements LovelaceCard { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: PictureEntityCardConfig; public getCardSize(): number { return 3; } - public setConfig(config: Config): void { + public setConfig(config: PictureEntityCardConfig): void { if (!config || !config.entity) { throw new Error("Invalid Configuration: 'entity' required"); } diff --git a/src/panels/lovelace/cards/hui-picture-glance-card.ts b/src/panels/lovelace/cards/hui-picture-glance-card.ts index f2de5b80e5..0fb78c5298 100644 --- a/src/panels/lovelace/cards/hui-picture-glance-card.ts +++ b/src/panels/lovelace/cards/hui-picture-glance-card.ts @@ -10,13 +10,6 @@ import { } from "lit-element"; import { classMap } from "lit-html/directives/class-map"; -import { DOMAINS_TOGGLE } from "../../../common/const"; -import { LovelaceCard } from "../types"; -import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace"; -import { EntityConfig } from "../entity-rows/types"; -import { HomeAssistant } from "../../../types"; -import { longPress } from "../common/directives/long-press-directive"; -import { processConfigEntities } from "../common/process-config-entities"; import computeStateDisplay from "../../../common/entity/compute_state_display"; import computeStateName from "../../../common/entity/compute_state_name"; import computeDomain from "../../../common/entity/compute_domain"; @@ -27,29 +20,24 @@ import "../../../components/ha-icon"; import "../components/hui-image"; import "../components/hui-warning-element"; +import { DOMAINS_TOGGLE } from "../../../common/const"; +import { LovelaceCard } from "../types"; +import { EntityConfig } from "../entity-rows/types"; +import { HomeAssistant } from "../../../types"; +import { longPress } from "../common/directives/long-press-directive"; +import { processConfigEntities } from "../common/process-config-entities"; import { handleClick } from "../common/handle-click"; import { fireEvent } from "../../../common/dom/fire_event"; import { toggleEntity } from "../common/entity/toggle-entity"; +import { PictureGlanceCardConfig } from "./types"; const STATES_OFF = new Set(["closed", "locked", "not_home", "off"]); -interface Config extends LovelaceCardConfig { - entities: EntityConfig[]; - title?: string; - image?: string; - camera_image?: string; - state_image?: {}; - aspect_ratio?: string; - entity?: string; - tap_action?: ActionConfig; - hold_action?: ActionConfig; -} - @customElement("hui-picture-glance-card") class HuiPictureGlanceCard extends LitElement implements LovelaceCard { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: PictureGlanceCardConfig; private _entitiesDialog?: EntityConfig[]; @@ -59,7 +47,7 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard { return 3; } - public setConfig(config: Config): void { + public setConfig(config: PictureGlanceCardConfig): void { if ( !config || !config.entities || diff --git a/src/panels/lovelace/cards/hui-plant-status-card.ts b/src/panels/lovelace/cards/hui-plant-status-card.ts index 80b7fa03bd..239051374c 100644 --- a/src/panels/lovelace/cards/hui-plant-status-card.ts +++ b/src/panels/lovelace/cards/hui-plant-status-card.ts @@ -8,18 +8,18 @@ import { customElement, PropertyValues, } from "lit-element"; +import { HassEntity } from "home-assistant-js-websocket"; import "../../../components/ha-card"; import "../../../components/ha-icon"; -import { HassEntity } from "home-assistant-js-websocket"; import computeStateName from "../../../common/entity/compute_state_name"; import { LovelaceCardEditor, LovelaceCard } from "../types"; import { HomeAssistant } from "../../../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; import { fireEvent } from "../../../common/dom/fire_event"; import { hasConfigOrEntityChanged } from "../common/has-changed"; +import { PlantStatusCardConfig, PlantAttributeTarget } from "./types"; const SENSORS = { moisture: "hass:water", @@ -29,15 +29,6 @@ const SENSORS = { battery: "hass:battery", }; -export interface PlantAttributeTarget extends EventTarget { - value?: string; -} - -export interface PlantStatusConfig extends LovelaceCardConfig { - name?: string; - entity: string; -} - @customElement("hui-plant-status-card") class HuiPlantStatusCard extends LitElement implements LovelaceCard { public static async getConfigElement(): Promise { @@ -51,13 +42,13 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard { @property() public hass?: HomeAssistant; - @property() private _config?: PlantStatusConfig; + @property() private _config?: PlantStatusCardConfig; public getCardSize(): number { return 3; } - public setConfig(config: PlantStatusConfig): void { + public setConfig(config: PlantStatusCardConfig): void { if (!config.entity || config.entity.split(".")[0] !== "plant") { throw new Error("Specify an entity from within the plant domain."); } diff --git a/src/panels/lovelace/cards/hui-sensor-card.ts b/src/panels/lovelace/cards/hui-sensor-card.ts index ff6f980565..76bac76fe4 100644 --- a/src/panels/lovelace/cards/hui-sensor-card.ts +++ b/src/panels/lovelace/cards/hui-sensor-card.ts @@ -11,13 +11,6 @@ import { } from "lit-element"; import "@polymer/paper-spinner/paper-spinner"; -import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; -import { HomeAssistant } from "../../../types"; -import { fireEvent } from "../../../common/dom/fire_event"; -import { fetchRecent } from "../../../data/history"; -import { hasConfigOrEntityChanged } from "../common/has-changed"; - import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import computeStateName from "../../../common/entity/compute_state_name"; import stateIcon from "../../../common/entity/state_icon"; @@ -26,6 +19,13 @@ import "../../../components/ha-card"; import "../../../components/ha-icon"; import "../components/hui-warning"; +import { LovelaceCard, LovelaceCardEditor } from "../types"; +import { HomeAssistant } from "../../../types"; +import { fireEvent } from "../../../common/dom/fire_event"; +import { fetchRecent } from "../../../data/history"; +import { SensorCardConfig } from "./types"; +import { hasConfigOrEntityChanged } from "../common/has-changed"; + const midPoint = ( _Ax: number, _Ay: number, @@ -138,17 +138,6 @@ const coordinates = ( return calcPoints(history, hours, width, detail, min, max); }; -export interface Config extends LovelaceCardConfig { - entity: string; - name?: string; - icon?: string; - graph?: string; - unit?: string; - detail?: number; - theme?: string; - hours_to_show?: number; -} - @customElement("hui-sensor-card") class HuiSensorCard extends LitElement implements LovelaceCard { public static async getConfigElement(): Promise { @@ -162,13 +151,13 @@ class HuiSensorCard extends LitElement implements LovelaceCard { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: SensorCardConfig; @property() private _history?: any; private _date?: Date; - public setConfig(config: Config): void { + public setConfig(config: SensorCardConfig): void { if (!config.entity || config.entity.split(".")[0] !== "sensor") { throw new Error("Specify an entity from within the sensor domain."); } diff --git a/src/panels/lovelace/cards/hui-shopping-list-card.ts b/src/panels/lovelace/cards/hui-shopping-list-card.ts index 7eecc139a7..10f391e6aa 100644 --- a/src/panels/lovelace/cards/hui-shopping-list-card.ts +++ b/src/panels/lovelace/cards/hui-shopping-list-card.ts @@ -16,7 +16,6 @@ import "../../../components/ha-icon"; import { HomeAssistant } from "../../../types"; import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; import { fetchItems, updateItem, @@ -24,10 +23,7 @@ import { clearItems, addItem, } from "../../../data/shopping-list"; - -export interface Config extends LovelaceCardConfig { - title?: string; -} +import { ShoppingListCardConfig } from "./types"; @customElement("hui-shopping-list-card") class HuiShoppingListCard extends LitElement implements LovelaceCard { @@ -42,7 +38,7 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: ShoppingListCardConfig; @property() private _uncheckedItems?: ShoppingListItem[]; @@ -54,7 +50,7 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard { return (this._config ? (this._config.title ? 1 : 0) : 0) + 3; } - public setConfig(config: Config): void { + public setConfig(config: ShoppingListCardConfig): void { this._config = config; this._uncheckedItems = []; this._checkedItems = []; diff --git a/src/panels/lovelace/cards/hui-stack-card.ts b/src/panels/lovelace/cards/hui-stack-card.ts index c3fdd18ba6..b2f6d17034 100644 --- a/src/panels/lovelace/cards/hui-stack-card.ts +++ b/src/panels/lovelace/cards/hui-stack-card.ts @@ -1,14 +1,10 @@ import { html, LitElement, TemplateResult } from "lit-element"; import { createCardElement } from "../common/create-card-element"; - import { LovelaceCard } from "../types"; import { LovelaceCardConfig } from "../../../data/lovelace"; import { HomeAssistant } from "../../../types"; - -interface Config extends LovelaceCardConfig { - cards: LovelaceCardConfig[]; -} +import { StackCardConfig } from "./types"; export abstract class HuiStackCard extends LitElement implements LovelaceCard { static get properties() { @@ -29,12 +25,12 @@ export abstract class HuiStackCard extends LitElement implements LovelaceCard { } } protected _cards?: LovelaceCard[]; - private _config?: Config; + private _config?: StackCardConfig; private _hass?: HomeAssistant; public abstract getCardSize(): number; - public setConfig(config: Config): void { + public setConfig(config: StackCardConfig): void { if (!config || !config.cards || !Array.isArray(config.cards)) { throw new Error("Card config incorrect"); } diff --git a/src/panels/lovelace/cards/hui-thermostat-card.ts b/src/panels/lovelace/cards/hui-thermostat-card.ts index 74bec1a21f..a6af4caf24 100644 --- a/src/panels/lovelace/cards/hui-thermostat-card.ts +++ b/src/panels/lovelace/cards/hui-thermostat-card.ts @@ -19,10 +19,10 @@ import computeStateName from "../../../common/entity/compute_state_name"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import { HomeAssistant, ClimateEntity } from "../../../types"; import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; import { loadRoundslider } from "../../../resources/jquery.roundslider.ondemand"; import { UNIT_F } from "../../../common/const"; import { fireEvent } from "../../../common/dom/fire_event"; +import { ThermostatCardConfig } from "./types"; const thermostatConfig = { radius: 150, @@ -47,12 +47,6 @@ const modeIcons = { idle: "hass:power-sleep", }; -export interface Config extends LovelaceCardConfig { - entity: string; - theme?: string; - name?: string; -} - @customElement("hui-thermostat-card") export class HuiThermostatCard extends LitElement implements LovelaceCard { public static async getConfigElement(): Promise { @@ -66,7 +60,7 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: ThermostatCardConfig; @property() private _roundSliderStyle?: TemplateResult; @@ -82,7 +76,7 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard { return 4; } - public setConfig(config: Config): void { + public setConfig(config: ThermostatCardConfig): void { if (!config.entity || config.entity.split(".")[0] !== "climate") { throw new Error("Specify an entity from within the climate domain."); } diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.js b/src/panels/lovelace/cards/hui-weather-forecast-card.js index 0ef2b8c2c2..9c05fdc2c9 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.js +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.js @@ -2,12 +2,6 @@ import "../../../cards/ha-weather-card"; import LegacyWrapperCard from "./hui-legacy-wrapper-card"; -// should be interface when converted to TS -export const Config = { - entity: "", - name: "", -}; - class HuiWeatherForecastCard extends LegacyWrapperCard { static async getConfigElement() { await import(/* webpackChunkName: "hui-weather-forecast-card-editor" */ "../editor/config-elements/hui-weather-forecast-card-editor"); diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts new file mode 100644 index 0000000000..6d8820b2fd --- /dev/null +++ b/src/panels/lovelace/cards/types.ts @@ -0,0 +1,200 @@ +import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace"; +import { Condition } from "../common/validate-condition"; +import { EntityConfig } from "../entity-rows/types"; +import { LovelaceElementConfig } from "../elements/types"; + +export interface AlarmPanelCardConfig extends LovelaceCardConfig { + entity: string; + name?: string; + states?: string[]; +} + +export interface ConditionalCardConfig extends LovelaceCardConfig { + card: LovelaceCardConfig; + conditions: Condition[]; +} + +export interface EmptyStateCardConfig extends LovelaceCardConfig { + content: string; + title?: string; +} + +export interface EntitiesCardEntityConfig extends EntityConfig { + type?: string; + secondary_info?: "entity-id" | "last-changed"; + action_name?: string; + service?: string; + service_data?: object; + url?: string; +} + +export interface EntitiesCardConfig extends LovelaceCardConfig { + show_header_toggle?: boolean; + title?: string; + entities: EntitiesCardEntityConfig[]; + theme?: string; +} + +export interface EntityButtonCardConfig extends LovelaceCardConfig { + entity: string; + name?: string; + snow_name?: boolean; + icon?: string; + show_icon?: boolean; + theme?: string; + tap_action?: ActionConfig; + hold_action?: ActionConfig; +} + +export interface EntityFilterCardConfig extends LovelaceCardConfig { + type: "entity-filter"; + entities: Array; + state_filter: string[]; + card: Partial; + show_empty?: boolean; +} + +export interface ErrorCardConfig extends LovelaceCardConfig { + error: string; + origConfig: LovelaceCardConfig; +} + +export interface SeverityConfig { + green?: number; + yellow?: number; + red?: number; +} + +export interface GaugeCardConfig extends LovelaceCardConfig { + entity: string; + name?: string; + unit?: string; + min?: number; + max?: number; + severity?: SeverityConfig; + theme?: string; +} + +export interface ConfigEntity extends EntityConfig { + tap_action?: ActionConfig; + hold_action?: ActionConfig; +} + +export interface GlanceCardConfig extends LovelaceCardConfig { + show_name?: boolean; + show_state?: boolean; + show_icon?: boolean; + title?: string; + theme?: string; + entities: ConfigEntity[]; + columns?: number; +} + +export interface IframeCardConfig extends LovelaceCardConfig { + aspect_ratio?: string; + title?: string; + url: string; +} + +export interface LightCardConfig extends LovelaceCardConfig { + entity: string; + name?: string; + theme?: string; +} + +export interface MapCardConfig extends LovelaceCardConfig { + title: string; + aspect_ratio: string; + default_zoom?: number; + entities?: Array; + geo_location_sources?: string[]; +} + +export interface MarkdownCardConfig extends LovelaceCardConfig { + content: string; + title?: string; +} + +export interface MediaControlCardConfig extends LovelaceCardConfig { + entity: string; +} + +export interface PictureCardConfig extends LovelaceCardConfig { + image?: string; + tap_action?: ActionConfig; + hold_action?: ActionConfig; +} + +export interface PictureElementsCardConfig extends LovelaceCardConfig { + title?: string; + image?: string; + camera_image?: string; + state_image?: {}; + aspect_ratio?: string; + entity?: string; + elements: LovelaceElementConfig[]; +} + +export interface PictureEntityCardConfig extends LovelaceCardConfig { + entity: string; + name?: string; + image?: string; + camera_image?: string; + state_image?: {}; + aspect_ratio?: string; + tap_action?: ActionConfig; + hold_action?: ActionConfig; + show_name?: boolean; + show_state?: boolean; +} + +export interface PictureGlanceCardConfig extends LovelaceCardConfig { + entities: EntityConfig[]; + title?: string; + image?: string; + camera_image?: string; + state_image?: {}; + aspect_ratio?: string; + entity?: string; + tap_action?: ActionConfig; + hold_action?: ActionConfig; +} + +export interface PlantAttributeTarget extends EventTarget { + value?: string; +} + +export interface PlantStatusCardConfig extends LovelaceCardConfig { + name?: string; + entity: string; +} + +export interface SensorCardConfig extends LovelaceCardConfig { + entity: string; + name?: string; + icon?: string; + graph?: string; + unit?: string; + detail?: number; + theme?: string; + hours_to_show?: number; +} + +export interface ShoppingListCardConfig extends LovelaceCardConfig { + title?: string; +} + +export interface StackCardConfig extends LovelaceCardConfig { + cards: LovelaceCardConfig[]; +} + +export interface ThermostatCardConfig extends LovelaceCardConfig { + entity: string; + theme?: string; + name?: string; +} + +export interface WeatherForecastCardConfig extends LovelaceCardConfig { + entity: string; + name?: string; +} diff --git a/src/panels/lovelace/common/generate-lovelace-config.ts b/src/panels/lovelace/common/generate-lovelace-config.ts index 70b794cf13..3e771733a2 100644 --- a/src/panels/lovelace/common/generate-lovelace-config.ts +++ b/src/panels/lovelace/common/generate-lovelace-config.ts @@ -5,6 +5,7 @@ import { LovelaceViewConfig, } from "../../../data/lovelace"; import { HassEntity, HassEntities } from "home-assistant-js-websocket"; + import extractViews from "../../../common/entity/extract_views"; import getViewEntities from "../../../common/entity/get_view_entities"; import computeStateName from "../../../common/entity/compute_state_name"; @@ -12,9 +13,10 @@ import splitByGroups from "../../../common/entity/split_by_groups"; import computeObjectId from "../../../common/entity/compute_object_id"; import computeStateDomain from "../../../common/entity/compute_state_domain"; import computeDomain from "../../../common/entity/compute_domain"; + import { EntityRowConfig, WeblinkConfig } from "../entity-rows/types"; -import { EntitiesCardConfig } from "../cards/hui-entities-card"; import { LocalizeFunc } from "../../../common/translations/localize"; +import { EntitiesCardConfig } from "../cards/types"; const DEFAULT_VIEW_ENTITY_ID = "group.default_view"; const DOMAINS_BADGES = [ diff --git a/src/panels/lovelace/components/hui-generic-entity-row.ts b/src/panels/lovelace/components/hui-generic-entity-row.ts index d38b413dfc..515eafdd6b 100644 --- a/src/panels/lovelace/components/hui-generic-entity-row.ts +++ b/src/panels/lovelace/components/hui-generic-entity-row.ts @@ -9,15 +9,15 @@ import { TemplateResult, } from "lit-element"; -import { HomeAssistant } from "../../../types"; -import { EntitiesCardEntityConfig } from "../cards/hui-entities-card"; -import { computeRTL } from "../../../common/util/compute_rtl"; - import "../../../components/entity/state-badge"; import "../../../components/ha-relative-time"; import "../../../components/ha-icon"; import "../components/hui-warning"; +import { HomeAssistant } from "../../../types"; +import { computeRTL } from "../../../common/util/compute_rtl"; +import { EntitiesCardEntityConfig } from "../cards/types"; + class HuiGenericEntityRow extends LitElement { @property() public hass?: HomeAssistant; diff --git a/src/panels/lovelace/editor/config-elements/hui-alarm-panel-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-alarm-panel-card-editor.ts index 8daa8ead02..47da255b09 100644 --- a/src/panels/lovelace/editor/config-elements/hui-alarm-panel-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-alarm-panel-card-editor.ts @@ -16,11 +16,11 @@ import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-alarm-panel-card"; import { configElementStyle } from "./config-elements-style"; import "../../../../components/entity/ha-entity-picker"; import "../../../../components/ha-icon"; +import { AlarmPanelCardConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -34,9 +34,9 @@ export class HuiAlarmPanelCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: AlarmPanelCardConfig; - public setConfig(config: Config): void { + public setConfig(config: AlarmPanelCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts index 7e61259e97..4b9be7d22c 100644 --- a/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts @@ -10,23 +10,23 @@ import "@polymer/paper-item/paper-item"; import "@polymer/paper-listbox/paper-listbox"; import "@polymer/paper-toggle-button/paper-toggle-button"; +import "../../../../components/entity/state-badge"; +import "../../components/hui-theme-select-editor"; +import "../../components/hui-entity-editor"; +import "../../../../components/ha-card"; +import "../../../../components/ha-icon"; + import { processEditorEntities } from "../process-editor-entities"; import { struct } from "../../common/structs/struct"; import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; +import { configElementStyle } from "./config-elements-style"; import { EntitiesCardConfig, EntitiesCardEntityConfig, -} from "../../cards/hui-entities-card"; -import { configElementStyle } from "./config-elements-style"; - -import "../../../../components/entity/state-badge"; -import "../../components/hui-theme-select-editor"; -import "../../components/hui-entity-editor"; -import "../../../../components/ha-card"; -import "../../../../components/ha-icon"; +} from "../../cards/types"; const entitiesConfigStruct = struct.union([ { diff --git a/src/panels/lovelace/editor/config-elements/hui-entity-button-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-entity-button-card-editor.ts index 93ecd9498a..7ac9ffca2a 100644 --- a/src/panels/lovelace/editor/config-elements/hui-entity-button-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-entity-button-card-editor.ts @@ -7,6 +7,10 @@ import { } from "lit-element"; import "@polymer/paper-input/paper-input"; +import "../../components/hui-action-editor"; +import "../../components/hui-theme-select-editor"; +import "../../components/hui-entity-editor"; + import { struct } from "../../common/structs/struct"; import { EntitiesEditorEvent, @@ -16,13 +20,9 @@ import { import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-entity-button-card"; import { configElementStyle } from "./config-elements-style"; import { ActionConfig } from "../../../../data/lovelace"; - -import "../../components/hui-action-editor"; -import "../../components/hui-theme-select-editor"; -import "../../components/hui-entity-editor"; +import { EntityButtonCardConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -41,9 +41,9 @@ export class HuiEntityButtonCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: EntityButtonCardConfig; - public setConfig(config: Config): void { + public setConfig(config: EntityButtonCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts index a9f5af2dec..d92c8262bf 100644 --- a/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts @@ -10,16 +10,16 @@ import { import "@polymer/paper-input/paper-input"; import "@polymer/paper-toggle-button/paper-toggle-button"; +import "../../components/hui-theme-select-editor"; +import "../../components/hui-entity-editor"; + import { struct } from "../../common/structs/struct"; import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config, SeverityConfig } from "../../cards/hui-gauge-card"; import { configElementStyle } from "./config-elements-style"; - -import "../../components/hui-theme-select-editor"; -import "../../components/hui-entity-editor"; +import { GaugeCardConfig, SeverityConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -37,11 +37,11 @@ export class HuiGaugeCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: GaugeCardConfig; private _useSeverity?: boolean; - public setConfig(config: Config): void { + public setConfig(config: GaugeCardConfig): void { config = cardConfigStruct(config); this._useSeverity = !!config.severity; this._config = config; diff --git a/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts index cef49e197e..68397b381b 100644 --- a/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts @@ -10,20 +10,20 @@ import "@polymer/paper-item/paper-item"; import "@polymer/paper-listbox/paper-listbox"; import "@polymer/paper-toggle-button/paper-toggle-button"; +import "../../../../components/entity/state-badge"; +import "../../components/hui-theme-select-editor"; +import "../../components/hui-entity-editor"; +import "../../../../components/ha-card"; +import "../../../../components/ha-icon"; + import { struct } from "../../common/structs/struct"; import { processEditorEntities } from "../process-editor-entities"; import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { GlanceCardConfig, ConfigEntity } from "../../cards/hui-glance-card"; import { configElementStyle } from "./config-elements-style"; - -import "../../../../components/entity/state-badge"; -import "../../components/hui-theme-select-editor"; -import "../../components/hui-entity-editor"; -import "../../../../components/ha-card"; -import "../../../../components/ha-icon"; +import { GlanceCardConfig, ConfigEntity } from "../../cards/types"; const entitiesConfigStruct = struct.union([ { diff --git a/src/panels/lovelace/editor/config-elements/hui-iframe-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-iframe-card-editor.ts index 6d01f24ee5..3672b8af54 100644 --- a/src/panels/lovelace/editor/config-elements/hui-iframe-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-iframe-card-editor.ts @@ -12,8 +12,8 @@ import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-iframe-card"; import { configElementStyle } from "./config-elements-style"; +import { IframeCardConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -27,9 +27,9 @@ export class HuiIframeCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: IframeCardConfig; - public setConfig(config: Config): void { + public setConfig(config: IframeCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts index 742fe7ee4c..8f1eba6876 100644 --- a/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts @@ -7,16 +7,16 @@ import { } from "lit-element"; import "@polymer/paper-input/paper-input"; +import "../../components/hui-theme-select-editor"; +import "../../components/hui-entity-editor"; + import { struct } from "../../common/structs/struct"; import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-light-card"; import { configElementStyle } from "./config-elements-style"; - -import "../../components/hui-theme-select-editor"; -import "../../components/hui-entity-editor"; +import { LightCardConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -30,9 +30,9 @@ export class HuiLightCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: LightCardConfig; - public setConfig(config: Config): void { + public setConfig(config: LightCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts index bacda9c4d5..0e43e36e88 100644 --- a/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts @@ -9,19 +9,19 @@ import { } from "lit-element"; import "@polymer/paper-input/paper-input"; +import "../../components/hui-entity-editor"; +import "../../components/hui-input-list-editor"; + import { struct } from "../../common/structs/struct"; import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { MapCardConfig } from "../../cards/hui-map-card"; import { configElementStyle } from "./config-elements-style"; import { processEditorEntities } from "../process-editor-entities"; import { EntityConfig } from "../../entity-rows/types"; import { PolymerChangedEvent } from "../../../../polymer-types"; - -import "../../components/hui-entity-editor"; -import "../../components/hui-input-list-editor"; +import { MapCardConfig } from "../../cards/types"; const entitiesConfigStruct = struct.union([ { diff --git a/src/panels/lovelace/editor/config-elements/hui-markdown-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-markdown-card-editor.ts index 362ed6940f..a1da22d8a6 100644 --- a/src/panels/lovelace/editor/config-elements/hui-markdown-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-markdown-card-editor.ts @@ -13,8 +13,8 @@ import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-markdown-card"; import { configElementStyle } from "./config-elements-style"; +import { MarkdownCardConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -27,9 +27,9 @@ export class HuiMarkdownCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: MarkdownCardConfig; - public setConfig(config: Config): void { + public setConfig(config: MarkdownCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/editor/config-elements/hui-media-control-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-media-control-card-editor.ts index 6a3b6a835d..104959e8f0 100644 --- a/src/panels/lovelace/editor/config-elements/hui-media-control-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-media-control-card-editor.ts @@ -11,7 +11,7 @@ import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-media-control-card"; +import { MediaControlCardConfig } from "../../cards/hui-media-control-card"; import "../../../../components/entity/ha-entity-picker"; @@ -25,9 +25,9 @@ export class HuiMediaControlCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: MediaControlCardConfig; - public setConfig(config: Config): void { + public setConfig(config: MediaControlCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts index b6cfc6125a..cfde20c852 100644 --- a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts @@ -7,6 +7,8 @@ import { } from "lit-element"; import "@polymer/paper-input/paper-input"; +import "../../components/hui-action-editor"; + import { struct } from "../../common/structs/struct"; import { EntitiesEditorEvent, @@ -16,11 +18,9 @@ import { import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-picture-card"; import { configElementStyle } from "./config-elements-style"; import { ActionConfig } from "../../../../data/lovelace"; - -import "../../components/hui-action-editor"; +import { PictureCardConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -34,9 +34,9 @@ export class HuiPictureCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: PictureCardConfig; - public setConfig(config: Config): void { + public setConfig(config: PictureCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/editor/config-elements/hui-plant-status-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-plant-status-card-editor.ts index 942da40302..335eb0e8b9 100644 --- a/src/panels/lovelace/editor/config-elements/hui-plant-status-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-plant-status-card-editor.ts @@ -7,16 +7,16 @@ import { } from "lit-element"; import "@polymer/paper-input/paper-input"; +import "../../../../components/entity/ha-entity-picker"; +import "../../../../components/ha-icon"; + import { struct } from "../../common/structs/struct"; import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-alarm-panel-card"; import { configElementStyle } from "./config-elements-style"; - -import "../../../../components/entity/ha-entity-picker"; -import "../../../../components/ha-icon"; +import { PlantStatusCardConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -29,9 +29,9 @@ export class HuiPlantStatusCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: PlantStatusCardConfig; - public setConfig(config: Config): void { + public setConfig(config: PlantStatusCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/editor/config-elements/hui-sensor-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-sensor-card-editor.ts index 062a9baeed..30654517f4 100644 --- a/src/panels/lovelace/editor/config-elements/hui-sensor-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-sensor-card-editor.ts @@ -10,16 +10,16 @@ import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; import "@polymer/paper-item/paper-item"; import "@polymer/paper-listbox/paper-listbox"; +import "../../components/hui-theme-select-editor"; +import "../../../../components/entity/ha-entity-picker"; + import { struct } from "../../common/structs/struct"; import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-sensor-card"; import { configElementStyle } from "./config-elements-style"; - -import "../../components/hui-theme-select-editor"; -import "../../../../components/entity/ha-entity-picker"; +import { SensorCardConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -38,9 +38,9 @@ export class HuiSensorCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: SensorCardConfig; - public setConfig(config: Config): void { + public setConfig(config: SensorCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/editor/config-elements/hui-shopping-list-editor.ts b/src/panels/lovelace/editor/config-elements/hui-shopping-list-editor.ts index b2c0090299..0ea1fa00dc 100644 --- a/src/panels/lovelace/editor/config-elements/hui-shopping-list-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-shopping-list-editor.ts @@ -12,7 +12,7 @@ import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-shopping-list-card"; +import { ShoppingListCardConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -24,9 +24,9 @@ export class HuiShoppingListEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: ShoppingListCardConfig; - public setConfig(config: Config): void { + public setConfig(config: ShoppingListCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts index bc6e27edae..cd98e60286 100644 --- a/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts @@ -7,16 +7,16 @@ import { } from "lit-element"; import "@polymer/paper-input/paper-input"; +import "../../components/hui-theme-select-editor"; +import "../../../../components/entity/ha-entity-picker"; + import { struct } from "../../common/structs/struct"; import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-thermostat-card"; import { configElementStyle } from "./config-elements-style"; - -import "../../components/hui-theme-select-editor"; -import "../../../../components/entity/ha-entity-picker"; +import { ThermostatCardConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -30,9 +30,9 @@ export class HuiThermostatCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: ThermostatCardConfig; - public setConfig(config: Config): void { + public setConfig(config: ThermostatCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts index cf394c5450..6502054af9 100644 --- a/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts @@ -6,15 +6,15 @@ import { property, } from "lit-element"; +import "../../../../components/entity/ha-entity-picker"; + import { struct } from "../../common/structs/struct"; import { EntitiesEditorEvent, EditorTarget } from "../types"; import { HomeAssistant } from "../../../../types"; import { LovelaceCardEditor } from "../../types"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { Config } from "../../cards/hui-weather-forecast-card"; import { configElementStyle } from "./config-elements-style"; - -import "../../../../components/entity/ha-entity-picker"; +import { WeatherForecastCardConfig } from "../../cards/types"; const cardConfigStruct = struct({ type: "string", @@ -27,9 +27,9 @@ export class HuiWeatherForecastCardEditor extends LitElement implements LovelaceCardEditor { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: WeatherForecastCardConfig; - public setConfig(config: Config): void { + public setConfig(config: WeatherForecastCardConfig): void { config = cardConfigStruct(config); this._config = config; } diff --git a/src/panels/lovelace/elements/hui-conditional-element.ts b/src/panels/lovelace/elements/hui-conditional-element.ts index 15901e294d..648c15af40 100644 --- a/src/panels/lovelace/elements/hui-conditional-element.ts +++ b/src/panels/lovelace/elements/hui-conditional-element.ts @@ -1,24 +1,21 @@ import { - Condition, checkConditionsMet, validateConditionalConfig, } from "../../lovelace/common/validate-condition"; import { createStyledHuiElement } from "../cards/picture-elements/create-styled-hui-element"; - -import { LovelaceElement, LovelaceElementConfig } from "./types"; +import { + LovelaceElement, + LovelaceElementConfig, + ConditionalElementConfig, +} from "./types"; import { HomeAssistant } from "../../../types"; -interface Config extends LovelaceElementConfig { - conditions: Condition[]; - elements: LovelaceElementConfig[]; -} - class HuiConditionalElement extends HTMLElement implements LovelaceElement { public _hass?: HomeAssistant; - private _config?: Config; + private _config?: ConditionalElementConfig; private _elements: LovelaceElement[] = []; - public setConfig(config: Config): void { + public setConfig(config: ConditionalElementConfig): void { if ( !config.conditions || !Array.isArray(config.conditions) || diff --git a/src/panels/lovelace/elements/hui-icon-element.ts b/src/panels/lovelace/elements/hui-icon-element.ts index 489e9a6742..f0da18717d 100644 --- a/src/panels/lovelace/elements/hui-icon-element.ts +++ b/src/panels/lovelace/elements/hui-icon-element.ts @@ -13,24 +13,15 @@ import "../../../components/ha-icon"; import { computeTooltip } from "../common/compute-tooltip"; import { handleClick } from "../common/handle-click"; import { longPress } from "../common/directives/long-press-directive"; -import { LovelaceElement, LovelaceElementConfig } from "./types"; +import { LovelaceElement, IconElementConfig } from "./types"; import { HomeAssistant } from "../../../types"; -import { ActionConfig } from "../../../data/lovelace"; - -export interface Config extends LovelaceElementConfig { - entity?: string; - name?: string; - tap_action?: ActionConfig; - hold_action?: ActionConfig; - icon: string; -} @customElement("hui-icon-element") export class HuiIconElement extends LitElement implements LovelaceElement { public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: IconElementConfig; - public setConfig(config: Config): void { + public setConfig(config: IconElementConfig): void { if (!config.icon) { throw Error("Invalid Configuration: 'icon' required"); } diff --git a/src/panels/lovelace/elements/hui-image-element.ts b/src/panels/lovelace/elements/hui-image-element.ts index 76e55b08e2..e6d98e2163 100644 --- a/src/panels/lovelace/elements/hui-image-element.ts +++ b/src/panels/lovelace/elements/hui-image-element.ts @@ -13,28 +13,15 @@ import "../components/hui-image"; import { computeTooltip } from "../common/compute-tooltip"; import { handleClick } from "../common/handle-click"; import { longPress } from "../common/directives/long-press-directive"; -import { LovelaceElement, LovelaceElementConfig } from "./types"; +import { LovelaceElement, ImageElementConfig } from "./types"; import { HomeAssistant } from "../../../types"; -import { ActionConfig } from "../../../data/lovelace"; - -export interface Config extends LovelaceElementConfig { - entity?: string; - tap_action?: ActionConfig; - hold_action?: ActionConfig; - image?: string; - state_image?: string; - camera_image?: string; - filter?: string; - state_filter?: string; - aspect_ratio?: string; -} @customElement("hui-image-element") export class HuiImageElement extends LitElement implements LovelaceElement { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: ImageElementConfig; - public setConfig(config: Config): void { + public setConfig(config: ImageElementConfig): void { if (!config) { throw Error("Error in element configuration"); } diff --git a/src/panels/lovelace/elements/hui-service-button-element.ts b/src/panels/lovelace/elements/hui-service-button-element.ts index 1c3ecef0ab..7f2ebb34d8 100644 --- a/src/panels/lovelace/elements/hui-service-button-element.ts +++ b/src/panels/lovelace/elements/hui-service-button-element.ts @@ -10,20 +10,14 @@ import { import "../../../components/buttons/ha-call-service-button"; -import { LovelaceElement, LovelaceElementConfig } from "./types"; +import { LovelaceElement, ServiceButtonElementConfig } from "./types"; import { HomeAssistant } from "../../../types"; -export interface Config extends LovelaceElementConfig { - title?: string; - service?: string; - service_data?: object; -} - @customElement("hui-service-button-element") export class HuiServiceButtonElement extends LitElement implements LovelaceElement { public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: ServiceButtonElementConfig; private _domain?: string; private _service?: string; @@ -31,7 +25,7 @@ export class HuiServiceButtonElement extends LitElement return { _config: {} }; } - public setConfig(config: Config): void { + public setConfig(config: ServiceButtonElementConfig): void { if (!config || !config.service) { throw Error("Invalid Configuration: 'service' required"); } diff --git a/src/panels/lovelace/elements/hui-state-badge-element.ts b/src/panels/lovelace/elements/hui-state-badge-element.ts index 6b191a678f..9ac63484cf 100644 --- a/src/panels/lovelace/elements/hui-state-badge-element.ts +++ b/src/panels/lovelace/elements/hui-state-badge-element.ts @@ -11,21 +11,17 @@ import "../../../components/entity/ha-state-label-badge"; import "../components/hui-warning-element"; import computeStateName from "../../../common/entity/compute_state_name"; -import { LovelaceElement, LovelaceElementConfig } from "./types"; +import { LovelaceElement, StateBadgeElementConfig } from "./types"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -export interface Config extends LovelaceElementConfig { - entity: string; -} - @customElement("hui-state-badge-element") export class HuiStateBadgeElement extends LitElement implements LovelaceElement { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: StateBadgeElementConfig; - public setConfig(config: Config): void { + public setConfig(config: StateBadgeElementConfig): void { if (!config.entity) { throw Error("Invalid Configuration: 'entity' required"); } diff --git a/src/panels/lovelace/elements/hui-state-icon-element.ts b/src/panels/lovelace/elements/hui-state-icon-element.ts index 59d57989cf..91a41748d9 100644 --- a/src/panels/lovelace/elements/hui-state-icon-element.ts +++ b/src/panels/lovelace/elements/hui-state-icon-element.ts @@ -15,23 +15,16 @@ import "../components/hui-warning-element"; import { computeTooltip } from "../common/compute-tooltip"; import { handleClick } from "../common/handle-click"; import { longPress } from "../common/directives/long-press-directive"; -import { LovelaceElement, LovelaceElementConfig } from "./types"; +import { LovelaceElement, StateIconElementConfig } from "./types"; import { HomeAssistant } from "../../../types"; -import { ActionConfig } from "../../../data/lovelace"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -export interface Config extends LovelaceElementConfig { - entity: string; - tap_action?: ActionConfig; - hold_action?: ActionConfig; -} - @customElement("hui-state-icon-element") export class HuiStateIconElement extends LitElement implements LovelaceElement { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: StateIconElementConfig; - public setConfig(config: Config): void { + public setConfig(config: StateIconElementConfig): void { if (!config.entity) { throw Error("Invalid Configuration: 'entity' required"); } diff --git a/src/panels/lovelace/elements/hui-state-label-element.ts b/src/panels/lovelace/elements/hui-state-label-element.ts index 87cc147ebe..561e9a8588 100644 --- a/src/panels/lovelace/elements/hui-state-label-element.ts +++ b/src/panels/lovelace/elements/hui-state-label-element.ts @@ -16,25 +16,16 @@ import computeStateDisplay from "../../../common/entity/compute_state_display"; import { computeTooltip } from "../common/compute-tooltip"; import { handleClick } from "../common/handle-click"; import { longPress } from "../common/directives/long-press-directive"; -import { LovelaceElement, LovelaceElementConfig } from "./types"; +import { LovelaceElement, StateLabelElementConfig } from "./types"; import { HomeAssistant } from "../../../types"; -import { ActionConfig } from "../../../data/lovelace"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -interface Config extends LovelaceElementConfig { - entity: string; - prefix?: string; - suffix?: string; - tap_action?: ActionConfig; - hold_action?: ActionConfig; -} - @customElement("hui-state-label-element") class HuiStateLabelElement extends LitElement implements LovelaceElement { @property() public hass?: HomeAssistant; - @property() private _config?: Config; + @property() private _config?: StateLabelElementConfig; - public setConfig(config: Config): void { + public setConfig(config: StateLabelElementConfig): void { if (!config.entity) { throw Error("Invalid Configuration: 'entity' required"); } diff --git a/src/panels/lovelace/elements/types.ts b/src/panels/lovelace/elements/types.ts index 6d6b908a29..5c82484003 100644 --- a/src/panels/lovelace/elements/types.ts +++ b/src/panels/lovelace/elements/types.ts @@ -1,4 +1,6 @@ import { HomeAssistant } from "../../../types"; +import { Condition } from "../common/validate-condition"; +import { ActionConfig } from "../../../data/lovelace"; export interface LovelaceElementConfig { type: string; @@ -9,3 +11,52 @@ export interface LovelaceElement extends HTMLElement { hass?: HomeAssistant; setConfig(config: LovelaceElementConfig): void; } + +export interface ConditionalElementConfig extends LovelaceElementConfig { + conditions: Condition[]; + elements: LovelaceElementConfig[]; +} + +export interface IconElementConfig extends LovelaceElementConfig { + entity?: string; + name?: string; + tap_action?: ActionConfig; + hold_action?: ActionConfig; + icon: string; +} + +export interface ImageElementConfig extends LovelaceElementConfig { + entity?: string; + tap_action?: ActionConfig; + hold_action?: ActionConfig; + image?: string; + state_image?: string; + camera_image?: string; + filter?: string; + state_filter?: string; + aspect_ratio?: string; +} + +export interface ServiceButtonElementConfig extends LovelaceElementConfig { + title?: string; + service?: string; + service_data?: object; +} + +export interface StateBadgeElementConfig extends LovelaceElementConfig { + entity: string; +} + +export interface StateIconElementConfig extends LovelaceElementConfig { + entity: string; + tap_action?: ActionConfig; + hold_action?: ActionConfig; +} + +export interface StateLabelElementConfig extends LovelaceElementConfig { + entity: string; + prefix?: string; + suffix?: string; + tap_action?: ActionConfig; + hold_action?: ActionConfig; +} diff --git a/src/panels/lovelace/entity-rows/hui-group-entity-row.ts b/src/panels/lovelace/entity-rows/hui-group-entity-row.ts index 7a172b9a78..ebc78cee83 100644 --- a/src/panels/lovelace/entity-rows/hui-group-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-group-entity-row.ts @@ -12,6 +12,7 @@ import "../../../components/entity/ha-entity-toggle"; import "../components/hui-warning"; import computeStateDisplay from "../../../common/entity/compute_state_display"; + import { DOMAINS_TOGGLE } from "../../../common/const"; import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; diff --git a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts index a17e16d314..9909c89106 100644 --- a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts @@ -17,6 +17,7 @@ import "../../../components/entity/state-badge"; import "../components/hui-warning"; import computeStateName from "../../../common/entity/compute_state_name"; + import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; import { setOption } from "../../../data/input-select"; diff --git a/src/panels/lovelace/entity-rows/hui-text-entity-row.ts b/src/panels/lovelace/entity-rows/hui-text-entity-row.ts index eafd7f42c7..34e98c737c 100644 --- a/src/panels/lovelace/entity-rows/hui-text-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-text-entity-row.ts @@ -13,6 +13,7 @@ import "../components/hui-generic-entity-row"; import "../components/hui-warning"; import computeStateDisplay from "../../../common/entity/compute_state_display"; + import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; diff --git a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts index bbd27aa51b..cd46bccae8 100644 --- a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts @@ -12,6 +12,7 @@ import "../components/hui-warning"; import timerTimeRemaining from "../../../common/entity/timer_time_remaining"; import secondsToDuration from "../../../common/datetime/seconds_to_duration"; + import { HomeAssistant } from "../../../types"; import { EntityConfig } from "./types"; import { HassEntity } from "home-assistant-js-websocket"; From adc63e1e5af3dc8a757ee2ba97acfab3ff40e85c Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Wed, 27 Mar 2019 21:11:07 -0700 Subject: [PATCH 22/29] Fix login form missing abort reason (#3024) --- src/auth/ha-auth-flow.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/auth/ha-auth-flow.js b/src/auth/ha-auth-flow.js index ceb487a031..d397aa4f4e 100644 --- a/src/auth/ha-auth-flow.js +++ b/src/auth/ha-auth-flow.js @@ -2,6 +2,7 @@ import { PolymerElement } from "@polymer/polymer/polymer-element"; import "@material/mwc-button"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import "../components/ha-form"; +import "../components/ha-markdown"; import { localizeLiteMixin } from "../mixins/localize-lite-mixin"; class HaAuthFlow extends localizeLiteMixin(PolymerElement) { From a743a2c46b3cb2a37b4e8ddd74f26a5b2bf5ca75 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Wed, 27 Mar 2019 23:12:20 -0500 Subject: [PATCH 23/29] =?UTF-8?q?=F0=9F=9B=A0=20Fix=20button=20icon/name?= =?UTF-8?q?=20(#3026)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/panels/lovelace/cards/hui-entity-button-card.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/lovelace/cards/hui-entity-button-card.ts b/src/panels/lovelace/cards/hui-entity-button-card.ts index 5178f1d1ab..5f3926b4fd 100644 --- a/src/panels/lovelace/cards/hui-entity-button-card.ts +++ b/src/panels/lovelace/cards/hui-entity-button-card.ts @@ -61,9 +61,9 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard { this._config = { theme: "default", hold_action: { action: "more-info" }, - ...config, show_icon: true, show_name: true, + ...config, }; if (DOMAINS_TOGGLE.has(computeDomain(config.entity))) { From 7f8f99a4145a0afdf9b1464b2981fcaba0181b4c Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Wed, 27 Mar 2019 23:12:56 -0500 Subject: [PATCH 24/29] =?UTF-8?q?=F0=9F=95=B6=20convert=20hui-configurator?= =?UTF-8?q?-notification-item=20to=20TypeScript/LitElement=20(#3027)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hui-configurator-notification-item.js | 60 ------------------- .../hui-configurator-notification-item.ts | 59 ++++++++++++++++++ 2 files changed, 59 insertions(+), 60 deletions(-) delete mode 100644 src/panels/lovelace/components/notifications/hui-configurator-notification-item.js create mode 100644 src/panels/lovelace/components/notifications/hui-configurator-notification-item.ts diff --git a/src/panels/lovelace/components/notifications/hui-configurator-notification-item.js b/src/panels/lovelace/components/notifications/hui-configurator-notification-item.js deleted file mode 100644 index 020a4b2821..0000000000 --- a/src/panels/lovelace/components/notifications/hui-configurator-notification-item.js +++ /dev/null @@ -1,60 +0,0 @@ -import "@material/mwc-button"; -import "@polymer/paper-icon-button/paper-icon-button"; - -import { html } from "@polymer/polymer/lib/utils/html-tag"; -import { PolymerElement } from "@polymer/polymer/polymer-element"; - -import "./hui-notification-item-template"; - -import EventsMixin from "../../../../mixins/events-mixin"; -import LocalizeMixin from "../../../../mixins/localize-mixin"; - -/* - * @appliesMixin EventsMixin - * @appliesMixin LocalizeMixin - */ -export class HuiConfiguratorNotificationItem extends EventsMixin( - LocalizeMixin(PolymerElement) -) { - static get template() { - return html` - - [[localize('domain.configurator')]] - -
[[_getMessage(notification)]]
- - [[_localizeState(notification.state)]] -
- `; - } - - static get properties() { - return { - hass: Object, - notification: Object, - }; - } - - _handleClick() { - this.fire("hass-more-info", { entityId: this.notification.entity_id }); - } - - _localizeState(state) { - return this.localize(`state.configurator.${state}`); - } - - _getMessage(notification) { - const friendlyName = notification.attributes.friendly_name; - return this.localize( - "ui.notification_drawer.click_to_configure", - "entity", - friendlyName - ); - } -} -customElements.define( - "hui-configurator-notification-item", - HuiConfiguratorNotificationItem -); diff --git a/src/panels/lovelace/components/notifications/hui-configurator-notification-item.ts b/src/panels/lovelace/components/notifications/hui-configurator-notification-item.ts new file mode 100644 index 0000000000..59a779f503 --- /dev/null +++ b/src/panels/lovelace/components/notifications/hui-configurator-notification-item.ts @@ -0,0 +1,59 @@ +import { + html, + LitElement, + TemplateResult, + property, + customElement, +} from "lit-element"; +import "@material/mwc-button"; + +import "./hui-notification-item-template"; + +import { HomeAssistant } from "../../../../types"; +import { HassEntity } from "home-assistant-js-websocket"; +import { fireEvent } from "../../../../common/dom/fire_event"; + +@customElement("hui-configurator-notification-item") +export class HuiConfiguratorNotificationItem extends LitElement { + @property() public hass?: HomeAssistant; + + @property() public notification?: HassEntity; + + protected render(): TemplateResult | void { + if (!this.hass || !this.notification) { + return html``; + } + + return html` + + ${this.hass.localize("domain.configurator")} + +
+ ${this.hass.localize( + "ui.notification_drawer.click_to_configure", + "entity", + this.notification.attributes.friendly_name + )} +
+ + ${this.hass.localize( + `state.configurator.${this.notification.state}` + )} +
+ `; + } + + private _handleClick(): void { + fireEvent(this, "hass-more-info", { + entityId: this.notification!.entity_id, + }); + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-configurator-notification-item": HuiConfiguratorNotificationItem; + } +} From eac37af18c8ad79fe36d3a90c4eb3f5cd670d8c7 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Wed, 27 Mar 2019 23:14:27 -0500 Subject: [PATCH 25/29] =?UTF-8?q?=F0=9F=95=B6=20convert=20hui-notification?= =?UTF-8?q?-item=20to=20TypeScript/LitElement=20(#3028)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notifications/hui-notification-item.js | 35 ------------ .../notifications/hui-notification-item.ts | 55 +++++++++++++++++++ .../hui-persistent-notification-item.js | 2 +- 3 files changed, 56 insertions(+), 36 deletions(-) delete mode 100644 src/panels/lovelace/components/notifications/hui-notification-item.js create mode 100644 src/panels/lovelace/components/notifications/hui-notification-item.ts diff --git a/src/panels/lovelace/components/notifications/hui-notification-item.js b/src/panels/lovelace/components/notifications/hui-notification-item.js deleted file mode 100644 index 66ed2f2a2a..0000000000 --- a/src/panels/lovelace/components/notifications/hui-notification-item.js +++ /dev/null @@ -1,35 +0,0 @@ -import { PolymerElement } from "@polymer/polymer/polymer-element"; -import computeDomain from "../../../../common/entity/compute_domain"; - -import "./hui-configurator-notification-item"; -import "./hui-persistent-notification-item"; - -export class HuiNotificationItem extends PolymerElement { - static get properties() { - return { - hass: Object, - notification: { - type: Object, - observer: "_stateChanged", - }, - }; - } - - _stateChanged(notification) { - if (this.lastChild) { - this.removeChild(this.lastChild); - } - - if (!notification) return; - - const domain = notification.entity_id - ? computeDomain(notification.entity_id) - : "persistent_notification"; - const tag = `hui-${domain}-notification-item`; - const el = document.createElement(tag); - el.hass = this.hass; - el.notification = notification; - this.appendChild(el); - } -} -customElements.define("hui-notification-item", HuiNotificationItem); diff --git a/src/panels/lovelace/components/notifications/hui-notification-item.ts b/src/panels/lovelace/components/notifications/hui-notification-item.ts new file mode 100644 index 0000000000..0aa39a4e4d --- /dev/null +++ b/src/panels/lovelace/components/notifications/hui-notification-item.ts @@ -0,0 +1,55 @@ +import { + LitElement, + property, + customElement, + PropertyValues, + TemplateResult, + html, +} from "lit-element"; + +import "./hui-configurator-notification-item"; +import "./hui-persistent-notification-item"; + +import { HassEntity } from "home-assistant-js-websocket"; +import { HomeAssistant } from "../../../../types"; + +@customElement("hui-notification-item") +export class HuiNotificationItem extends LitElement { + @property() public hass?: HomeAssistant; + + @property() public notification?: HassEntity; + + protected shouldUpdate(changedProps: PropertyValues): boolean { + if (!this.hass || !this.notification || changedProps.has("notification")) { + return true; + } + + return false; + } + + protected render(): TemplateResult | void { + if (!this.hass || !this.notification) { + return html``; + } + + return this.notification.entity_id + ? html` + + ` + : html` + + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-notification-item": HuiNotificationItem; + } +} diff --git a/src/panels/lovelace/components/notifications/hui-persistent-notification-item.js b/src/panels/lovelace/components/notifications/hui-persistent-notification-item.js index d763ab3838..30ee92adc1 100644 --- a/src/panels/lovelace/components/notifications/hui-persistent-notification-item.js +++ b/src/panels/lovelace/components/notifications/hui-persistent-notification-item.js @@ -87,6 +87,6 @@ export class HuiPersistentNotificationItem extends LocalizeMixin( } } customElements.define( - "hui-persistent_notification-notification-item", + "hui-persistent-notification-item", HuiPersistentNotificationItem ); From 40863db1380cd5e1953eaa6381210159e05611ec Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 27 Mar 2019 21:12:15 -0700 Subject: [PATCH 26/29] Typo --- src/panels/lovelace/cards/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts index 6d8820b2fd..3c8a00b8ad 100644 --- a/src/panels/lovelace/cards/types.ts +++ b/src/panels/lovelace/cards/types.ts @@ -38,7 +38,7 @@ export interface EntitiesCardConfig extends LovelaceCardConfig { export interface EntityButtonCardConfig extends LovelaceCardConfig { entity: string; name?: string; - snow_name?: boolean; + show_name?: boolean; icon?: string; show_icon?: boolean; theme?: string; From aa1ac8f3396247db2030a6d292dfbfa25956a658 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 27 Mar 2019 21:21:15 -0700 Subject: [PATCH 27/29] Update translations --- translations/af.json | 866 +++++++++++++++++++++++++++++++++++---- translations/bg.json | 2 +- translations/cy.json | 4 +- translations/de.json | 4 +- translations/es-419.json | 4 +- translations/eu.json | 857 +++++++++++++++++++++++++++++++++++++- translations/nl.json | 8 +- translations/pl.json | 2 +- translations/pt.json | 70 +++- translations/ru.json | 8 +- translations/sl.json | 26 +- translations/tr.json | 8 +- 12 files changed, 1744 insertions(+), 115 deletions(-) diff --git a/translations/af.json b/translations/af.json index 1371d3b086..fff2615ebc 100644 --- a/translations/af.json +++ b/translations/af.json @@ -7,71 +7,72 @@ "history": "Geskiedenis", "mailbox": "Posbus", "shopping_list": "Inkopielys", - "dev-services": "Services", - "dev-states": "States", - "dev-events": "Events", - "dev-templates": "Templates", + "dev-services": "Dienste", + "dev-states": "State", + "dev-events": "Gebeure", + "dev-templates": "Template", "dev-mqtt": "MQTT", - "dev-info": "Info" + "dev-info": "Info", + "calendar": "Kalender" }, "state": { "default": { "off": "Af", - "on": "Op", - "unknown": "Onbekende", + "on": "Aan", + "unknown": "Onbekend", "unavailable": "Nie beskikbaar nie" }, "alarm_control_panel": { "armed": "Gewapen", "disarmed": "Ontwapen", - "armed_home": "Gewapende huis", - "armed_away": "Gewapen weg", - "armed_night": "Gewapende nag", + "armed_home": "Gewapend tuis", + "armed_away": "Gewapend weg", + "armed_night": "Gewapend nag", "pending": "Hangende", "arming": "Bewapen", "disarming": "Ontwapen", - "triggered": "Veroorsaak", + "triggered": "Geaktiveer", "armed_custom_bypass": "Gewapende pasgemaakte omseil" }, "automation": { "off": "Af", - "on": "Op" + "on": "Aan" }, "binary_sensor": { "default": { "off": "Af", - "on": "Op" + "on": "Aan" }, "moisture": { - "off": "Droë", + "off": "Droog", "on": "Nat" }, "gas": { - "off": "Duidelike", - "on": "Opgespoor" + "off": "Ongemerk", + "on": "Bespeur" }, "motion": { - "off": "Duidelike", - "on": "Opgespoor" + "off": "Ongemerk", + "on": "Bespeur" }, "occupancy": { - "off": "Duidelike", - "on": "Opgespoor" + "off": "Ongemerk", + "on": "Bespeur" }, "smoke": { - "off": "Duidelike", - "on": "Opgespoor" + "off": "Ongemerk", + "on": "Bespeur" }, "sound": { - "off": "Duidelike", - "on": "Opgespoor" + "off": "Ongemerk", + "on": "Bespeur" }, "vibration": { - "off": "Duidelike", - "on": "Opgespoor" + "off": "Ongemerk", + "on": "Bespeur" }, "opening": { - "off": "Gesluit", + "off": "Toe", "on": "Oop" }, "safety": { @@ -79,17 +80,40 @@ "on": "Onveilige" }, "presence": { - "off": "Weg", - "on": "Huis" + "off": "Afwesig", + "on": "Tuis" }, "battery": { - "off": "Normale", - "on": "Lae" + "off": "Normaal", + "on": "Laag" + }, + "problem": { + "off": "OK", + "on": "Probleem" + }, + "cold": { + "on": "Koud" + }, + "door": { + "on": "Oop" + }, + "garage_door": { + "on": "Oop" + }, + "heat": { + "on": "Warm" + }, + "window": { + "on": "Oop" + }, + "lock": { + "off": "Gesluit", + "on": "Oopgesluit" } }, "calendar": { "off": "Af", - "on": "Op" + "on": "Aan" }, "camera": { "recording": "Opname", @@ -98,19 +122,20 @@ }, "climate": { "off": "Af", - "on": "Op", + "on": "Aan", "heat": "Hitte", - "cool": "Afkoel", + "cool": "Koel", "idle": "Ledig", "auto": "Outo", - "dry": "Droë", - "fan_only": "Slegs fan", + "dry": "Droog", + "fan_only": "Slegs waaier", "eco": "Eko", - "electric": "Elektriese", + "electric": "Elektries", "performance": "Prestasie", "high_demand": "Hoë aanvraag", "heat_pump": "Hitte pomp", - "gas": "Gas" + "gas": "Gas", + "manual": "Handmatig" }, "configurator": { "configure": "Konfigureer", @@ -119,65 +144,71 @@ "cover": { "open": "Oop", "opening": "Opening", - "closed": "Gesluit", - "closing": "Sluit", + "closed": "Toe", + "closing": "Sluiting", "stopped": "Gestop" }, "device_tracker": { - "home": "Huis", - "not_home": "Weg" + "home": "Tuis", + "not_home": "Afwesig" }, "fan": { "off": "Af", - "on": "Op" + "on": "Aan" }, "group": { "off": "Af", - "on": "Op", - "home": "Huis", - "not_home": "Weg", + "on": "Aan", + "home": "Tuis", + "not_home": "Afwesig", "open": "Oop", "opening": "Opening", - "closed": "Gesluit", - "closing": "Sluit", + "closed": "Toe", + "closing": "Sluiting", "stopped": "Gestop", "locked": "Gesluit", - "unlocked": "Ontsluit" + "unlocked": "Oopgesluit", + "ok": "OK", + "problem": "Probleem" }, "input_boolean": { "off": "Af", - "on": "Op" + "on": "Aan" }, "light": { "off": "Af", - "on": "Op" + "on": "Aan" }, "lock": { "locked": "Gesluit", - "unlocked": "Ontsluit" + "unlocked": "Oopgesluit" }, "media_player": { "off": "Af", - "on": "Op", + "on": "Aan", "playing": "Speel", "paused": "Onderbreek", "idle": "Ledig", - "standby": "Gereedheid" + "standby": "Staan by" + }, + "plant": { + "ok": "OK", + "problem": "Probleem" }, "remote": { "off": "Af", - "on": "Op" + "on": "Aan" }, "scene": { - "scening": "Scening" + "scening": "Toneeling" }, "script": { "off": "Af", - "on": "Op" + "on": "Aan" }, "sensor": { "off": "Af", - "on": "Op" + "on": "Aan" }, "sun": { "above_horizon": "Bo horison", @@ -185,7 +216,7 @@ }, "switch": { "off": "Af", - "on": "Op" + "on": "Aan" }, "zwave": { "default": { @@ -198,40 +229,723 @@ "initializing": "Inisialiseer ({query_stage})", "dead": "Dood ({query_stage})" } + }, + "weather": { + "clear-night": "Helder, nag", + "cloudy": "Bewolk", + "fog": "Mis", + "hail": "Hael", + "lightning": "Weerlig", + "lightning-rainy": "Weerlig, Reënagtig", + "partlycloudy": "Gedeeltelik bewolk", + "pouring": "Stort", + "rainy": "Reënagtig", + "snowy": "Sneeuagtig", + "snowy-rainy": "Ysreën", + "sunny": "Sonnig", + "windy": "Winderig", + "windy-variant": "Winderig" + }, + "vacuum": { + "cleaning": "Skoonmaak", + "docked": "Vasgemeer", + "on": "Aan", + "paused": "Onderbreek" + }, + "timer": { + "active": "aktief", + "idle": "onaktiewe", + "paused": "Onderbreek" + }, + "person": { + "home": "Tuis", + "not_home": "Afwesig" } }, "state_badge": { "default": { - "unknown": "Unk", - "unavailable": "Unavai" + "unknown": "?", + "unavailable": "Onbeskik" }, "alarm_control_panel": { - "armed": "Armed", - "disarmed": "Disarm", - "armed_home": "Armed", - "armed_away": "Armed", - "armed_night": "Armed", - "pending": "Pend", - "arming": "Arming", - "disarming": "Disarm", - "triggered": "Trig", - "armed_custom_bypass": "Armed" + "armed": "Gewapen", + "disarmed": "Ontwapen", + "armed_home": "Gewapen", + "armed_away": "Gewapen", + "armed_night": "Gewapen", + "pending": "Hangend", + "arming": "Bewapen", + "disarming": "Ontwapen", + "triggered": "Aktief", + "armed_custom_bypass": "Gewapen" }, "device_tracker": { - "home": "Huis", - "not_home": "Weg" + "home": "Tuis", + "not_home": "Afwesig" + }, + "person": { + "home": "Tuis", + "not_home": "Afwesig" } }, "ui": { "panel": { "shopping-list": { - "clear_completed": "Duidelik voltooide", - "add_item": "Voeg item" + "clear_completed": "Maak voltooide items skoon", + "add_item": "Voeg item", + "microphone_tip": "Druk die mikrofoon regs bo en sê \"Add candy to my shopping list\"" + }, + "mailbox": { + "delete_prompt": "Skrap hierdie boodskap?", + "delete_button": "Skrap" + }, + "config": { + "automation": { + "description": "Skep en wysig outomatisasies", + "picker": { + "introduction": "Die outomatiseringsredakteur stel jou in staat om outomatisasies te skep en te wysig. Volg die onderstaande skakel om die instruksies te lees om seker te maak dat u Home Assistant korrek opgestel het.", + "learn_more": "Kom meer te wete oor outomatisasies" + }, + "editor": { + "save": "Stoor", + "alias": "Naam", + "triggers": { + "duplicate": "Dupliseer", + "delete": "Skrap", + "delete_confirm": "Is jy seker jy wil dit skrap?", + "type": { + "event": { + "label": "Gebeurtenis", + "event_type": "Gebeurtenis tipe", + "event_data": "Gebeurtenis data" + }, + "state": { + "label": "Staat" + }, + "homeassistant": { + "event": "Gebeurtenis:" + }, + "numeric_state": { + "label": "Numeriese toestand", + "above": "Bo", + "below": "Onder", + "value_template": "Waarde templaat (opsioneel)" + }, + "sun": { + "label": "Son", + "event": "Gebeurtenis:", + "sunrise": "Sonsopkoms", + "sunset": "Sonsondergang", + "offset": "Verreken (opsioneel)" + }, + "template": { + "label": "Templaat", + "value_template": "Waarde templaat" + }, + "time": { + "label": "Tyd" + }, + "zone": { + "label": "Sone", + "entity": "Entiteit met plek", + "zone": "Sone", + "event": "Gebeurtenis:" + }, + "webhook": { + "label": "Webhook", + "webhook_id": "Webhook ID" + }, + "time_pattern": { + "label": "Tydpatroon", + "hours": "Ure", + "minutes": "Minute", + "seconds": "Sekondes" + }, + "geo_location": { + "label": "Ligginggewing", + "source": "Bron", + "zone": "Sone", + "event": "Gebeurtenis:", + "enter": "Betree", + "leave": "Verlaat" + } + }, + "learn_more": "Kom meer te wete oor snellers" + }, + "conditions": { + "header": "Voorwaardes", + "add": "Voeg voorwaarde by", + "duplicate": "Dupliseer", + "delete": "Skrap", + "delete_confirm": "Is jy seker jy wil dit skrap?", + "unsupported_condition": "Ongesteunde voorwaarde: {condition}", + "type_select": "Voorwaarde tipe", + "type": { + "state": { + "label": "Staat", + "state": "Staat" + }, + "numeric_state": { + "label": "Numeriese toestand", + "above": "Bo", + "below": "Onder", + "value_template": "Waarde templaat (opsioneel)" + }, + "sun": { + "label": "Son", + "before": "Voor:", + "after": "Na:", + "before_offset": "Voor verreken (opsioneel)", + "after_offset": "Na verreken (opsioneel)", + "sunrise": "Sonsopkoms", + "sunset": "Sonsondergang" + }, + "template": { + "label": "Templaat", + "value_template": "Waarde templaat" + }, + "time": { + "label": "Tyd", + "after": "Na", + "before": "Voor" + }, + "zone": { + "label": "Sone", + "entity": "Entiteit met plek", + "zone": "Sone" + } + }, + "learn_more": "Kom meer te wete oor die voorwaardes" + }, + "actions": { + "header": "Aksies", + "introduction": "Die aksies is wat Home Assistant sal doen wanneer die outomatisering geaktiveer word.", + "add": "Voeg aksie by", + "duplicate": "Dupliseer", + "delete": "Skrap", + "delete_confirm": "Is jy seker jy wil dit skrap?", + "unsupported_action": "Ongesteunde aksie: {action}", + "type_select": "Aksie tipe", + "type": { + "service": { + "label": "Roep diens", + "service_data": "Diens data" + }, + "delay": { + "label": "Vertraging", + "delay": "Vertraging" + }, + "wait_template": { + "label": "Wag", + "wait_template": "Wag Templaat", + "timeout": "Tyd verstreke (opsioneel)" + }, + "condition": { + "label": "Voorwaarde" + }, + "event": { + "label": "Vuur geval", + "event": "Gebeurtenis:", + "service_data": "Diens data" + } + }, + "learn_more": "Kom meer te wete oor aksies" + } + } + }, + "script": { + "description": "Skep en wysig skripte" + }, + "users": { + "caption": "Gebruikers", + "description": "Bestuur gebruikers", + "picker": { + "title": "Gebruikers" + }, + "editor": { + "rename_user": "Hernoem gebruiker", + "change_password": "Verander Wagwoord", + "activate_user": "Aktiveer gebruiker", + "deactivate_user": "Deaktiveer gebruiker", + "delete_user": "Skrap gebruiker", + "caption": "Bekyk gebruiker" + }, + "add_user": { + "caption": "Voeg gebruiker by", + "name": "Naam", + "username": "Gebruikersnaam", + "password": "Wagwoord", + "create": "Skep" + } + }, + "integrations": { + "config_entry": { + "delete_confirm": "Is jy seker jy wil hierdie integrasie skrap?", + "restart_confirm": "Herbegin Home Assistant om hierdie integrasie te voltooi", + "manuf": "deur {manufacturer}", + "hub": "Gekonnekteer via", + "firmware": "Fermware: {version}", + "device_unavailable": "toestel nie beskikbaar nie", + "entity_unavailable": "entiteit nie beskikbaar nie", + "no_area": "Geen Gebied" + } + }, + "zha": { + "caption": "ZHA", + "description": "Zigbee Home Automation netwerk bestuur", + "services": { + "reconfigure": "Herkonfigureer ZHA-toestel (heal device). Gebruik dit as jy probleme ondervind met die toestel. As die betrokke toestel 'n battery aangedrewe toestel is, maak asseblief seker dat dit wakker is en bevele aanvaar wanneer u hierdie diens gebruik.", + "updateDeviceName": "Stel 'n persoonlike naam vir hierdie toestel in die toestelregister" + } + }, + "area_registry": { + "caption": "Gebiedsregister", + "description": "Oorsig van alle gebiede in jou huis.", + "picker": { + "header": "Gebiedsregister", + "introduction": "Gebiede word gebruik om toestelle te organiseer gebaseer op waar hulle is. Hierdie inligting sal deur die Home Assistant gebruik word om u te help om u koppelvlak, toestemmings en integrasies met ander stelsels te organiseer.", + "introduction2": "Om toestelle in 'n gebied te plaas, gebruik die skakel hieronder om na die integrasies bladsy toe te gaan en klik dan op 'n gekonfigureerde integrasie om na die toestelkaarte toe te gaan.", + "integrations_page": "Integrasies bladsy", + "no_areas": "Dit lyk asof jy nog geen gebiede het nie!", + "create_area": "SKEP GEBIED" + }, + "no_areas": "Dit lyk asof jy nog geen gebiede het nie!", + "create_area": "SKEP GEBIED", + "editor": { + "default_name": "Nuwe Gebied", + "delete": "SKRAP", + "update": "OPDATEER", + "create": "SKEP" + } + }, + "entity_registry": { + "caption": "Entiteit Register", + "description": "Oorsig van alle bekende entiteite.", + "picker": { + "header": "Entiteit Register", + "unavailable": "(nie beskikbaar nie)", + "introduction": "Home Assistant hou 'n register van al die vorige entiteite wat uniek geïdentifiseer kan word. Elk van hierdie entiteite sal 'n entiteit-ID hê wat vir hierdie entiteit gereserveer sal word.", + "introduction2": "Gebruik die entiteitsregister om die naam te oorskryf, die entiteit ID te verander, of die inskrywing van Home Assistant te verwyder. Let wel, die verwydering van die entiteit registerinskrywing sal nie die entiteit verwyder nie. Om dit te doen, volg die skakel hieronder en verwyder dit uit die integrasies bladsy.", + "integrations_page": "Integrasies bladsy" + }, + "editor": { + "unavailable": "Hierdie entiteit is tans nie beskikbaar nie.", + "default_name": "Nuwe Gebied", + "delete": "SKRAP", + "update": "OPDATEER" + } + }, + "customize": { + "picker": { + "header": "Pasgemaakte Instellings ", + "introduction": "Verfyn per-entiteit eienskappe. Bygevoegde \/ gewysigde aanpassings sal onmiddellik in werking tree. Verwyderde aanpassings sal in werkin tree wanneer die entiteit opgedateer word." + } + }, + "person": { + "caption": "Persone", + "description": "Bestuur die persone wat Home Assistant op spoor.", + "detail": { + "name": "Naam", + "device_tracker_intro": "Kies die toestelle wat aan hierdie persoon behoort.", + "device_tracker_picked": "Spoor toestel op", + "device_tracker_pick": "Kies toestel om op te spoor" + } + } + }, + "page-authorize": { + "form": { + "working": "Wag asseblief", + "providers": { + "homeassistant": { + "step": { + "init": { + "data": { + "username": "Gebruikersnaam", + "password": "Wagwoord" + } + }, + "mfa": { + "data": { + "code": "Twee-faktor-Verifikasiekode" + }, + "description": "Maak die ** {mfa_module_name} ** op jou toestel oop om jou twee-faktor-verifikasiekode te sien en jou identiteit te verifieer:" + } + }, + "error": { + "invalid_auth": "Ongeldige Gebruikersnaam of wagwoord", + "invalid_code": "Ongeldige verifikasiekode" + }, + "abort": { + "login_expired": "Sessie verstryk, teken asseblief weer aan." + } + }, + "legacy_api_password": { + "step": { + "mfa": { + "data": { + "code": "Twee-faktor-Verifikasiekode" + }, + "description": "Maak die ** {mfa_module_name} ** op jou toestel oop om jou twee-faktor-verifikasiekode te sien en jou identiteit te verifieer:" + } + }, + "error": { + "invalid_code": "Ongeldige verifikasiekode" + }, + "abort": { + "login_expired": "Sessie verstryk, teken asseblief weer aan." + } + }, + "command_line": { + "step": { + "init": { + "data": { + "username": "Gebruikersnaam", + "password": "Wagwoord" + } + }, + "mfa": { + "data": { + "code": "Twee-faktor-Verifikasiekode" + }, + "description": "Maak die ** {mfa_module_name} ** op jou toestel oop om jou twee-faktor-verifikasiekode te sien en jou identiteit te verifieer:" + } + }, + "error": { + "invalid_auth": "Ongeldige gebruikersnaam of wagwoord", + "invalid_code": "Ongeldige verifikasiekode" + }, + "abort": { + "login_expired": "Sessie verstryk, teken asseblief weer aan." + } + } + } + } + }, + "page-onboarding": { + "user": { + "data": { + "name": "Naam", + "username": "Gebruikersnaam", + "password": "Wagwoord", + "password_confirm": "Bevestig Wagwoord" + }, + "create_account": "Skep Rekening", + "error": { + "password_not_match": "Wagwoorde stem nie ooreen nie" + } + } + }, + "profile": { + "refresh_tokens": { + "header": "Verfris-tekseenhede", + "description": "Elke verfris-tekseenheid verteenwoordig 'n aanmeldingssessie. Verfris-tekseenhede sal outomaties verwyder word wanneer u op meld af klik. Die volgende verfris-tekseenhede is tans aktief vir u rekening.", + "token_title": "Verfris-tekseenheid vir {clientId}", + "created_at": "Geskep op {date}", + "confirm_delete": "Is jy seker jy wil die verfris-tekseenheid vir {name} skrap?", + "delete_failed": "Het misluk om die verfris-tekseenheid te skrap.", + "last_used": "Laas gebruik op {date} vanaf {location}", + "not_used": "Is nog nooit gebruik nie", + "current_token_tooltip": "Nie in staat om huidige verfris-tekseenheid te skrap nie" + }, + "long_lived_access_tokens": { + "header": "Langlewende-toegangs-tekseenhede", + "description": "Skep langlewende-toegangs-tekseenhede om jou skripte in staat te stel om met jou Home Assistant-instansie te kommunikeer. Elke tekseenheid sal geldig wees vir 10 jaar vanaf die skepping. Die volgende langlewende-toegangs-tekseenheid is tans aktief.", + "learn_auth_requests": "Leer hoe om geverifieerde versoeke te maak.", + "created_at": "Geskep op {date}", + "confirm_delete": "Is jy seker jy wil die toegangs-tekseenheid vir {name} skrap?", + "delete_failed": "Het misluk om die toegangs-tekseenheid te skrap.", + "create": "Skep Tekseenheid", + "create_failed": "Het misluk om die toegangs-tekseenheid te maak.", + "prompt_name": "Naam?", + "prompt_copy_token": "Kopieer jou toegangs-tekseenheid. Dit sal nie weer gewys word nie.", + "empty_state": "Jy het nog geen langlewende-toegangs-tekseenhede nie.", + "last_used": "Laas gebruik op {date} vanaf {location}", + "not_used": "Is nog nooit gebruik nie" + }, + "logout": "Meld af", + "change_password": { + "header": "Verander Wagwoord", + "current_password": "Huidige Wagwoord", + "new_password": "Nuwe Wagwoord", + "confirm_new_password": "Bevestig Nuwe Wagwoord", + "submit": "Dien in" + } + }, + "lovelace": { + "cards": { + "shopping-list": { + "checked_items": "Gemerkte items", + "clear_items": "Maak die gemerkte items skoon", + "add_item": "Voeg item by" + }, + "empty_state": { + "title": "Welkom tuis", + "no_devices": "Hierdie bladsy laat jou toe om jou toestelle te beheer, maar dit lyk asof jy nog nie toestelle opgestel het nie. Gaan na die integrasies bladsy om te begin.", + "go_to_integrations_page": "Gaan na die integrasies bladsy." + } + }, + "editor": { + "edit_card": { + "header": "Kaartkonfigurasie", + "save": "Stoor", + "toggle_editor": "Wissel redigeerder", + "pick_card": "Kies die kaart wat jy wil byvoeg.", + "add": "Voeg Kaart by", + "edit": "Wysig", + "delete": "Skrap", + "move": "Skuif" + }, + "migrate": { + "header": "Konfigurasie Onversoenbaar", + "para_no_id": "Hierdie element het nie 'n ID nie. Voeg asseblief 'n ID by vir hierdie element in 'ui-lovelace.yaml'.", + "para_migrate": "Druk die 'Migreer konfigurasie' knoppie as jy wil hê Home Assistant moet vir jou ID's by al jou kaarte en aansigte outomaties byvoeg.", + "migrate": "Migreer konfigurasie" + }, + "header": "Wysig gebruikerskoppelvlak", + "edit_view": { + "header": "Bekyk konfigurasie", + "add": "Voeg aansig by", + "edit": "Wysig aansig", + "delete": "Skrap aansig" + }, + "save_config": { + "header": "Neem beheer van jou Lovelace gebruikerskoppelvlak", + "para": "Home Assistant sal outomaties u gebruikerskoppelvlak handhaaf, dit opdateer wanneer nuwe entiteite of Lovelace-komponente beskikbaar raak. Alhoewel, as u beheer neem, sal Home Assistant nie meer outomaties veranderings vir u doen nie.", + "para_sure": "Is jy seker jy wil beheer neem oor jou gebruikerskoppelvlak?", + "cancel": "Toemaar", + "save": "Neem beheer" + }, + "menu": { + "raw_editor": "Plat konfigurasie-redigeerder" + }, + "raw_editor": { + "header": "Wysig Konfigurasie", + "save": "Stoor", + "unsaved_changes": "Ongestoorde veranderinge", + "saved": "Gestoor" + } + }, + "menu": { + "configure_ui": "Konfigureer gebruikerskoppelvlak", + "unused_entities": "Ongebruikte entiteite", + "help": "Help", + "refresh": "Verfris" + }, + "warning": { + "entity_not_found": "Entiteit nie beskikbaar nie: {entity}", + "entity_non_numeric": "Entiteit is nie-numeriese: {entity}" + } + }, + "logbook": { + "period": "Tydperk" } }, "sidebar": { - "log_out": "Teken", + "log_out": "Meld af", "developer_tools": "Ontwikkelaar gereedskap" + }, + "duration": { + "day": "{count} {count, plural,\n one {dag}\n other {dae}\n}", + "week": "{count} {count, plural,\n one {week}\n other {weke}\n}", + "second": "{count} {count, plural,\n one {sekonde}\n other {sekondes}\n}", + "minute": "{count} {count, plural,\none {minuut}\nother {minute}\n}", + "hour": "{count} {count, plural,\n one {uur}\n other {ure}\n}" + }, + "login-form": { + "password": "Wagwoord" + }, + "card": { + "scene": { + "activate": "Aktiveer" + }, + "script": { + "execute": "Voer uit" + }, + "weather": { + "attributes": { + "air_pressure": "Lugdruk", + "humidity": "Humiditeit", + "temperature": "Temperatuur", + "visibility": "Sigbaarheid", + "wind_speed": "Wind spoed" + }, + "cardinal_direction": { + "e": "O", + "ene": "ONO", + "ese": "OSO", + "n": "N", + "ne": "NO", + "nne": "NNO", + "nw": "NW", + "nnw": "NNW", + "s": "S", + "se": "SO", + "sse": "SSO", + "ssw": "SSW", + "sw": "SW", + "w": "W", + "wnw": "WNW", + "wsw": "WSW" + }, + "forecast": "Voorspelling" + }, + "alarm_control_panel": { + "code": "Kode", + "clear_code": "Maak skoon", + "disarm": "Skakel Af", + "arm_home": "Skakel tuis aan", + "arm_away": "Skakel weg aan", + "arm_night": "Nag alarm", + "armed_custom_bypass": "Pasgemaakte omseil", + "arm_custom_bypass": "Pasgemaakte omseil" + }, + "automation": { + "last_triggered": "Laas geaktiveer", + "trigger": "Sneller" + }, + "cover": { + "position": "Posisie", + "tilt_position": "Kantel posisie" + }, + "fan": { + "speed": "Spoed", + "oscillate": "Ossilleer", + "direction": "Rigting" + }, + "light": { + "brightness": "Helderheid", + "color_temperature": "Kleur temperatuur", + "white_value": "Wit ligwaarde", + "effect": "Effek" + }, + "media_player": { + "text_to_speak": "Teks na spraak", + "source": "Bron", + "sound_mode": "Klank modus" + }, + "climate": { + "currently": "Tans", + "on_off": "Aan \/ af", + "target_temperature": "Teiken temperatuur", + "target_humidity": "Teiken humiditeit", + "operation": "Operasie", + "fan_mode": "Waaier modus", + "swing_mode": "Swaai modus", + "away_mode": "Wegmodus", + "aux_heat": "Aanvullende hitte" + }, + "lock": { + "code": "Kode", + "lock": "Sluit toe", + "unlock": "Sluit oop" + }, + "water_heater": { + "currently": "Tans", + "on_off": "Aan \/ af", + "target_temperature": "Teiken temperatuur", + "operation": "Operasie", + "away_mode": "Afwesig modus" + } + }, + "components": { + "relative_time": { + "past": "{time} gelede", + "future": "In {time}", + "never": "Nooit", + "duration": { + "second": "{count} {count, plural,\n one {sekonde}\n other {sekondes}\n}", + "minute": "{count} {count, plural,\n one {minuut}\n other {minute}\n}", + "hour": "{count} {count, plural,\n one {uur}\n other {ure}\n}", + "day": "{count} {count, plural,\n one {dag}\n other {dae}\n}", + "week": "{count} {count, plural,\n one {week}\n other {weke}\n}" + } + }, + "history_charts": { + "loading_history": "Laai tans staatsgeskiedenis ...", + "no_history_found": "Geen staatgeskiedenis gevind nie." + } + }, + "notification_toast": { + "entity_turned_on": "{entity} aangeskakel.", + "entity_turned_off": "{entity} afgeskakel.", + "service_called": "Diens {service} geroep.", + "service_call_failed": "Het misluk om diens {service} te roep.", + "connection_lost": "Konneksie verlore. Herkoppel tans..." + }, + "dialogs": { + "more_info_settings": { + "save": "Stoor", + "name": "Naam Oorheers", + "entity_id": "Entiteit ID" + }, + "more_info_control": { + "script": { + "last_action": "Laaste Aksie" + }, + "sun": { + "elevation": "Hoogte", + "rising": "Stygende", + "setting": "Instelling" + }, + "updater": { + "title": "Opdateringsinstruksies" + } + } + }, + "common": { + "save": "Stoor" } + }, + "domain": { + "alarm_control_panel": "Alarm beheer paneel", + "automation": "Outomatisering", + "binary_sensor": "Binêre sensor", + "calendar": "Kalender", + "camera": "Kamera", + "climate": "Klimaat", + "configurator": "Konfigureerder", + "conversation": "Konversasie", + "cover": "Dekking", + "device_tracker": "Toestel opspoorder", + "fan": "Waaier", + "history_graph": "Geskiedenis grafiek", + "group": "Groep", + "image_processing": "Beeldverwerking", + "input_boolean": "Invoer boole", + "input_datetime": "Invoer datum\/tyd", + "input_select": "Invoer seleksie", + "input_number": "Invoer nommer", + "input_text": "Invoer teks", + "light": "Lig", + "lock": "Slot", + "mailbox": "Posbus", + "script": "Skrip", + "sensor": "Sensor", + "sun": "Son", + "switch": "Skakelaar", + "updater": "Opdateerder", + "weblink": "Web skakel", + "zwave": "Z-Wave", + "vacuum": "Vakuum", + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "Stelsel Gesondheid", + "person": "Persoon" + }, + "state_attributes": { + "climate": { + "fan_mode": { + "off": "Af", + "on": "Aan", + "auto": "Outomatiese" + } + } + }, + "groups": { + "system-admin": "Administrateurs", + "system-users": "Gebruikers", + "system-read-only": "Leesalleen-gebruikers" } } \ No newline at end of file diff --git a/translations/bg.json b/translations/bg.json index b5ffc0e321..609671ef64 100644 --- a/translations/bg.json +++ b/translations/bg.json @@ -128,7 +128,7 @@ "camera": { "recording": "Записване", "streaming": "Предава", - "idle": "Неработещ" + "idle": "Не записва" }, "climate": { "off": "Изключен", diff --git a/translations/cy.json b/translations/cy.json index ccb99c6506..e98a9dbbba 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -661,8 +661,8 @@ } }, "warning": { - "entity_not_found": "Endid ddim ar gael", - "entity_non_numeric": "Endid di-rhifol: {endid}" + "entity_not_found": "Endid ddim ar gael: {entity}", + "entity_non_numeric": "Endid di-rhifol: {entity}" } }, "page-authorize": { diff --git a/translations/de.json b/translations/de.json index c94ae68c52..07831e73ea 100644 --- a/translations/de.json +++ b/translations/de.json @@ -272,7 +272,7 @@ "paused": "pausiert" }, "person": { - "home": "Zuhause", + "home": "Zu Hause", "not_home": "Abwesend" } }, @@ -298,7 +298,7 @@ "not_home": "Abwes." }, "person": { - "home": "Zuhause", + "home": "Zu Hause", "not_home": "Abwesend" } }, diff --git a/translations/es-419.json b/translations/es-419.json index 600d3b461f..2bb0d88c06 100644 --- a/translations/es-419.json +++ b/translations/es-419.json @@ -213,8 +213,8 @@ "scening": "Reproduciendo Escena" }, "script": { - "off": "", - "on": "" + "off": "Apagado", + "on": "Encendido" }, "sensor": { "off": "", diff --git a/translations/eu.json b/translations/eu.json index 132f442750..4551db2cc7 100644 --- a/translations/eu.json +++ b/translations/eu.json @@ -1,11 +1,862 @@ { "panel": { "config": "Konfigurazioa", - "states": "Orokorra", + "states": "Laburpena", "map": "Mapa", - "logbook": "Logbook", + "logbook": "Erregistroa", "history": "Historia", "mailbox": "Postontzia", - "shopping_list": "Erosketa zerrenda" + "shopping_list": "Erosketa zerrenda", + "dev-services": "Zerbitzuak", + "dev-states": "Egoerak", + "dev-events": "Gertaerak", + "dev-templates": "Txantiloiak", + "dev-mqtt": "MQTT", + "dev-info": "Informazioa", + "calendar": "Egutegia", + "profile": "Profila" + }, + "state": { + "default": { + "off": "Itzalita", + "on": "Piztuta", + "unknown": "Ezezaguna", + "unavailable": "Ez dago erabilgarri" + }, + "alarm_control_panel": { + "pending": "Zain", + "triggered": "Abiarazita" + }, + "automation": { + "off": "Itzalita", + "on": "Piztuta" + }, + "binary_sensor": { + "default": { + "off": "Itzalita", + "on": "Piztuta" + }, + "moisture": { + "off": "Lehorra", + "on": "Buztita" + }, + "opening": { + "off": "Itxita", + "on": "Ireki" + }, + "safety": { + "off": "Babestuta" + }, + "presence": { + "off": "Kanpoan", + "on": "Etxean" + }, + "battery": { + "off": "Normala", + "on": "Baxua" + }, + "problem": { + "off": "Ondo", + "on": "Arazoa" + }, + "connectivity": { + "off": "Deskonektatuta", + "on": "Konektatuta" + }, + "cold": { + "off": "Normala", + "on": "Hotza" + }, + "door": { + "off": "Itxita", + "on": "Ireki" + }, + "garage_door": { + "off": "Itxita", + "on": "Ireki" + }, + "heat": { + "off": "Normala", + "on": "Beroa" + }, + "window": { + "off": "Itxita", + "on": "Ireki" + }, + "lock": { + "off": "Itxita", + "on": "Irekita" + } + }, + "calendar": { + "off": "Itzalita", + "on": "Piztuta" + }, + "camera": { + "recording": "Grabatzen" + }, + "climate": { + "off": "Itzalita", + "on": "Piztuta", + "heat": "Beroa", + "cool": "Hotza", + "auto": "Automatikoa", + "dry": "Lehorra", + "fan_only": "Haizagailua bakarrik", + "eco": "Eko", + "electric": "Elektrikoa", + "performance": "Errendimendua", + "high_demand": "Eskari handia", + "heat_pump": "Bero-ponpa", + "gas": "Gasa" + }, + "configurator": { + "configure": "Konfiguratu", + "configured": "Konfiguratuta" + }, + "cover": { + "open": "Irekita", + "opening": "Irekitzen", + "closed": "Itxita", + "closing": "Ixten", + "stopped": "Geldituta" + }, + "device_tracker": { + "home": "Etxean", + "not_home": "Kanpoan" + }, + "fan": { + "off": "Itzalita", + "on": "Piztuta" + }, + "group": { + "off": "Itzalita", + "on": "Piztuta", + "home": "Etxean", + "not_home": "Kanpoan", + "open": "Ireki", + "opening": "Irekitzen", + "closed": "Itxita", + "closing": "Ixten", + "stopped": "Geldirik", + "ok": "Itzalita", + "problem": "Arazoa" + }, + "input_boolean": { + "off": "Itzalita", + "on": "Piztuta" + }, + "light": { + "off": "Itzalita", + "on": "Piztuta" + }, + "media_player": { + "off": "Itzalita", + "on": "Piztuta" + }, + "plant": { + "ok": "Itzalita", + "problem": "Arazoa" + }, + "remote": { + "off": "Itzalita", + "on": "Piztuta" + }, + "script": { + "off": "Itzalita", + "on": "Piztuta" + }, + "sensor": { + "off": "Itzalita", + "on": "Piztuta" + }, + "sun": { + "above_horizon": "Horizonte gainetik", + "below_horizon": "Horizonte azpitik" + }, + "switch": { + "off": "Itzalita", + "on": "Piztuta" + }, + "zwave": { + "default": { + "initializing": "Hasieratzen", + "dead": "Hilda", + "sleeping": "Lotan", + "ready": "Prest" + }, + "query_stage": { + "initializing": "Hasieratzen ({query_stage})", + "dead": "Ez du erantzuten ({query_stage})" + } + }, + "weather": { + "clear-night": "Garbia, gaua", + "cloudy": "Hodeitsua", + "fog": "Lainoa", + "hail": "Txingorra", + "lightning": "Tximistak", + "lightning-rainy": "Tximistak, euritsua", + "partlycloudy": "Ostarteak", + "pouring": "Botatzen", + "rainy": "Euritsua", + "snowy": "Elurtsua", + "snowy-rainy": "Elurtsua, euritsua", + "sunny": "Eguzkitsua", + "windy": "Haizetsua", + "windy-variant": "Haizetsua" + }, + "vacuum": { + "cleaning": "Garbitzen", + "docked": "Basean", + "error": "Errorea", + "off": "Itzalita", + "on": "Piztuta", + "returning": "Basera itzultzen" + }, + "person": { + "home": "Etxean", + "not_home": "Kanpoan" + } + }, + "state_badge": { + "device_tracker": { + "home": "Etxean", + "not_home": "Kanpoan" + }, + "person": { + "home": "Etxean", + "not_home": "Kanpoan" + } + }, + "ui": { + "panel": { + "shopping-list": { + "clear_completed": "Osatutakoak ezabatu", + "add_item": "Artikulua gehitu" + }, + "mailbox": { + "empty": "Ez duzu mezurik", + "delete_prompt": "Mezu hau ezabatu?", + "delete_button": "Ezabatu" + }, + "config": { + "core": { + "caption": "Orokorra", + "section": { + "core": { + "reloading": { + "core": "Nukleoa birkargatu", + "group": "Taldeak birkargatu", + "automation": "Automatizazioak birkargatu", + "script": "Scriptak birkargatu" + }, + "server_management": { + "heading": "Zerbitzariaren kudeaketa", + "introduction": "Zure Home Assistant zerbitzaria... Home Assistantetik kontrolatu", + "restart": "Berrabiarazi", + "stop": "Gelditu" + } + } + } + }, + "script": { + "caption": "Script", + "description": "Scriptak sortu eta editatu" + }, + "zwave": { + "caption": "Z-Wave" + }, + "automation": { + "picker": { + "add_automation": "Automatizazioa gehitu", + "learn_more": "Automatizazioei buruz gehiago ikasi" + }, + "editor": { + "default_name": "Automatizazio berria", + "save": "Gorde", + "alias": "Izena", + "triggers": { + "header": "Abiarazleak", + "add": "Abiarazlea gehitu", + "duplicate": "Bikoiztu", + "delete": "Ezabatu", + "type_select": "Abiarazle mota", + "type": { + "event": { + "label": "Gertaera", + "event_type": "Gertaera mota" + }, + "state": { + "label": "Egoera" + }, + "homeassistant": { + "label": "Home Assistant", + "event": "Gertaera:", + "start": "Hasi", + "shutdown": "Itzali" + }, + "mqtt": { + "label": "MQTT", + "topic": "Gaia" + }, + "numeric_state": { + "above": "Honen gainetik", + "below": "Honen azpitik" + }, + "sun": { + "label": "Eguzkia", + "event": "Gertaera:", + "sunrise": "Egunsentia", + "sunset": "Ilunabarra" + }, + "template": { + "label": "Txantiloia", + "value_template": "Balio txantiloia" + }, + "time": { + "label": "Ordua", + "at": "Noiz" + }, + "zone": { + "enter": "Sartu", + "leave": "Utzi" + }, + "time_pattern": { + "hours": "Orduak", + "minutes": "Minutuak", + "seconds": "Segunduak" + }, + "geo_location": { + "label": "Geokokapena", + "source": "Iturria", + "event": "Gertaera:", + "enter": "Sartu", + "leave": "Utzi" + } + }, + "learn_more": "Abiarazleei buruz gehiago ikasi" + }, + "conditions": { + "header": "Baldintzak", + "add": "Baldintza gehitu", + "duplicate": "Bikoiztu", + "delete": "Ezabatu", + "type_select": "Baldintza mota", + "type": { + "state": { + "label": "Egoera", + "state": "Egoera" + }, + "sun": { + "label": "Eguzkia", + "sunrise": "Egunsentia", + "sunset": "Ilunabarra" + }, + "template": { + "label": "Txantiloia", + "value_template": "Valio txantiloia" + }, + "time": { + "label": "Denbora" + } + }, + "learn_more": "Baldintzei buruz gehiago ikasi" + }, + "actions": { + "header": "Ekintzak", + "add": "Ekintza gehitu", + "duplicate": "Bikoiztu", + "delete": "Ezabatu", + "unsupported_action": "Ekintza ez onartua: {action}", + "type_select": "Ekintza mota", + "type": { + "service": { + "label": "Zerbitzua deitu" + }, + "delay": { + "label": "Atzerapena", + "delay": "Atzerapena" + }, + "wait_template": { + "label": "Itxaron", + "wait_template": "Itxaron txantiloia" + }, + "condition": { + "label": "Baldintza" + } + }, + "learn_more": "Ekintzei buruz gehiago ikasi" + } + } + }, + "users": { + "caption": "Erabiltzaileak", + "description": "Erabiltzaileak kudeatu", + "picker": { + "title": "Erabiltzaileak" + }, + "editor": { + "rename_user": "Erabiltzailea berrizendatu", + "change_password": "Pasahitza aldatu", + "activate_user": "Erabiltzailea aktibatu", + "deactivate_user": "Erabiltzailea desaktibatu", + "delete_user": "Erabiltzailea ezabatu", + "caption": "Erabiltzailea ikusi" + }, + "add_user": { + "caption": "Erabiltzailea gehitu", + "name": "Izena", + "username": "Erabiltzaile izena", + "password": "Pasahitza", + "create": "Sortu" + } + }, + "cloud": { + "caption": "Home Assistant Cloud", + "description_login": "{email} bezala hasi duzu saioa", + "description_not_login": "Ez da saioa hasi" + }, + "integrations": { + "caption": "Integrazioak", + "configured": "Konfiguratuta", + "new": "Integrazio berri bat konfiguratu", + "configure": "Konfiguratu", + "none": "Ez dago ezer konfiguratuta", + "config_entry": { + "no_devices": "Integrazio honek ez du gailurik.", + "firmware": "Firmware: {version}", + "no_area": "Ez dago gunerik" + } + }, + "zha": { + "caption": "ZHA", + "services": { + "updateDeviceName": "Gailu honentzako izen pertsonalizatua ezarri gailuen erregistroan." + } + }, + "area_registry": { + "picker": { + "header": "Gune Erregistroa", + "integrations_page": "Integrazioen orria", + "no_areas": "Oraindik gunerik ez duzula dirudi!", + "create_area": "GUNEA SORTU" + }, + "create_area": "GUNEA SORTU", + "editor": { + "default_name": "Gune berria", + "delete": "EZABATU", + "update": "EGUNERATU", + "create": "SORTU" + } + }, + "entity_registry": { + "picker": { + "unavailable": "(ez dago eskuragarri)", + "integrations_page": "Integrazioak" + }, + "editor": { + "default_name": "Gune berria", + "delete": "EZABATU", + "update": "EGUNERATU" + } + }, + "person": { + "caption": "Pertsonak", + "detail": { + "name": "Izena" + } + } + }, + "profile": { + "push_notifications": { + "header": "Push jakinarazpenak", + "error_load_platform": "notify.html5 konfiguratu.", + "push_notifications": "Push jakinarazpenak", + "link_promo": "Gehiago ikasi" + }, + "language": { + "header": "Hizkuntza", + "link_promo": "Itzultzen lagundu", + "dropdown_label": "Hizkuntza" + }, + "themes": { + "header": "Gaia", + "error_no_theme": "Ez dago gairik eskuragarri", + "link_promo": "Gaiei buruz gehiago ikasi", + "dropdown_label": "Gaia" + }, + "refresh_tokens": { + "header": "Tokenak eguneratu", + "delete_failed": "Errorea sortu da sarbide tokena ezabatzerakoan.", + "not_used": "Ez da inoiz erabili", + "current_token_tooltip": "Ezin da uneko tokena ezabatu" + }, + "long_lived_access_tokens": { + "header": "Iraupen luzeko sarbide tokenak", + "delete_failed": "Errorea sortu da sarbide tokena ezabatzerakoan.", + "create": "Tokena Sortu", + "create_failed": "Ezin izan da sarbide token sortu.", + "prompt_name": "Izena?", + "prompt_copy_token": "Zure sarbide tokena kopiatu. Ez da berriro erakutsiko.", + "not_used": "Ez da inoiz erabili" + }, + "current_user": "{fullName} moduan hasi duzu saioa.", + "is_owner": "Jabea zara", + "logout": "Saioa itxi", + "change_password": { + "header": "Pasahitza aldatu", + "current_password": "Egungo pasahitza", + "new_password": "Pasahitz berria", + "confirm_new_password": "Pasahitz berria baieztatu", + "error_required": "Beharrezkoa", + "submit": "Bidali" + }, + "mfa": { + "enable": "Gaitu", + "confirm_disable": "{name} desgaitu nahi duzula ziur zaude?" + }, + "mfa_setup": { + "title_success": "Arrakasta!", + "close": "Itxi", + "submit": "Bidali" + } + }, + "page-authorize": { + "initializing": "Hasieratzen", + "form": { + "working": "Mesedez, itxaron", + "unknown_error": "Zerbait gaizki joan da", + "providers": { + "homeassistant": { + "step": { + "init": { + "data": { + "username": "Erabiltzaile izena", + "password": "Pasahitza" + } + }, + "mfa": { + "data": { + "code": "Bi faktoreko autentifikazio kodea" + } + } + }, + "error": { + "invalid_auth": "Erabiltzaile edo pasahitz okerra" + } + }, + "legacy_api_password": { + "step": { + "init": { + "data": { + "password": "API pasahitza" + } + } + } + }, + "trusted_networks": { + "step": { + "init": { + "data": { + "user": "Erabiltzailea" + } + } + }, + "abort": { + "not_whitelisted": "Zure ordenagailua ez dago baimenduta." + } + }, + "command_line": { + "step": { + "init": { + "data": { + "username": "Erabiltzaile izena", + "password": "Pasahitza" + } + } + } + } + } + } + }, + "page-onboarding": { + "user": { + "intro": "Erabiltzaile kontu bat sortuz has gaitezen.", + "required_field": "Beharrezkoa", + "data": { + "name": "Izena", + "username": "Erabiltzaile izena", + "password": "Pasahitza", + "password_confirm": "Pasahitza baieztatu" + }, + "create_account": "Kontua sortu", + "error": { + "required_fields": "Beharrezkoak diren eremu guztiak bete", + "password_not_match": "Pasahitzak ez datoz bat" + } + } + }, + "lovelace": { + "cards": { + "shopping-list": { + "checked_items": "Aukeratutako elementuak", + "add_item": "Elementua gehitu" + }, + "empty_state": { + "title": "Ongi etorri Etxera", + "go_to_integrations_page": "Integrazioen orrira joan." + } + }, + "editor": { + "edit_card": { + "header": "Txartelaren konfigurazioa", + "save": "Gorde", + "add": "Txartela gehitu", + "edit": "Editatu", + "delete": "Ezabatu", + "move": "Mugitu" + }, + "migrate": { + "header": "Konfigurazio Bateraezina", + "migrate": "Konfigurazioa migratu" + }, + "header": "Erabiltzaile interfazea editatu", + "edit_view": { + "header": "Konfigurazioa ikusi", + "add": "Bista gehitu", + "edit": "Bista editatu", + "delete": "Bista ezabatu" + }, + "save_config": { + "cancel": "Berdin dio", + "save": "Kontrola hartu" + }, + "raw_editor": { + "header": "Ezarpenak aldatu", + "save": "Gorde", + "unsaved_changes": "Gorde gabeko aldaketak", + "saved": "Gordeta" + } + }, + "menu": { + "configure_ui": "Erabiltzaile interfazea konfiguratu", + "help": "Laguntza" + } + }, + "logbook": { + "period": "Epea" + } + }, + "sidebar": { + "log_out": "Saioa itxi", + "developer_tools": "Garatzaileentzako tresnak" + }, + "common": { + "loading": "Kargatzen", + "save": "Gorde" + }, + "duration": { + "day": "{count} {count, plural,\n one {egun}\n other {egun}\n}", + "week": "{count} {count, plural,\n one {aste}\n other {aste}\n}", + "second": "{count} {count, plural,\n one {segundo}\n other {segundo}\n}", + "minute": "{count} {count, plural,\n one {minutu}\n other {minutu}\n}", + "hour": "{count} {count, plural,\n one {ordu}\n other {ordu}\n}" + }, + "login-form": { + "password": "Pasahitza", + "remember": "Gogoratu", + "log_in": "Saioa hasi" + }, + "card": { + "camera": { + "not_available": "Irudia ez dago eskuragarri" + }, + "scene": { + "activate": "Aktibatu" + }, + "script": { + "execute": "Exekutatu" + }, + "weather": { + "attributes": { + "air_pressure": "Aire presioa", + "humidity": "Hezetasuna", + "temperature": "Tenperatura", + "visibility": "Ikusgarritasuna", + "wind_speed": "Haizearen abiadura" + }, + "cardinal_direction": { + "e": "E", + "ene": "EIE", + "ese": "EHE", + "n": "I", + "ne": "IE", + "nne": "IIE", + "nw": "IM", + "nnw": "IIM", + "s": "H", + "se": "HE", + "sse": "HHE", + "ssw": "HHM", + "sw": "HM", + "w": "M", + "wnw": "MIM", + "wsw": "MHM" + }, + "forecast": "Iragarpena" + }, + "alarm_control_panel": { + "code": "Kodea", + "clear_code": "Garbitu" + }, + "cover": { + "position": "Posizioa" + }, + "fan": { + "speed": "Abiadura" + }, + "light": { + "brightness": "Distira", + "color_temperature": "Kolore tenperatura", + "effect": "Efektua" + }, + "media_player": { + "text_to_speak": "Esateko testua", + "source": "Iturria", + "sound_mode": "Soinu modua" + }, + "climate": { + "currently": "Orain", + "on_off": "Piztuta \/ itzalita", + "operation": "Modua", + "fan_mode": "Haizagailuaren modua", + "away_mode": "Etxetik kanpo" + }, + "lock": { + "code": "Kodea" + }, + "vacuum": { + "actions": { + "resume_cleaning": "Garbitzen jarraitu", + "return_to_base": "Basera itzuli", + "start_cleaning": "Garbitzen hasi", + "turn_on": "Piztu", + "turn_off": "Itzali" + } + }, + "water_heater": { + "currently": "Orain", + "on_off": "Piztuta \/ itzalita", + "operation": "Operazioa" + } + }, + "components": { + "service-picker": { + "service": "Zerbitzua" + }, + "relative_time": { + "past": "Orain dela {time}", + "future": "{time} barru", + "never": "Inoiz", + "duration": { + "second": "{count} {count, plural,\n one {segundo}\n other {segundo}\n}", + "minute": "{count} {count, plural,\n one {minutu}\n other {minutu}\n}", + "hour": "{count} {count, plural,\n one {ordu}\n other {ordu}\n}", + "day": "{count} {count, plural,\n one {egun}\n other {egun}\n}", + "week": "{count} {count, plural,\n one {aste}\n other {aste}\n}" + } + } + }, + "notification_toast": { + "entity_turned_on": "{entity} piztuta.", + "entity_turned_off": "{entity} itzalita.", + "service_called": "{service} zerbitzua deitu da.", + "connection_lost": "Konexioa galdu da. Berriro konektatzen..." + }, + "dialogs": { + "more_info_settings": { + "save": "Gorde", + "name": "Izena" + }, + "more_info_control": { + "script": { + "last_action": "Azken ekintza" + }, + "sun": { + "rising": "Igotzen", + "setting": "Ezarpena" + }, + "updater": { + "title": "Argibideak Eguneratu" + } + } + }, + "auth_store": { + "ask": "Saio hau gorde nahi duzu?", + "decline": "Ez, eskerrik asko", + "confirm": "Erabiltzailea gorde" + }, + "notification_drawer": { + "empty": "Jakinarazpenik ez", + "title": "Jakinarazpenak" + } + }, + "domain": { + "alarm_control_panel": "Alarmen kontrol panela", + "automation": "Automatizazioa", + "binary_sensor": "Sentsore bitarra", + "calendar": "Egutegia", + "camera": "Kamera", + "climate": "Klimatizazioa", + "configurator": "Konfiguratzailea", + "conversation": "Elkarrizketa", + "fan": "Haizagailua", + "group": "Taldea", + "input_boolean": "Sarrera boolearra", + "input_datetime": "Data sarrera", + "input_select": "Aukeraketa sarrera", + "input_number": "Zenbaki sarrera", + "input_text": "Testu sarrera", + "light": "Argia", + "lock": "Sarraila", + "mailbox": "Postontzia", + "notify": "Jakinarazi", + "plant": "Landarea", + "proximity": "Gertutasuna", + "remote": "Urrunekoa", + "scene": "Eszena", + "script": "Script", + "sensor": "Sentsorea", + "sun": "Eguzkia", + "updater": "Eguneratzailea", + "vacuum": "Xurgagailua", + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "Sistemaren Osasuna", + "person": "Pertsona" + }, + "attribute": { + "weather": { + "humidity": "Hezetasuna", + "visibility": "Ikusgarritasuna", + "wind_speed": "Haizearen abiadura" + } + }, + "state_attributes": { + "climate": { + "fan_mode": { + "off": "Itzalita", + "on": "Piztuta", + "auto": "Auto" + } + } + }, + "groups": { + "system-admin": "Administratzaileak", + "system-users": "Erabiltzaileak", + "system-read-only": "Soilik irakurtzeko erabiltzaileak" } } \ No newline at end of file diff --git a/translations/nl.json b/translations/nl.json index f08fb87d04..2ebeb3d665 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -606,7 +606,8 @@ "caption": "ZHA", "description": "Zigbee Home Automation netwerkbeheer", "services": { - "reconfigure": "Herconfigureer het ZHA-apparaat (heal device). Gebruik dit als je problemen hebt met het apparaat. Als het een apparaat met batterij is, zorg dan dat het wakker is en commando's accepteert wanneer je deze service gebruikt." + "reconfigure": "Herconfigureer het ZHA-apparaat (heal device). Gebruik dit als je problemen hebt met het apparaat. Als het een apparaat met batterij is, zorg dan dat het wakker is en commando's accepteert wanneer je deze service gebruikt.", + "updateDeviceName": "Stel een aangepaste naam in voor dit apparaat in het apparaatregister." } }, "area_registry": { @@ -617,6 +618,7 @@ "introduction": "Gebieden worden gebruikt om te bepalen waar apparaten zijn. Deze informatie wordt overal in de Home Assistant gebruikt om u te helpen bij het organiseren van uw interface, machtigingen en integraties met andere systemen.", "introduction2": "Als u apparaten in een gebied wilt plaatsen, gebruikt u de onderstaande koppeling om naar de integratiespagina te gaan en vervolgens op een geconfigureerde integratie te klikken om naar de apparaatkaarten te gaan.", "integrations_page": "Integratiespagina", + "no_areas": "Het lijkt erop dat je nog geen ruimtes hebt!", "create_area": "MAAK RUIMTE" }, "no_areas": "Het lijkt erop dat je nog geen gebieden hebt!", @@ -1161,6 +1163,8 @@ } }, "groups": { - "system-users": "Gebruikers" + "system-admin": "Beheerders", + "system-users": "Gebruikers", + "system-read-only": "Alleen-lezen gebruikers" } } \ No newline at end of file diff --git a/translations/pl.json b/translations/pl.json index f93ce17d31..74fa7f521d 100644 --- a/translations/pl.json +++ b/translations/pl.json @@ -570,7 +570,7 @@ }, "add_user": { "caption": "Dodaj użytkownika", - "name": "Nazwa", + "name": "Imię", "username": "Nazwa użytkownika", "password": "Hasło", "create": "Utwórz" diff --git a/translations/pt.json b/translations/pt.json index a5c4b5823f..c804d15f28 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -265,6 +265,15 @@ "on": "Ligado", "paused": "Em pausa", "returning": "A regressar ao cais" + }, + "timer": { + "active": "ativo", + "idle": "Em espera", + "paused": "Em pausa" + }, + "person": { + "home": "Casa", + "not_home": "Ausente" } }, "state_badge": { @@ -287,6 +296,10 @@ "device_tracker": { "home": "Casa", "not_home": "Fora" + }, + "person": { + "home": "Casa", + "not_home": "Ausente" } }, "ui": { @@ -319,10 +332,10 @@ "section": { "core": { "header": "Configuração e controlo do servidor", - "introduction": "Alterar a configuração pode ser um processo repetitivo. Nós sabemos. Esta seção pretende tornar a sua vida um pouco mais fácil.", + "introduction": "Alterar a configuração pode ser um processo repetitivo. Nós sabemos. Esta secção pretende tornar a sua vida um pouco mais fácil.", "validation": { "heading": "Validar a configuração", - "introduction": "Valide sua configuração caso tenha alterado recentemente a mesma e quiser certificar-se de que tudo é válido.", + "introduction": "Valide a sua configuração caso tenha alterado recentemente a mesma e quiser certificar-se de que tudo é válido.", "check_config": "Verificar a configuração", "valid": "Configuração válida!", "invalid": "Configuração inválida" @@ -360,7 +373,8 @@ "introduction": "O editor de automação permite criar e editar automações. Leia [as instruções] (https:\/\/home-assistant.io\/docs\/automation\/editor\/) para se certificar de que configurou o Home Assistant corretamente.", "pick_automation": "Escolha a automação a editar", "no_automations": "Não foi possível encontrar nenhuma automação editável", - "add_automation": "Acrescentar automação" + "add_automation": "Acrescentar automação", + "learn_more": "Saber mais sobre automações" }, "editor": { "introduction": "Crie automatizações para tornar a sua casa viva", @@ -492,7 +506,8 @@ "entity": "Entidade com localização", "zone": "Zona" } - } + }, + "learn_more": "Saber mais sobre condições" }, "actions": { "header": "Ações", @@ -525,7 +540,8 @@ "event": "Evento", "service_data": "Informação de Serviço" } - } + }, + "learn_more": "Saber mais sobre ações" } } }, @@ -548,7 +564,15 @@ "change_password": "Alterar palavra-passe", "activate_user": "Ativar utilizador", "deactivate_user": "Desativar utilizador", - "delete_user": "Apagar utilizador" + "delete_user": "Apagar utilizador", + "caption": "Ver utilizador" + }, + "add_user": { + "caption": "Adicionar Utilizador", + "name": "Nome", + "username": "Nome de Utilizador", + "password": "Password", + "create": "Criar" } }, "cloud": { @@ -588,7 +612,9 @@ "caption": "Registo de áreas", "description": "Visão geral de todas as áreas da sua casa.", "picker": { - "header": "Registo de áreas" + "header": "Registo de áreas", + "integrations_page": "Página de Integrações", + "create_area": "CRIAR ÁREA" }, "no_areas": "Parece que ainda não tem áreas!", "create_area": "CRIAR ÁREA", @@ -604,7 +630,8 @@ "description": "Visão geral de todas as entidades conhecidas.", "picker": { "header": "Registo de Entidades", - "unavailable": "(indisponível)" + "unavailable": "(indisponível)", + "integrations_page": "Página de Integrações" }, "editor": { "unavailable": "Esta entidade não está atualmente disponível.", @@ -799,11 +826,13 @@ "data": { "name": "Nome", "username": "Utilizador", - "password": "Palavra-passe" + "password": "Palavra-passe", + "password_confirm": "Confirme Password" }, "create_account": "Criar conta", "error": { - "required_fields": "Preencha todos os campos obrigatórios" + "required_fields": "Preencha todos os campos obrigatórios", + "password_not_match": "Password não coincide" } } }, @@ -855,7 +884,10 @@ "raw_editor": "Editor de configuração fonte." }, "raw_editor": { - "saved": "Salvou" + "header": "Editar configuração", + "save": "Guardar", + "unsaved_changes": "Alterações não gravadas", + "saved": "Guardou" } }, "menu": { @@ -1100,7 +1132,8 @@ "hassio": "Hass.io", "homeassistant": "Home Assistant", "lovelace": "Lovelace", - "system_health": "Saúde do sistema" + "system_health": "Saúde do sistema", + "person": "Pessoa" }, "attribute": { "weather": { @@ -1108,5 +1141,18 @@ "visibility": "Visibilidade", "wind_speed": "Vel. do vento" } + }, + "state_attributes": { + "climate": { + "fan_mode": { + "off": "Off", + "on": "On", + "auto": "Auto" + } + } + }, + "groups": { + "system-admin": "Administradores", + "system-users": "Utilizadores" } } \ No newline at end of file diff --git a/translations/ru.json b/translations/ru.json index 1faa0a1cc8..1fac4cec95 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -561,11 +561,11 @@ "title": "Пользователи" }, "editor": { - "rename_user": "Изменить имя пользователя", + "rename_user": "Изменить имя", "change_password": "Изменить пароль", - "activate_user": "Активировать пользователя", - "deactivate_user": "Деактивировать пользователя", - "delete_user": "Удалить пользователя", + "activate_user": "Активировать", + "deactivate_user": "Деактивировать", + "delete_user": "Удалить", "caption": "Просмотр пользователя" }, "add_user": { diff --git a/translations/sl.json b/translations/sl.json index 138bc8388b..7d7d01fc84 100644 --- a/translations/sl.json +++ b/translations/sl.json @@ -466,7 +466,7 @@ }, "conditions": { "header": "Pogoji", - "introduction": "Pogoji so neobvezni del pravila za avtomatizacijo in jih je mogoče uporabiti za preprečitev, da bi se dejanje zgodilo ob sprožitvi. Pogoji so zelo podobni sprožilcem, vendar so zelo različni. Sprožilec bo pogledal dogodke, ki se dogajajo v sistemu, medtem ko pogoj gleda samo na to, kako sistem trenutno izgleda. Sprožilec lahko opazi, da je stikalo vklopljeno. Pogoj lahko vidi le, če je stikalo trenutno vklopljeno ali izklopljeno. \n\n [Več o pogojih.] (Https:\/\/home-assistant.io\/docs\/scripts\/conditions\/)", + "introduction": "Pogoji so neobvezni del pravila za avtomatizacijo in jih je mogoče uporabiti za preprečitev, da bi se dejanje zgodilo ob sprožitvi. Pogoji so zelo podobni sprožilcem, vendar so zelo različni. Sprožilec bo pogledal dogodke, ki se dogajajo v sistemu, medtem, ko pogoj gleda samo na to, kako sistem trenutno izgleda. Sprožilec lahko opazi, da je stikalo vklopljeno. Pogoj lahko vidi le, če je stikalo trenutno vklopljeno ali izklopljeno. \n\n [Več o pogojih.] (Https:\/\/home-assistant.io\/docs\/scripts\/conditions\/)", "add": "Dodaj pogoj", "duplicate": "Podvoji", "delete": "Izbriši", @@ -606,7 +606,8 @@ "caption": "ZHA", "description": "Upravljanje omrežja za avtomatizacijo doma Zigbee", "services": { - "reconfigure": "Ponovno konfigurirajte napravo ZHA (\"pozdravite\" napravo). To uporabite, če imate z njo težave. Če ta naprava deluje na baterije, se prepričajte, da je budna in sprejema ukaze pri uporabi te storitve." + "reconfigure": "Ponovno konfigurirajte napravo ZHA (\"pozdravite\" napravo). To uporabite, če imate z njo težave. Če ta naprava deluje na baterije, se prepričajte, da je budna in sprejema ukaze pri uporabi te storitve.", + "updateDeviceName": "Nastavite ime po meri za to napravo v registru naprav." } }, "area_registry": { @@ -614,7 +615,11 @@ "description": "Pregled vseh območij v vašem domu.", "picker": { "header": "Register območij", - "integrations_page": "Stran za integracije" + "introduction": "Področja se uporabljajo za organizacijo področja naprav. Te informacije bodo uporabljene v celotnem Home Assistant-u in vam bodo pomagale pri organizaciji vašega vmesnika, dovoljenj in integracij z drugimi sistemi.", + "introduction2": "Če želite namestiti napravo na območje, uporabite spodnjo povezavo, da se pomaknete na stran za integracije, nato pa kliknite konfigurirano integracijo, da pridete do kartic naprave.", + "integrations_page": "Stran za integracije", + "no_areas": "Izgleda, da še nimate območij!", + "create_area": "USTVARITE OBMOČJE" }, "no_areas": "Izgleda, da še nimate območij!", "create_area": "USTVARITE OBMOČJE", @@ -631,6 +636,8 @@ "picker": { "header": "Register subjekta", "unavailable": "(ni na voljo)", + "introduction": "Home Assistant vodi register vseh entitet, ki jih je kdajkoli videl in jih je mogoče enolično identificirati. Vsak od teh entitet ima dodeljen ID entitete, ki bo rezerviran samo za to entiteto.", + "introduction2": "Z registrom entitet preglasite ime, spremenite ID entitete ali odstranite vnos iz Home Assistent-a. Opomba, odstranitev vnosa registra entitet ne bo odstranila entitete. Če želite to narediti, sledite spodnji povezavi in jo odstranite s strani za integracijo.", "integrations_page": "Stran za integracije" }, "editor": { @@ -826,11 +833,13 @@ "data": { "name": "Ime", "username": "Uporabniško ime", - "password": "Geslo" + "password": "Geslo", + "password_confirm": "Potrdi Geslo" }, "create_account": "Ustvarite račun", "error": { - "required_fields": "Izpolnite vsa zahtevana polja" + "required_fields": "Izpolnite vsa zahtevana polja", + "password_not_match": "Gesli se ne ujemata" } } }, @@ -1065,7 +1074,7 @@ "dialogs": { "more_info_settings": { "save": "Shrani", - "name": "Ime", + "name": "Preglasitev imena", "entity_id": "ID subjekta" }, "more_info_control": { @@ -1152,5 +1161,10 @@ "auto": "Samodejno" } } + }, + "groups": { + "system-admin": "Skrbniki", + "system-users": "Uporabniki", + "system-read-only": "Uporabniki \"samo za branje\"" } } \ No newline at end of file diff --git a/translations/tr.json b/translations/tr.json index 48737568af..98d45921d0 100644 --- a/translations/tr.json +++ b/translations/tr.json @@ -102,11 +102,11 @@ }, "door": { "off": "[%key:state::cover::kapalı%]", - "on": "[%key:state::cover::açık%]" + "on": "Açık" }, "garage_door": { "off": "[%key:state::cover::kapalı%]", - "on": "[%key:state::cover::açık%]" + "on": "Açık" }, "heat": { "off": "Normal", @@ -114,7 +114,7 @@ }, "window": { "off": "[%key:state::cover::kapalı%]", - "on": "[%key:state::cover::açık%]" + "on": "Açık" }, "lock": { "off": "Kilit kapalı", @@ -690,7 +690,7 @@ }, "duration": { "day": "{count}{count, plural,\n one { gün }\n other { gün }\n}", - "week": "{say}{say, çoğul,\n bir { hafta }\n diğer { hafta }\n}", + "week": "{count}{count, plural,\n one { hafta }\n other { hafta }\n}", "second": "{count}{count, plural,\n one { saniye }\n other { saniye }\n}" }, "login-form": { From e3e0d4618ece542ee881bcb4b75fe5dd899714a8 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 27 Mar 2019 21:21:20 -0700 Subject: [PATCH 28/29] Bumped version to 20190327.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b8f610553d..5ef268efa2 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="home-assistant-frontend", - version="20190321.0", + version="20190327.0", description="The Home Assistant frontend", url="https://github.com/home-assistant/home-assistant-polymer", author="The Home Assistant Authors", From 22e5792a8f36f36bbb7555fa6294ba363fe29f31 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 27 Mar 2019 21:24:46 -0700 Subject: [PATCH 29/29] Upgrade mwc (#3031) --- package.json | 4 +- yarn.lock | 172 ++++++++++++++++++++++++++++----------------------- 2 files changed, 96 insertions(+), 80 deletions(-) diff --git a/package.json b/package.json index d049b1ca4b..4898fc98b7 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,8 @@ "author": "Paulus Schoutsen (http://paulusschoutsen.nl)", "license": "Apache-2.0", "dependencies": { - "@material/mwc-button": "^0.4.0", - "@material/mwc-ripple": "^0.4.0", + "@material/mwc-button": "^0.5.0", + "@material/mwc-ripple": "^0.5.0", "@mdi/svg": "3.5.95", "@polymer/app-layout": "^3.0.1", "@polymer/app-localize-behavior": "^3.0.1", diff --git a/yarn.lock b/yarn.lock index 7ed5694ce9..121f2a2b7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -728,108 +728,124 @@ log-update "^2.3.0" strip-ansi "^3.0.1" -"@material/animation@^0.41.0": - version "0.41.0" - resolved "https://registry.yarnpkg.com/@material/animation/-/animation-0.41.0.tgz#315b45b32e1aeebee8a4cf555b8ad52076d09ddd" - integrity sha512-yYAwJbX3Q2AFd4dr6IYOsWLQy2HN8zWOFVl9AbUXunjzTfJCa/ecfXCriaT6qkmoNoHeTdJHRrsQJZC5GsPvzA== - -"@material/base@^0.41.0": - version "0.41.0" - resolved "https://registry.yarnpkg.com/@material/base/-/base-0.41.0.tgz#badadce711b4c25b1eb889a5e7581e32cd07c421" - integrity sha512-tEyzwBRu3d1H120SfKsDVYZHcqT5lKohh/7cWKR93aAaPDkSvjpKJIjyu2yuSkjpDduVZGzVocYbOvhUKhhzXQ== - -"@material/button@^0.44.0": - version "0.44.1" - resolved "https://registry.yarnpkg.com/@material/button/-/button-0.44.1.tgz#2a0bc0e6961128ace81e050770695c4aaad7f3bd" - integrity sha512-+eI0nI2zkxZOanPfeWzZPoQDbv2NqgUhUhPxERKoXEqkyJIne7gWRYMHqHjKPctsD2xmzgqGmGCLcrvhgFZ+FQ== +"@material/animation@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@material/animation/-/animation-1.0.0.tgz#dfd8575c8b031203917dc838ac0e3c0fe0f6709b" + integrity sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw== dependencies: - "@material/elevation" "^0.44.1" + tslib "^1.9.3" + +"@material/base@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@material/base/-/base-1.0.0.tgz#e4ef0b22c54aa887af94f5988fb1c0cb3245beba" + integrity sha512-5dxFp46x5FA+Epg6YHLzN+5zRt9S2wR84UdvVAEJ1egea94m9UHUg7y9tAnNSN16aexRSywmzyLwPr+i8PGEYA== + dependencies: + tslib "^1.9.3" + +"@material/button@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@material/button/-/button-1.1.0.tgz#dbb46c953040d3a161346e1d3cd057159b9a3c34" + integrity sha512-P1oZyyC1ELRe26vdnmax+fO3BWNmftDqHDDlQbJ+gfYMDQsNQtZNJU16ZbnVHsnzEXOpFj729imbmuLfnz8Nbg== + dependencies: + "@material/elevation" "^1.1.0" "@material/feature-targeting" "^0.44.1" - "@material/ripple" "^0.44.1" + "@material/ripple" "^1.1.0" "@material/rtl" "^0.42.0" - "@material/shape" "^0.44.1" - "@material/theme" "^0.43.0" - "@material/typography" "^0.44.1" + "@material/shape" "^1.0.0" + "@material/theme" "^1.1.0" + "@material/typography" "^1.0.0" -"@material/elevation@^0.44.1": - version "0.44.1" - resolved "https://registry.yarnpkg.com/@material/elevation/-/elevation-0.44.1.tgz#19efa293e195b00141711899e3c3fde6a3670454" - integrity sha512-Gr2x/FHysM4ty7sctLPT48pw7YItLZvhXsB4ZzXpdhuy7QshxllBW9NGlAMffzrmNu16MTl3ouGzbhArUYz4jw== +"@material/dom@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@material/dom/-/dom-1.1.0.tgz#3bd3d1a3415b4181118fecb182d93beda56a6f8c" + integrity sha512-+HWW38ZaM2UBPu4+7QCusLDSf4tFT31rsEXHkTkxYSg/QpDivfPx6YDz4OmYtafmhPR1d1YjqB3MYysUHdodyw== dependencies: - "@material/animation" "^0.41.0" + tslib "^1.9.3" + +"@material/elevation@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@material/elevation/-/elevation-1.1.0.tgz#def23c360ae067b43c1632a331b9883b9f679cc5" + integrity sha512-m4eATJvDhWK1BT+yA1iHz5mhAk8cV9olC4mjVzm4PTAqhDH2yya4WzjN1HPVHE/a65ObyZ7V4qopxu9MRocm3A== + dependencies: + "@material/animation" "^1.0.0" "@material/feature-targeting" "^0.44.1" - "@material/theme" "^0.43.0" + "@material/theme" "^1.1.0" "@material/feature-targeting@^0.44.1": version "0.44.1" resolved "https://registry.yarnpkg.com/@material/feature-targeting/-/feature-targeting-0.44.1.tgz#afafc80294e5efab94bee31a187273d43d34979a" integrity sha512-90cc7njn4aHbH9UxY8qgZth1W5JgOgcEdWdubH1t7sFkwqFxS5g3zgxSBt46TygFBVIXNZNq35Xmg80wgqO7Pg== -"@material/mwc-base@^0.3.6": - version "0.3.6" - resolved "https://registry.yarnpkg.com/@material/mwc-base/-/mwc-base-0.3.6.tgz#44382945509602adc3ba07b554e81e0f24810873" - integrity sha512-DVwsTJYCMSgIXzh7yGdn0CW11qz7/QaimPGbQ1jo4zyV/aizbetpKwFlkJj9Ut45/cCqZMlXIU2valjoO0dU8g== +"@material/mwc-base@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@material/mwc-base/-/mwc-base-0.5.0.tgz#21f9f237acea444b07a0fb1dfd45d30ef8f62374" + integrity sha512-G0n5LCmeXs9QR/ptHgUmV043wUVN2Uq1CWxUeGisGEPCI5e/mt9ISk5/7MubO25yF9muQeQXxXdRt/kFc7xGCg== dependencies: - lit-element "^2.0.0-rc.2" - lit-html "^1.0.0-rc.2" - -"@material/mwc-button@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@material/mwc-button/-/mwc-button-0.4.0.tgz#e1e4b23ced20a641e04ea7c35fe36e4aa190879e" - integrity sha512-308Lrol26bgauUwzSo/RzW9o6Aglff6YTpxsbNi3+bR4FIh20MpYxo6umKG8ix9xhezZ7YQFD0PR3JLLRUZJEg== - dependencies: - "@material/button" "^0.44.0" - "@material/mwc-base" "^0.3.6" - "@material/mwc-icon" "^0.3.6" - "@material/mwc-ripple" "^0.4.0" - -"@material/mwc-icon@^0.3.6": - version "0.3.6" - resolved "https://registry.yarnpkg.com/@material/mwc-icon/-/mwc-icon-0.3.6.tgz#0a4fe6984300f240b0a3371e037c9fd59957c40f" - integrity sha512-ssdZSY1z2i9n974iXZiy26wZzMAd4/LkPCbHtpUAOqxWLq+8r3djmPuoKhIdiI4YCarpBOpgm8HQEuHdvClkGw== - dependencies: - "@material/mwc-base" "^0.3.6" - -"@material/mwc-ripple@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@material/mwc-ripple/-/mwc-ripple-0.4.0.tgz#42b3b3c17e55d576deceb20e955f87e68d2615bb" - integrity sha512-KaNR4QSleKYNb97drVqM+TEmxgR7/ClJSXeK1rGcbvDAaE+3vx5wlPW1Ems23eLqSsFNntgy43wPbRkMjogIew== - dependencies: - "@material/mwc-base" "^0.3.6" - "@material/ripple" "^0.44.0" + "@material/base" "^1.0.0" + lit-element "^2.0.1" lit-html "^1.0.0" -"@material/ripple@^0.44.0", "@material/ripple@^0.44.1": - version "0.44.1" - resolved "https://registry.yarnpkg.com/@material/ripple/-/ripple-0.44.1.tgz#79cb2ddf1f998498d877d3e3c46b50fed6f13b01" - integrity sha512-prJ1p3bR+GvwAtJgtdeIixsnRVApN3bizGnX7upKoqxsqbBDHj84JxaO8EsG9bjruG/LJu8Fb6WKKdIp2oXHTA== +"@material/mwc-button@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@material/mwc-button/-/mwc-button-0.5.0.tgz#3456bfd9ef7d91d96c623952cca974216bf47f3e" + integrity sha512-XFzMuEGCtiT80fw5B6TibyAq3LPTUKXlbvgGg8kRSFsWJUXLfZKzCp/J3oJRGxZeSut33HiYXoQ1FAq9cygXeA== dependencies: - "@material/animation" "^0.41.0" - "@material/base" "^0.41.0" + "@material/button" "^1.0.0" + "@material/mwc-base" "^0.5.0" + "@material/mwc-icon" "^0.5.0" + "@material/mwc-ripple" "^0.5.0" + +"@material/mwc-icon@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@material/mwc-icon/-/mwc-icon-0.5.0.tgz#432a1c5b7d817f1d04341b3c4bb8ef514cbd8cb6" + integrity sha512-vDzNc3sYPm9I5cG//TiYM5BTt3zW283zC8F5mx2rmtK3E7/UXRZmT6b94rv9em7mEUv86DedYPzCzND8oXctxA== + dependencies: + "@material/mwc-base" "^0.5.0" + +"@material/mwc-ripple@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@material/mwc-ripple/-/mwc-ripple-0.5.0.tgz#6520971df2ff067ef52121c3cc0c4d8960d61977" + integrity sha512-vOB9ZpbBKnNsE+d4GoZIUoupk2am5kHBHqGkwSXXTt4c01SO0HRWkdNxayB2QAHgN56Xnsct0z0/pdfoZz7lKA== + dependencies: + "@material/mwc-base" "^0.5.0" + "@material/ripple" "^1.0.0" + lit-html "^1.0.0" + +"@material/ripple@^1.0.0", "@material/ripple@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@material/ripple/-/ripple-1.1.0.tgz#236016fb30c8366faf143297df2c38166d84ffbc" + integrity sha512-mkfDBZAmxjpRG7V9TrfOmLxt1g/wvGHCXtYPgvH7W8ozjf53edqxLOFENEdvHbie27y9nyixzXn0gzU0HnxSeA== + dependencies: + "@material/animation" "^1.0.0" + "@material/base" "^1.0.0" + "@material/dom" "^1.1.0" "@material/feature-targeting" "^0.44.1" - "@material/theme" "^0.43.0" + "@material/theme" "^1.1.0" + tslib "^1.9.3" "@material/rtl@^0.42.0": version "0.42.0" resolved "https://registry.yarnpkg.com/@material/rtl/-/rtl-0.42.0.tgz#1836e78186c2d8b996f6fbf97adab203535335bc" integrity sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w== -"@material/shape@^0.44.1": - version "0.44.1" - resolved "https://registry.yarnpkg.com/@material/shape/-/shape-0.44.1.tgz#ff4d5d42b07c5781306677bffee43234b756ea8e" - integrity sha512-8mCDQmyTEhDK+HX8Tap2Lc82QlVySlXU8zDCNkWoIn1ge+UnRezSDjE4y4P1ABegN5PrkJZPartuQ1U0ttIYXw== +"@material/shape@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@material/shape/-/shape-1.0.0.tgz#bef17de1f282e5c71138338a34078d8402308f65" + integrity sha512-zfXEacPQZmH+ujVtaFyfAsYiF46j1QCcFzJeZVouG4pznrbA7XD6614Ywg0wbyWX5iB6hD52ld/IN+R/6oxKqA== dependencies: "@material/feature-targeting" "^0.44.1" -"@material/theme@^0.43.0": - version "0.43.0" - resolved "https://registry.yarnpkg.com/@material/theme/-/theme-0.43.0.tgz#6d9fa113c82e841817882172c152d60d2d203ca6" - integrity sha512-/zndZL6EihI18v2mYd4O8xvOBAAXmLeHyHVK28LozSAaJ9okQgD25wq5Ktk95oMTmPIC+rH66KcK6371ivNk8g== +"@material/theme@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@material/theme/-/theme-1.1.0.tgz#9c95dd804168c23c30589fcf09ecc5af5b3d1adc" + integrity sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ== + dependencies: + "@material/feature-targeting" "^0.44.1" -"@material/typography@^0.44.1": - version "0.44.1" - resolved "https://registry.yarnpkg.com/@material/typography/-/typography-0.44.1.tgz#a94f01172f9122180bc2ce0aa55658183a35590d" - integrity sha512-wMXHusg+Lp5Fdgoj3m0c+Lt6GCeGSh3EPRtQ1TQ2bwdBa0et2FqBaQRgXoq3tVmr0O/7unTfa0DoXlh4nVp1wA== +"@material/typography@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@material/typography/-/typography-1.0.0.tgz#327ecfcac5ee3af8a3a102f3f125a761202f4189" + integrity sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA== dependencies: "@material/feature-targeting" "^0.44.1" @@ -8542,14 +8558,14 @@ listr@^0.14.2: p-map "^2.0.0" rxjs "^6.3.3" -lit-element@^2.0.0-rc.2, lit-element@^2.1.0: +lit-element@^2.0.1, lit-element@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-2.1.0.tgz#85bc3f1da0227f4b13de8a1be978229b9fa327e9" integrity sha512-0z/KHm1xZweivfOVRr8AKR06+D3k02u15m9s4jkuRdnGe5wfmEwePzrQQBsSZNILdnfJvfo3TJOeGhBCVZaPbw== dependencies: lit-html "^1.0.0" -lit-html@^1.0.0, lit-html@^1.0.0-rc.2: +lit-html@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-1.0.0.tgz#3dc3781a8ca68a9b5c2ff2a61e263662b9b2267b" integrity sha512-oeWlpLmBW3gFl7979Wol2LKITpmKTUFNn7PnFbh6YNynF61W74l6x5WhwItAwPRSATpexaX1egNnRzlN4GOtfQ== @@ -13274,7 +13290,7 @@ tslib@1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ== -tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==