From cc969e547c97eab850f38d17cc6888b4874c326d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 12 Jul 2019 11:18:01 -0700 Subject: [PATCH 1/7] Add frontend version to info (#3354) --- src/panels/developer-tools/info/developer-tools-info.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/panels/developer-tools/info/developer-tools-info.ts b/src/panels/developer-tools/info/developer-tools-info.ts index 6e248a97c4..6bb200a205 100644 --- a/src/panels/developer-tools/info/developer-tools-info.ts +++ b/src/panels/developer-tools/info/developer-tools-info.ts @@ -14,7 +14,8 @@ import "./system-log-card"; import "./error-log-card"; import "./system-health-card"; -const JS_VERSION = __BUILD__; +const JS_TYPE = __BUILD__; +const JS_VERSION = __VERSION__; const OPT_IN_PANEL = "states"; class HaPanelDevInfo extends LitElement { @@ -92,7 +93,7 @@ class HaPanelDevInfo extends LitElement { >.

- Frontend JavaScript version: ${JS_VERSION} + Frontend version: ${JS_VERSION} - ${JS_TYPE} ${customUiList.length > 0 ? html`

From e99d6f8e6af0a1a28f4bb742db399923f40940bf Mon Sep 17 00:00:00 2001 From: Sean Mooney Date: Fri, 12 Jul 2019 15:07:46 -0400 Subject: [PATCH 2/7] Fix incorrect tooltip on Add Person button (#3355) The tooltip for the add person button incorrectly says "Create Area" when hovered. This should fix it, I think. --- src/panels/config/person/ha-config-person.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/config/person/ha-config-person.ts b/src/panels/config/person/ha-config-person.ts index 402aa2f29d..b4c34cce11 100644 --- a/src/panels/config/person/ha-config-person.ts +++ b/src/panels/config/person/ha-config-person.ts @@ -112,7 +112,7 @@ class HaConfigPerson extends LitElement { `; From b4dd971829eb811b4b18fb4344f230c7ad2083ff Mon Sep 17 00:00:00 2001 From: Charles Garwood Date: Fri, 12 Jul 2019 16:07:50 -0400 Subject: [PATCH 3/7] Z-Wave Config Panel Updates (#3349) * Display network status, hide buttons if network is stopped. * travis/lint updates * Review comments * Add translations * lint * Missed a translation * lint again... * Fix unsubscribe function? * lint again * Remove state_str * Code review comments * fix for lit re-rendering & possible undefined value --- src/data/zwave.ts | 18 ++ src/panels/config/zwave/zwave-network.ts | 347 +++++++++++++---------- src/translations/en.json | 26 +- 3 files changed, 243 insertions(+), 148 deletions(-) create mode 100644 src/data/zwave.ts diff --git a/src/data/zwave.ts b/src/data/zwave.ts new file mode 100644 index 0000000000..f86b11bd28 --- /dev/null +++ b/src/data/zwave.ts @@ -0,0 +1,18 @@ +import { HomeAssistant } from "../types"; + +export interface ZWaveNetworkStatus { + state: number; +} + +export const ZWAVE_NETWORK_STATE_STOPPED = 0; +export const ZWAVE_NETWORK_STATE_FAILED = 1; +export const ZWAVE_NETWORK_STATE_STARTED = 5; +export const ZWAVE_NETWORK_STATE_AWAKED = 7; +export const ZWAVE_NETWORK_STATE_READY = 10; + +export const fetchNetworkStatus = ( + hass: HomeAssistant +): Promise => + hass.callWS({ + type: "zwave/network_status", + }); diff --git a/src/panels/config/zwave/zwave-network.ts b/src/panels/config/zwave/zwave-network.ts index aeed3c23c0..41dd3457f7 100644 --- a/src/panels/config/zwave/zwave-network.ts +++ b/src/panels/config/zwave/zwave-network.ts @@ -1,4 +1,5 @@ import "@polymer/paper-icon-button/paper-icon-button"; +import "@polymer/paper-spinner/paper-spinner"; import { css, @@ -9,14 +10,24 @@ import { property, TemplateResult, } from "lit-element"; +import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; +import { + fetchNetworkStatus, + ZWaveNetworkStatus, + ZWAVE_NETWORK_STATE_STOPPED, + ZWAVE_NETWORK_STATE_STARTED, + ZWAVE_NETWORK_STATE_AWAKED, + ZWAVE_NETWORK_STATE_READY, +} from "../../../data/zwave"; import "../../../components/buttons/ha-call-api-button"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/ha-service-description"; import "../../../components/ha-card"; +import "../../../components/ha-icon"; import "../ha-config-section"; @customElement("zwave-network") @@ -24,12 +35,28 @@ export class ZwaveNetwork extends LitElement { @property() public hass!: HomeAssistant; @property() public isWide!: boolean; @property() private _showHelp = false; + @property() private _networkStatus?: ZWaveNetworkStatus; + @property() private _unsubs: Array> = []; + + public disconnectedCallback(): void { + this._unsubscribe(); + } + + protected firstUpdated(changedProps): void { + super.firstUpdated(changedProps); + this._getNetworkStatus(); + this._subscribe(); + } protected render(): TemplateResult | void { return html`
- Z-Wave Network Management + + ${this.hass!.localize( + "ui.panel.config.zwave.network_management.header" + )} +
- Run commands that affect the Z-Wave network. You won't get feedback on - whether the command succeeded, but you can look in the OZW Log to try - to figure out. + ${this.hass!.localize( + "ui.panel.config.zwave.network_management.introduction" + )} - -
- - Add Node Secure - - - - - - Add Node - - - - - - Remove Node - - - -
-
- - Cancel Command - - - -
-
- - Heal Network - - - - - Start Network - - - - - - Stop Network - - - - - - Soft Reset - - - - - - Test Network - - - - - - Save Config - -
-
+ ${this._networkStatus + ? html` + +
+ ${this._networkStatus.state === ZWAVE_NETWORK_STATE_STOPPED + ? html` + + ${this.hass!.localize( + "ui.panel.config.zwave.network_status.network_stopped" + )} + ` + : this._networkStatus.state === ZWAVE_NETWORK_STATE_STARTED + ? html` + + ${this.hass!.localize( + "ui.panel.config.zwave.network_status.network_starting" + )}
+ + ${this.hass!.localize( + "ui.panel.config.zwave.network_status.network_starting_note" + )} + + ` + : this._networkStatus.state === ZWAVE_NETWORK_STATE_AWAKED + ? html` + + ${this.hass!.localize( + "ui.panel.config.zwave.network_status.network_started" + )}
+ + ${this.hass!.localize( + "ui.panel.config.zwave.network_status.network_started_note_some_queried" + )} + + ` + : this._networkStatus.state === ZWAVE_NETWORK_STATE_READY + ? html` + ${this.hass!.localize( + "ui.panel.config.zwave.network_status.network_started" + )}
+ + ${this.hass!.localize( + "ui.panel.config.zwave.network_status.network_started_note_all_queried" + )} + + ` + : ""} +
+
+ ${this._networkStatus.state >= ZWAVE_NETWORK_STATE_AWAKED + ? html` + ${this._generateServiceButton("stop_network")} + ${this._generateServiceButton("heal_network")} + ${this._generateServiceButton("test_network")} + ` + : html` + ${this._generateServiceButton("start_network")} + `} +
+ ${this._networkStatus.state >= ZWAVE_NETWORK_STATE_AWAKED + ? html` +
+ ${this._generateServiceButton("soft_reset")} + + ${this.hass!.localize( + "ui.panel.config.zwave.services.save_config" + )} + +
+ ` + : ""} +
+ ${this._networkStatus.state >= ZWAVE_NETWORK_STATE_AWAKED + ? html` + +
+ ${this._generateServiceButton("add_node_secure")} + ${this._generateServiceButton("add_node")} + ${this._generateServiceButton("remove_node")} +
+
+ ${this._generateServiceButton("cancel_command")} +
+
+ ` + : ""} + ` + : ""}
`; } + private async _getNetworkStatus(): Promise { + this._networkStatus = await fetchNetworkStatus(this.hass!); + } + + private _subscribe(): void { + this._unsubs = [ + "zwave.network_start", + "zwave.network_stop", + "zwave.network_ready", + "zwave.network_complete", + "zwave.network_complete_some_dead", + ].map((e) => + this.hass!.connection.subscribeEvents( + (event) => this._handleEvent(event), + e + ) + ); + } + + private _unsubscribe(): void { + while (this._unsubs.length) { + this._unsubs.pop()!.then((unsub) => unsub()); + } + } + + private _handleEvent(event) { + if (event.event_type === "zwave.network_start") { + // Optimistically set the state, wait 1s and poll the backend + // The backend will still report a state of 0 when the 'network_start' + // event is first fired. + if (this._networkStatus) { + this._networkStatus = { ...this._networkStatus, state: 5 }; + } + setTimeout(() => this._getNetworkStatus, 1000); + } else { + this._getNetworkStatus(); + } + } + private _onHelpTap(): void { this._showHelp = !this._showHelp; } + private _generateServiceButton(service: string) { + return html` + + ${this.hass!.localize("ui.panel.config.zwave.services." + service)} + + + + `; + } + static get styles(): CSSResult[] { return [ haStyle, @@ -201,6 +234,26 @@ export class ZwaveNetwork extends LitElement { margin-top: 24px; } + .network-status { + text-align: center; + } + + .network-status div.details { + font-size: 1.5rem; + padding: 24px; + } + + .network-status ha-icon { + display: block; + margin: 0px auto 16px; + width: 48px; + height: 48px; + } + + .network-status small { + font-size: 1rem; + } + ha-card { margin: 0 auto; max-width: 600px; diff --git a/src/translations/en.json b/src/translations/en.json index c4aa870314..b6e6d7f158 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -921,7 +921,31 @@ }, "zwave": { "caption": "Z-Wave", - "description": "Manage your Z-Wave network" + "description": "Manage your Z-Wave network", + "network_management": { + "header": "Z-Wave Network Management", + "introduction": "Run commands that affect the Z-Wave network. You won't get feedback on whether most commands succeeded, but you can check the OZW Log to try to find out." + }, + "network_status": { + "network_stopped": "Z-Wave Network Stopped", + "network_starting": "Starting Z-Wave Network...", + "network_starting_note": "This may take a while depending on the size of your network.", + "network_started": "Z-Wave Network Started", + "network_started_note_some_queried": "Awake nodes have been queried. Sleeping nodes will be queried when they wake.", + "network_started_note_all_queried": "All nodes have been queried." + }, + "services": { + "start_network": "Start Network", + "stop_network": "Stop Network", + "heal_network": "Heal Network", + "test_network": "Test Network", + "soft_reset": "Soft Reset", + "save_config": "Save Config", + "add_node_secure": "Add Node Secure", + "add_node": "Add Node", + "remove_node": "Remove Node", + "cancel_command": "Cancel Command" + } } }, "history": { From f258aa28186c897b4146c35a351ad07732f80f5b Mon Sep 17 00:00:00 2001 From: Timmo Date: Fri, 12 Jul 2019 21:08:51 +0100 Subject: [PATCH 4/7] Replace standard browser scrollbar for overview and sidebar (#3350) * :scroll: Replace standard browser scrollbar for overview and sidebar * :hammer: Remove from main --- src/components/ha-sidebar.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/components/ha-sidebar.ts b/src/components/ha-sidebar.ts index fddaa2b958..dc62678da0 100644 --- a/src/components/ha-sidebar.ts +++ b/src/components/ha-sidebar.ts @@ -412,6 +412,17 @@ class HaSidebar extends LitElement { display: initial; } + ::-webkit-scrollbar { + width: 0.4rem; + height: 0.4rem; + } + + ::-webkit-scrollbar-thumb { + -webkit-border-radius: 4px; + border-radius: 4px; + background: var(--secondary-text-color); + } + paper-listbox { padding: 4px 0; display: flex; From 8f3d5fdb7d68491ff1278f2a77db7f8196820c2f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 12 Jul 2019 14:42:56 -0700 Subject: [PATCH 5/7] Fix scrollbar on Firefox (#3357) --- src/components/ha-sidebar.ts | 8 +++++--- src/resources/ha-style.ts | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/ha-sidebar.ts b/src/components/ha-sidebar.ts index dc62678da0..3f57d25ba9 100644 --- a/src/components/ha-sidebar.ts +++ b/src/components/ha-sidebar.ts @@ -412,15 +412,15 @@ class HaSidebar extends LitElement { display: initial; } - ::-webkit-scrollbar { + paper-listbox::-webkit-scrollbar { width: 0.4rem; height: 0.4rem; } - ::-webkit-scrollbar-thumb { + paper-listbox::-webkit-scrollbar-thumb { -webkit-border-radius: 4px; border-radius: 4px; - background: var(--secondary-text-color); + background: var(--scrollbar-thumb-color); } paper-listbox { @@ -431,6 +431,8 @@ class HaSidebar extends LitElement { height: calc(100% - 196px); overflow-y: auto; overflow-x: hidden; + scrollbar-color: var(--scrollbar-thumb-color) transparent; + scrollbar-width: thin; } a { diff --git a/src/resources/ha-style.ts b/src/resources/ha-style.ts index 6838312427..cb2fc997c7 100644 --- a/src/resources/ha-style.ts +++ b/src/resources/ha-style.ts @@ -31,6 +31,8 @@ documentContainer.innerHTML = ` --accent-color: #ff9800; --divider-color: rgba(0, 0, 0, .12); + --scrollbar-thumb-color: rgb(194, 194, 194); + /* states and badges */ --state-icon-color: #44739e; --state-icon-active-color: #FDD835; From 8e3b41885d9c091c9ca1a1797083f2457e592fd6 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 12 Jul 2019 14:44:07 -0700 Subject: [PATCH 6/7] Update translations --- translations/cy.json | 47 +++++++++++++++++++++++++++--- translations/es-419.json | 62 ++++++++++++++++++++++++++++++++++++++-- translations/fr.json | 18 ++++++++++-- translations/hu.json | 4 ++- translations/is.json | 5 +++- 5 files changed, 124 insertions(+), 12 deletions(-) diff --git a/translations/cy.json b/translations/cy.json index 70416fc575..62de0150d8 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -143,7 +143,8 @@ "high_demand": "Galw uchel", "heat_pump": "Pwmp gwres", "gas": "Nwy", - "manual": "Llawlyfr" + "manual": "Llawlyfr", + "heat_cool": "Awto" }, "configurator": { "configure": "Ffurfweddu", @@ -560,8 +561,25 @@ "caption": "Z-Wave", "description": "Rheoli eich rhwydwaith Z-Wave" }, + "cloud": { + "description_login": "Wedi mewngofnodi fel {email}", + "description_not_login": "Heb fewngofnodi", + "description_features": "Rheolaeth oddi cartref, integreiddio gyda Alexa a Google Assistant." + }, "integrations": { + "caption": "Integreiddiadau", + "description": "Rheoli dyfeisiau a gwasanaethau cysylltiedig", + "discovered": "Darganfuwyd", + "configured": "Wedi'i ffurfweddu", + "new": "Sefydlu integreiddiad newydd", + "configure": "Ffurfweddu", + "none": "Dim byd wedi'i ffurfweddu eto.", "config_entry": { + "no_devices": "Tydi'r integreiddad yma ddim efo dyfeisiadau.", + "no_device": "Endidau heb ddyfeisiau", + "delete_confirm": "A ydych yn siŵr bod chi eisiau dileu'r integreiddiad yma?", + "restart_confirm": "Ailgychwyn Home Assistant i ddarfod dileu'r integreiddiad hwn", + "manuf": "gan {manufacturer}", "via": "Cysylltiad drwy", "firmware": "Cadarnwedd: {version}", "device_unavailable": "Dyfais ddim ar gael", @@ -653,9 +671,6 @@ "password": "Cyfrinair", "create": "Creu" } - }, - "cloud": { - "description_features": "Rheolaeth oddi cartref, integreiddio gyda Alexa a Google Assistant." } }, "lovelace": { @@ -669,6 +684,14 @@ "title": "Croeso Gartref", "no_devices": "Mae'r dudalen hon yn eich galluogi i reoli'ch dyfeisiau, ond mae'n edrych fel nad oes gennych ddyfeisiau wedi eu sefydlu eto. Ewch i'r dudalen integreiddio i ddechrau.", "go_to_integrations_page": "Ewch i'r dudalen integreiddio." + }, + "picture-elements": { + "hold": "Disgwyl", + "tap": "Tarwch:", + "navigate_to": "Ewch i {location}", + "toggle": "Toglo {enw}", + "call_service": "Galw gwasanaeth {name}", + "more_info": "Dangos mwy o wybodaeth: {name}" } }, "editor": { @@ -783,6 +806,9 @@ "page-demo": { "cards": { "demo": { + "demo_by": "gan {name}", + "next_demo": "Demo nesaf", + "introduction": "Croeso adre! Rydych wedi cyrraedd demo Home Assistant lle rydym yn arddangos y UIs gorau a grewyd gan ein cymuned.", "learn_more": "Dysgwch fwy am Home Assistant" } }, @@ -891,6 +917,9 @@ "arm_night": "Larwm nos", "armed_custom_bypass": "Ffordd osgoi personol", "arm_custom_bypass": "Ffordd osgoi personol" + }, + "climate": { + "preset_mode": "Rhagosodiad" } }, "components": { @@ -978,6 +1007,16 @@ "off": "Off", "on": "Ar", "auto": "Awto" + }, + "preset_mode": { + "none": "Dim", + "eco": "Eco", + "away": "I ffwrdd", + "boost": "Cynydd", + "comfort": "Cyfforddus", + "home": "Cartref", + "sleep": "Cysgu", + "activity": "Gweithgaredd" } } }, diff --git a/translations/es-419.json b/translations/es-419.json index 1d9ab06394..2f40a5737d 100644 --- a/translations/es-419.json +++ b/translations/es-419.json @@ -145,7 +145,8 @@ "high_demand": "Alta Demanda", "heat_pump": "Bomba de Calor", "gas": "Gas", - "manual": "Manual" + "manual": "Manual", + "heat_cool": "Automático" }, "configurator": { "configure": "Configurar", @@ -619,7 +620,8 @@ "firmware": "Firmware: {version}", "device_unavailable": "dispositivo no disponible", "entity_unavailable": "entidad no disponible", - "no_area": "Ninguna área" + "no_area": "Ninguna área", + "hub": "Conectado a través de" }, "config_flow": { "external_step": { @@ -970,6 +972,49 @@ "refresh": "Actualizar" }, "reload_lovelace": "Recargar Lovelace" + }, + "page-demo": { + "cards": { + "demo": { + "demo_by": "por {name}", + "next_demo": "Siguiente demostración", + "introduction": "¡Bienvenido a casa! Ha llegado a la demostración de Home Assistant donde mostramos las mejores interfaces de usuario creadas por nuestra comunidad.", + "learn_more": "Aprenda más sobre Home Assistant" + } + }, + "config": { + "arsaboo": { + "names": { + "upstairs": "Piso de arriba", + "family_room": "Habitación familiar", + "kitchen": "Cocina", + "patio": "Patio", + "hallway": "Pasillo", + "master_bedroom": "Recamara principal", + "left": "Izquierda", + "right": "Derecha", + "mirror": "Espejo" + }, + "labels": { + "lights": "Luces", + "information": "Información", + "morning_commute": "Viaje de mañana", + "commute_home": "Viaje a casa", + "entertainment": "Entretenimiento", + "activity": "Actividad", + "hdmi_input": "Entrada HDMI", + "hdmi_switcher": "Conmutador HDMI", + "volume": "Volumen", + "total_tv_time": "Tiempo total de TV", + "turn_tv_off": "Apagar la televisión", + "air": "Aire" + }, + "unit": { + "watching": "viendo", + "minutes_abbr": "mín." + } + } + } } }, "sidebar": { @@ -1078,7 +1123,8 @@ "fan_mode": "Modo del ventilador", "swing_mode": "Modo de oscilación", "away_mode": "Fuera de Casa", - "aux_heat": "Calor auxiliar" + "aux_heat": "Calor auxiliar", + "preset_mode": "Preestablecido" }, "lock": { "code": "Código", @@ -1223,6 +1269,16 @@ "off": "Apagado", "on": "Encendido", "auto": "Auto" + }, + "preset_mode": { + "none": "Ninguno", + "eco": "Eco", + "away": "Fuera de casa", + "boost": "Aumentar", + "comfort": "Comodidad", + "home": "En Casa", + "sleep": "Dormir", + "activity": "Actividad" } } }, diff --git a/translations/fr.json b/translations/fr.json index 87d20641ce..911223f365 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -145,7 +145,8 @@ "high_demand": "Forte demande", "heat_pump": "Pompe à chaleur", "gas": "Gaz", - "manual": "Manuel" + "manual": "Manuel", + "heat_cool": "Automatique" }, "configurator": { "configure": "Configurer", @@ -297,7 +298,7 @@ }, "device_tracker": { "home": "Maison", - "not_home": "Absent.e" + "not_home": "Absent(e)" }, "person": { "home": "Présent", @@ -1122,7 +1123,8 @@ "fan_mode": "Mode de ventilation", "swing_mode": "Mode de balancement", "away_mode": "Mode \"Absent\"", - "aux_heat": "Chauffage d'appoint" + "aux_heat": "Chauffage d'appoint", + "preset_mode": "Préréglage" }, "lock": { "code": "Code", @@ -1267,6 +1269,16 @@ "off": "Off", "on": "On", "auto": "Auto" + }, + "preset_mode": { + "none": "Aucun", + "eco": "Eco", + "away": "Absent", + "boost": "Renforcer", + "comfort": "Confort", + "home": "Accueil", + "sleep": "Veille", + "activity": "Activité" } } }, diff --git a/translations/hu.json b/translations/hu.json index 43067963a9..5cbb2ce7e9 100644 --- a/translations/hu.json +++ b/translations/hu.json @@ -1123,7 +1123,8 @@ "fan_mode": "Sebesség", "swing_mode": "Forgási mód", "away_mode": "Távoli mód", - "aux_heat": "Külső melegítő" + "aux_heat": "Külső melegítő", + "preset_mode": "Beállítási mód" }, "lock": { "code": "Kód", @@ -1273,6 +1274,7 @@ "none": "Nincs", "eco": "Takarékos", "away": "Távol", + "boost": "Turbo", "comfort": "Komfort", "home": "Otthon", "sleep": "Alvás", diff --git a/translations/is.json b/translations/is.json index d2b85024d2..87a66f4a5e 100644 --- a/translations/is.json +++ b/translations/is.json @@ -122,7 +122,8 @@ "eco": "Sparnaður", "heat_pump": "Hitadæla", "gas": "Gas", - "manual": "Handvirkt" + "manual": "Handvirkt", + "heat_cool": "Sjálfvirkt" }, "cover": { "open": "Opin", @@ -393,6 +394,7 @@ "zone": { "label": "Öryggissvæði", "entity": "Eining með staðsetningu", + "zone": "Svæði", "event": "Viðburður:", "enter": "Koma", "leave": "Brottför" @@ -1094,6 +1096,7 @@ }, "domain": { "automation": "Sjálfvirkni", + "binary_sensor": "Tvíundar skynjari", "calendar": "Dagatal", "camera": "Myndavél", "climate": "Loftslag", From 4bdc82f0eda4671fb5dbe1f65a073c0c36c7e0ab Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 12 Jul 2019 14:44:22 -0700 Subject: [PATCH 7/7] Bumped version to 20190712.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d90b10390c..f7b4d98d63 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="home-assistant-frontend", - version="20190710.0", + version="20190712.0", description="The Home Assistant frontend", url="https://github.com/home-assistant/home-assistant-polymer", author="The Home Assistant Authors",