From 30c47a65f4f28273f4a133cbcc9957894349546d Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Mon, 7 Sep 2020 19:47:25 -0500 Subject: [PATCH 01/29] fix more info content --- src/dialogs/more-info/ha-more-info-dialog.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dialogs/more-info/ha-more-info-dialog.ts b/src/dialogs/more-info/ha-more-info-dialog.ts index 086040ddef..7738ee7349 100644 --- a/src/dialogs/more-info/ha-more-info-dialog.ts +++ b/src/dialogs/more-info/ha-more-info-dialog.ts @@ -274,6 +274,7 @@ export class MoreInfoDialog extends LitElement { --mdc-theme-on-primary: var(--primary-text-color); --mdc-theme-primary: var(--mdc-theme-surface); flex-shrink: 0; + display: block; } @media all and (max-width: 450px), all and (max-height: 500px) { From 8b1801f378dc5174186dad7db8843a1c9312d9d8 Mon Sep 17 00:00:00 2001 From: Zack Barett Date: Tue, 8 Sep 2020 02:14:34 -0500 Subject: [PATCH 02/29] Fix header on media browser in safari (#6838) --- src/components/media-player/ha-media-player-browse.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/media-player/ha-media-player-browse.ts b/src/components/media-player/ha-media-player-browse.ts index 8f54e1204c..0d9cde1946 100644 --- a/src/components/media-player/ha-media-player-browse.ts +++ b/src/components/media-player/ha-media-player-browse.ts @@ -172,6 +172,7 @@ export class HaMediaPlayerBrowse extends LitElement {
@@ -543,6 +544,7 @@ export class HaMediaPlayerBrowse extends LitElement { .header { background-color: var(--card-background-color); position: sticky; + position: -webkit-sticky; top: 0; z-index: 5; padding: 20px 24px 10px; @@ -740,6 +742,10 @@ export class HaMediaPlayerBrowse extends LitElement { padding: 0; } + :host([narrow]) .header.no-dialog { + display: block; + } + :host([narrow]) .header_button { position: absolute; top: 14px; From d7448ecb952afef1509d33c15e7061312c508120 Mon Sep 17 00:00:00 2001 From: Zack Barett Date: Tue, 8 Sep 2020 02:17:49 -0500 Subject: [PATCH 03/29] Fix Calendar Card in Add Card dialog (#6833) --- src/panels/lovelace/cards/hui-calendar-card.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/panels/lovelace/cards/hui-calendar-card.ts b/src/panels/lovelace/cards/hui-calendar-card.ts index 2351454829..ee94fb807c 100644 --- a/src/panels/lovelace/cards/hui-calendar-card.ts +++ b/src/panels/lovelace/cards/hui-calendar-card.ts @@ -76,11 +76,11 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard { private _resizeObserver?: ResizeObserver; public setConfig(config: CalendarCardConfig): void { - if (!config.entities) { + if (!config.entities?.length) { throw new Error("Entities must be defined"); } - if (config.entities && !Array.isArray(config.entities)) { + if (!Array.isArray(config.entities)) { throw new Error("Entities need to be an array"); } From 100ba8edfaa6e37c73e69c4603e58988ca1f897a Mon Sep 17 00:00:00 2001 From: Zack Barett Date: Tue, 8 Sep 2020 04:37:49 -0500 Subject: [PATCH 04/29] Add allowed options to entities struct so UI editor can still be used (#6823) --- src/panels/lovelace/editor/types.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/panels/lovelace/editor/types.ts b/src/panels/lovelace/editor/types.ts index 04a2755a4b..5d9a335a10 100644 --- a/src/panels/lovelace/editor/types.ts +++ b/src/panels/lovelace/editor/types.ts @@ -5,7 +5,7 @@ import { ShowViewConfig, } from "../../../data/lovelace"; import { EntityConfig } from "../entity-rows/types"; -import { optional, string, object, union } from "superstruct"; +import { optional, string, object, union, boolean } from "superstruct"; import { EntityId } from "../common/structs/is-entity-id"; import { Icon } from "../common/structs/is-icon"; @@ -81,6 +81,10 @@ export const entitiesConfigStruct = union([ entity: EntityId, name: optional(string()), icon: optional(Icon), + image: optional(string()), + secondary_info: optional(string()), + format: optional(string()), + state_color: optional(boolean()), }), EntityId, ]); From 6e0e169b6e89b2b85a217843f04c7fbe729e3420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Tue, 8 Sep 2020 13:27:59 +0200 Subject: [PATCH 05/29] Add reload for platforms with reload service (#6851) --- .../server_control/ha-config-server-control.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/panels/config/server_control/ha-config-server-control.ts b/src/panels/config/server_control/ha-config-server-control.ts index 7cd8e63160..04fbc5b237 100644 --- a/src/panels/config/server_control/ha-config-server-control.ts +++ b/src/panels/config/server_control/ha-config-server-control.ts @@ -23,6 +23,8 @@ import { HomeAssistant, Route } from "../../../types"; import "../ha-config-section"; import { configSections } from "../ha-panel-config"; +const platformsWithReload = ["template"]; + @customElement("ha-config-server-control") export class HaConfigServerControl extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -49,11 +51,13 @@ export class HaConfigServerControl extends LitElement { changedProperties.has("hass") && (!oldHass || oldHass.config.components !== this.hass.config.components) ) { - this._reloadableDomains = this.hass.config.components.filter( - (component) => - !component.includes(".") && - isServiceLoaded(this.hass, component, "reload") - ); + this._reloadableDomains = this.hass.config.components + .concat(platformsWithReload) + .filter( + (component) => + !component.includes(".") && + isServiceLoaded(this.hass, component, "reload") + ); } } From 67b46881684a9e061029c2a6448a3602dfeb2062 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 8 Sep 2020 13:28:29 +0200 Subject: [PATCH 06/29] Make time wider in logbook (#6854) Fixes #6842 --- src/panels/logbook/ha-logbook.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/logbook/ha-logbook.ts b/src/panels/logbook/ha-logbook.ts index 1270db9619..cf49dd24ba 100644 --- a/src/panels/logbook/ha-logbook.ts +++ b/src/panels/logbook/ha-logbook.ts @@ -216,7 +216,7 @@ class HaLogbook extends LitElement { display: flex; justify-content: center; flex-direction: column; - width: 70px; + width: 75px; flex-shrink: 0; font-size: 12px; color: var(--secondary-text-color); From 82e91783209f8b96c7184b99c34b9adac8f9e491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Tue, 8 Sep 2020 13:56:51 +0200 Subject: [PATCH 07/29] Add warning class to delete (#6852) * Add error class to delete * Apply suggestions from code review Co-authored-by: Bram Kragten * Add missing haStyle Co-authored-by: Bram Kragten --- .../action/ha-automation-action-row.ts | 2 +- .../condition/ha-automation-condition-row.ts | 34 +++++++++++-------- .../trigger/ha-automation-trigger-row.ts | 2 +- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/panels/config/automation/action/ha-automation-action-row.ts b/src/panels/config/automation/action/ha-automation-action-row.ts index 420d339e28..d9cf65ce8c 100644 --- a/src/panels/config/automation/action/ha-automation-action-row.ts +++ b/src/panels/config/automation/action/ha-automation-action-row.ts @@ -173,7 +173,7 @@ export default class HaAutomationActionRow extends LitElement { "ui.panel.config.automation.editor.actions.duplicate" )} - + ${this.hass.localize( "ui.panel.config.automation.editor.actions.delete" )} diff --git a/src/panels/config/automation/condition/ha-automation-condition-row.ts b/src/panels/config/automation/condition/ha-automation-condition-row.ts index 1f51b47f13..89bbfcab54 100644 --- a/src/panels/config/automation/condition/ha-automation-condition-row.ts +++ b/src/panels/config/automation/condition/ha-automation-condition-row.ts @@ -19,6 +19,7 @@ import { Condition } from "../../../../data/automation"; import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box"; import { HomeAssistant } from "../../../../types"; import "./ha-automation-condition-editor"; +import { haStyle } from "../../../../resources/styles"; export interface ConditionElement extends LitElement { condition: Condition; @@ -86,7 +87,7 @@ export default class HaAutomationConditionRow extends LitElement { "ui.panel.config.automation.editor.actions.duplicate" )} - + ${this.hass.localize( "ui.panel.config.automation.editor.actions.delete" )} @@ -134,20 +135,23 @@ export default class HaAutomationConditionRow extends LitElement { this._yamlMode = !this._yamlMode; } - static get styles(): CSSResult { - return css` - .card-menu { - float: right; - z-index: 3; - --mdc-theme-text-primary-on-background: var(--primary-text-color); - } - .rtl .card-menu { - float: left; - } - mwc-list-item[disabled] { - --mdc-theme-text-primary-on-background: var(--disabled-text-color); - } - `; + static get styles(): CSSResult[] { + return [ + haStyle, + css` + .card-menu { + float: right; + z-index: 3; + --mdc-theme-text-primary-on-background: var(--primary-text-color); + } + .rtl .card-menu { + float: left; + } + mwc-list-item[disabled] { + --mdc-theme-text-primary-on-background: var(--disabled-text-color); + } + `, + ]; } } diff --git a/src/panels/config/automation/trigger/ha-automation-trigger-row.ts b/src/panels/config/automation/trigger/ha-automation-trigger-row.ts index feeda91773..aa80ff1a96 100644 --- a/src/panels/config/automation/trigger/ha-automation-trigger-row.ts +++ b/src/panels/config/automation/trigger/ha-automation-trigger-row.ts @@ -118,7 +118,7 @@ export default class HaAutomationTriggerRow extends LitElement { "ui.panel.config.automation.editor.actions.duplicate" )} - + ${this.hass.localize( "ui.panel.config.automation.editor.actions.delete" )} From 4631994f2041b48385dce589bd94fa0e87c5d662 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 8 Sep 2020 14:10:34 +0200 Subject: [PATCH 08/29] Fix sidebar issues (#6853) * Fix sidebar issues * fix navigate in demo --- src/components/ha-sidebar.ts | 26 ++++++++++++++----- .../directives/action-handler-directive.ts | 9 ++++--- src/resources/ha-sortable-style.ts | 2 -- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/components/ha-sidebar.ts b/src/components/ha-sidebar.ts index 1226fffbc4..d02c7bbd60 100644 --- a/src/components/ha-sidebar.ts +++ b/src/components/ha-sidebar.ts @@ -322,7 +322,7 @@ class HaSidebar extends LitElement { )} href="#external-app-configuration" tabindex="-1" - @click=${this._handleExternalAppConfiguration} + @panel-tap=${this._handleExternalAppConfiguration} @mouseenter=${this._itemMouseEnter} @mouseleave=${this._itemMouseLeave} > @@ -479,7 +479,8 @@ class HaSidebar extends LitElement { } private async _handleAction(ev: CustomEvent) { - if (ev.detail.action !== "hold") { + if (ev.detail.action === "tap") { + fireEvent(ev.target as HTMLElement, "panel-tap"); return; } @@ -497,6 +498,10 @@ class HaSidebar extends LitElement { } this._editMode = true; + if (!this.expanded) { + fireEvent(this, "hass-toggle-menu"); + } + await this.updateComplete; this._createSortable(); @@ -655,8 +660,11 @@ class HaSidebar extends LitElement { ); } - private _handlePanelTap(ev: Event) { - navigate(this, (ev.currentTarget as HTMLAnchorElement).href); + private async _handlePanelTap(ev: Event) { + const path = __DEMO__ + ? (ev.currentTarget as HTMLAnchorElement).getAttribute("href")! + : (ev.currentTarget as HTMLAnchorElement).href; + navigate(this, path); } private _renderPanel( @@ -668,10 +676,10 @@ class HaSidebar extends LitElement { return html` @@ -980,4 +988,8 @@ declare global { interface HTMLElementTagNameMap { "ha-sidebar": HaSidebar; } + + interface HASSDomEvents { + "panel-tap": undefined; + } } diff --git a/src/panels/lovelace/common/directives/action-handler-directive.ts b/src/panels/lovelace/common/directives/action-handler-directive.ts index 0c245a4764..3b0ea378c8 100644 --- a/src/panels/lovelace/common/directives/action-handler-directive.ts +++ b/src/panels/lovelace/common/directives/action-handler-directive.ts @@ -154,6 +154,7 @@ class ActionHandler extends HTMLElement implements ActionHandler { if (["touchend", "touchcancel"].includes(ev.type) && this.cancelled) { return; } + const target = ev.target as HTMLElement; // Prevent mouse event if touch event if (ev.cancelable) { ev.preventDefault(); @@ -164,7 +165,7 @@ class ActionHandler extends HTMLElement implements ActionHandler { this.timer = undefined; } if (options.hasHold && this.held) { - fireEvent(element, "action", { action: "hold" }); + fireEvent(target, "action", { action: "hold" }); } else if (options.hasDoubleClick) { if ( (ev.type === "click" && (ev as MouseEvent).detail < 2) || @@ -172,15 +173,15 @@ class ActionHandler extends HTMLElement implements ActionHandler { ) { this.dblClickTimeout = window.setTimeout(() => { this.dblClickTimeout = undefined; - fireEvent(element, "action", { action: "tap" }); + fireEvent(target, "action", { action: "tap" }); }, 250); } else { clearTimeout(this.dblClickTimeout); this.dblClickTimeout = undefined; - fireEvent(element, "action", { action: "double_tap" }); + fireEvent(target, "action", { action: "double_tap" }); } } else { - fireEvent(element, "action", { action: "tap" }); + fireEvent(target, "action", { action: "tap" }); } }; diff --git a/src/resources/ha-sortable-style.ts b/src/resources/ha-sortable-style.ts index aa5ffe7789..5751f54819 100644 --- a/src/resources/ha-sortable-style.ts +++ b/src/resources/ha-sortable-style.ts @@ -20,8 +20,6 @@ export const sortableStyles = css` #sortable { outline: none; - display: flex; - flex-direction: column; } .sortable-ghost { From 9149bb9333b3ec7b191671bf4128138282664cca Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 8 Sep 2020 15:41:17 +0200 Subject: [PATCH 09/29] Remove deprecated HTML support (#6858) --- src/entrypoints/app.ts | 2 - src/html/index.html.template | 4 - src/panels/lovelace/common/load-resources.ts | 6 - src/resources/html-import/import-href.js | 101 ----- src/resources/html-import/polyfill.js | 451 ------------------- src/util/custom-panel/load-custom-panel.ts | 11 - 6 files changed, 575 deletions(-) delete mode 100644 src/resources/html-import/import-href.js delete mode 100644 src/resources/html-import/polyfill.js diff --git a/src/entrypoints/app.ts b/src/entrypoints/app.ts index bb4b54b6e7..a4dd8580d4 100644 --- a/src/entrypoints/app.ts +++ b/src/entrypoints/app.ts @@ -7,5 +7,3 @@ import "../util/legacy-support"; setPassiveTouchGestures(true); (window as any).frontendVersion = __VERSION__; - -import("../resources/html-import/polyfill"); diff --git a/src/html/index.html.template b/src/html/index.html.template index fe4271c0fb..f5d8be97d1 100644 --- a/src/html/index.html.template +++ b/src/html/index.html.template @@ -100,9 +100,5 @@ {% endfor -%} } - - {% for extra_url in extra_urls -%} - - {% endfor -%} diff --git a/src/panels/lovelace/common/load-resources.ts b/src/panels/lovelace/common/load-resources.ts index c996f25562..5b9fb6d316 100644 --- a/src/panels/lovelace/common/load-resources.ts +++ b/src/panels/lovelace/common/load-resources.ts @@ -30,12 +30,6 @@ export const loadLovelaceResources = ( loadModule(normalizedUrl); break; - case "html": - import( - /* webpackChunkName: "import-href-polyfill" */ "../../../resources/html-import/import-href" - ).then(({ importHref }) => importHref(normalizedUrl)); - break; - default: // eslint-disable-next-line console.warn(`Unknown resource type specified: ${resource.type}`); diff --git a/src/resources/html-import/import-href.js b/src/resources/html-import/import-href.js deleted file mode 100644 index 32083338c3..0000000000 --- a/src/resources/html-import/import-href.js +++ /dev/null @@ -1,101 +0,0 @@ -/* eslint-disable */ -import "./polyfill"; -/** -@license -Copyright (c) 2017 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 -*/ - -// run a callback when HTMLImports are ready or immediately if -// this api is not available. -function whenImportsReady(cb) { - if (window.HTMLImports) { - HTMLImports.whenReady(cb); - } else { - cb(); - } -} - -/** - * Convenience method for importing an HTML document imperatively. - * - * This method creates a new `` element with - * the provided URL and appends it to the document to start loading. - * In the `onload` callback, the `import` property of the `link` - * element will contain the imported document contents. - * - * @param {string} href URL to document to load. - * @param {?function(!Event):void=} onload Callback to notify when an import successfully - * loaded. - * @param {?function(!ErrorEvent):void=} onerror Callback to notify when an import - * unsuccessfully loaded. - * @param {boolean=} optAsync True if the import should be loaded `async`. - * Defaults to `false`. - * @return {!HTMLLinkElement} The link element for the URL to be loaded. - */ -export const importHref = function (href, onload, onerror, optAsync) { - let link /** @type {HTMLLinkElement} */ = document.head.querySelector( - 'link[href="' + href + '"][import-href]' - ); - if (!link) { - link = /** @type {HTMLLinkElement} */ (document.createElement("link")); - link.rel = "import"; - link.href = href; - link.setAttribute("import-href", ""); - } - // always ensure link has `async` attribute if user specified one, - // even if it was previously not async. This is considered less confusing. - if (optAsync) { - link.setAttribute("async", ""); - } - // NOTE: the link may now be in 3 states: (1) pending insertion, - // (2) inflight, (3) already loaded. In each case, we need to add - // event listeners to process callbacks. - const cleanup = function () { - link.removeEventListener("load", loadListener); - link.removeEventListener("error", errorListener); - }; - let loadListener = function (event) { - cleanup(); - // In case of a successful load, cache the load event on the link so - // that it can be used to short-circuit this method in the future when - // it is called with the same href param. - link.__dynamicImportLoaded = true; - if (onload) { - whenImportsReady(() => { - onload(event); - }); - } - }; - let errorListener = function (event) { - cleanup(); - // In case of an error, remove the link from the document so that it - // will be automatically created again the next time `importHref` is - // called. - if (link.parentNode) { - link.parentNode.removeChild(link); - } - if (onerror) { - whenImportsReady(() => { - onerror(event); - }); - } - }; - link.addEventListener("load", loadListener); - link.addEventListener("error", errorListener); - if (link.parentNode == null) { - document.head.appendChild(link); - // if the link already loaded, dispatch a fake load event - // so that listeners are called and get a proper event argument. - } else if (link.__dynamicImportLoaded) { - link.dispatchEvent(new Event("load")); - } - return link; -}; - -export const importHrefPromise = (href) => - new Promise((resolve, reject) => importHref(href, resolve, reject)); diff --git a/src/resources/html-import/polyfill.js b/src/resources/html-import/polyfill.js deleted file mode 100644 index 51844ed272..0000000000 --- a/src/resources/html-import/polyfill.js +++ /dev/null @@ -1,451 +0,0 @@ -/* eslint-disable */ -/* - 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 -*/ -(function (q) { - function y(a, b) { - if ("function" === typeof window.CustomEvent) return new CustomEvent(a, b); - var c = document.createEvent("CustomEvent"); - c.initCustomEvent(a, !!b.bubbles, !!b.cancelable, b.detail); - return c; - } - function m(a) { - if (u) return a.ownerDocument !== document ? a.ownerDocument : null; - var b = a.__importDoc; - if (!b && a.parentNode) { - b = a.parentNode; - if ("function" === typeof b.closest) b = b.closest("link[rel=import]"); - else for (; !r(b) && (b = b.parentNode); ); - a.__importDoc = b; - } - return b; - } - function D(a) { - var b = k(document, "link[rel=import]:not([import-dependency])"), - c = b.length; - c - ? g(b, function (b) { - return t(b, function () { - 0 === --c && a(); - }); - }) - : a(); - } - function z(a) { - function b() { - "loading" !== document.readyState && - document.body && - (document.removeEventListener("readystatechange", b), a()); - } - document.addEventListener("readystatechange", b); - b(); - } - function A(a) { - z(function () { - return D(function () { - return a && a(); - }); - }); - } - function t(a, b) { - if (a.__loaded) b && b(); - else if ( - ("script" === a.localName && !a.src) || - ("style" === a.localName && !a.firstChild) - ) - (a.__loaded = !0), b && b(); - else { - var c = function (d) { - a.removeEventListener(d.type, c); - a.__loaded = !0; - b && b(); - }; - a.addEventListener("load", c); - (v && "style" === a.localName) || a.addEventListener("error", c); - } - } - function r(a) { - return ( - a.nodeType === Node.ELEMENT_NODE && - "link" === a.localName && - "import" === a.rel - ); - } - function h() { - var a = this; - this.a = {}; - this.b = 0; - this.g = new MutationObserver(function (b) { - return a.w(b); - }); - this.g.observe(document.head, { childList: !0, subtree: !0 }); - this.loadImports(document); - } - function B(a) { - g(k(a, "template"), function (a) { - g( - k( - a.content, - 'script:not([type]),script[type="application/javascript"],script[type="text/javascript"]' - ), - function (a) { - var b = document.createElement("script"); - g(a.attributes, function (a) { - return b.setAttribute(a.name, a.value); - }); - b.textContent = a.textContent; - a.parentNode.replaceChild(b, a); - } - ); - B(a.content); - }); - } - function k(a, b) { - return a.childNodes.length ? a.querySelectorAll(b) : E; - } - function g(a, b, c) { - var d = a ? a.length : 0, - f = c ? -1 : 1; - for (c = c ? d - 1 : 0; c < d && 0 <= c; c += f) b(a[c], c); - } - var n = document.createElement("link"), - u = "import" in n, - E = n.querySelectorAll("*"), - w = null; - !1 === "currentScript" in document && - Object.defineProperty(document, "currentScript", { - get: function () { - return ( - w || - ("complete" !== document.readyState - ? document.scripts[document.scripts.length - 1] - : null) - ); - }, - configurable: !0, - }); - var F = /(url\()([^)]*)(\))/g, - G = /(@import[\s]+(?!url\())([^;]*)(;)/g, - H = /(]*)(rel=['|"]?stylesheet['|"]?[^>]*>)/g, - e = { - u: function (a, b) { - a.href && a.setAttribute("href", e.c(a.getAttribute("href"), b)); - a.src && a.setAttribute("src", e.c(a.getAttribute("src"), b)); - if ("style" === a.localName) { - var c = e.o(a.textContent, b, F); - a.textContent = e.o(c, b, G); - } - }, - o: function (a, b, c) { - return a.replace(c, function (a, c, l, g) { - a = l.replace(/["']/g, ""); - b && (a = e.c(a, b)); - return c + "'" + a + "'" + g; - }); - }, - c: function (a, b) { - if (void 0 === e.f) { - e.f = !1; - try { - var c = new URL("b", "http://a"); - c.pathname = "c%20d"; - e.f = "http://a/c%20d" === c.href; - } catch (d) {} - } - if (e.f) return new URL(a, b).href; - c = e.s; - c || - ((c = document.implementation.createHTMLDocument("temp")), - (e.s = c), - (c.i = c.createElement("base")), - c.head.appendChild(c.i), - (c.h = c.createElement("a"))); - c.i.href = b; - c.h.href = a; - return c.h.href || a; - }, - }, - C = { - async: !0, - load: function (a, b, c) { - if (a) - if (a.match(/^data:/)) { - a = a.split(","); - var d = a[1]; - d = -1 < a[0].indexOf(";base64") ? atob(d) : decodeURIComponent(d); - b(d); - } else { - var f = new XMLHttpRequest(); - f.open("GET", a, C.async); - f.onload = function () { - var a = f.responseURL || f.getResponseHeader("Location"); - a && - 0 === a.indexOf("/") && - (a = - (location.origin || - location.protocol + "//" + location.host) + a); - var d = f.response || f.responseText; - 304 === f.status || - 0 === f.status || - (200 <= f.status && 300 > f.status) - ? b(d, a) - : c(d); - }; - f.send(); - } - else c("error: href must be specified"); - }, - }, - v = - /Trident/.test(navigator.userAgent) || - /Edge\/\d./i.test(navigator.userAgent); - h.prototype.loadImports = function (a) { - var b = this; - g(k(a, "link[rel=import]"), function (a) { - return b.l(a); - }); - }; - h.prototype.l = function (a) { - var b = this, - c = a.href; - if (void 0 !== this.a[c]) { - var d = this.a[c]; - d && d.__loaded && ((a.__import = d), this.j(a)); - } else - this.b++, - (this.a[c] = "pending"), - C.load( - c, - function (a, d) { - a = b.A(a, d || c); - b.a[c] = a; - b.b--; - b.loadImports(a); - b.m(); - }, - function () { - b.a[c] = null; - b.b--; - b.m(); - } - ); - }; - h.prototype.A = function (a, b) { - if (!a) return document.createDocumentFragment(); - v && - (a = a.replace(H, function (a, b, c) { - return -1 === a.indexOf("type=") ? b + " type=import-disable " + c : a; - })); - var c = document.createElement("template"); - c.innerHTML = a; - if (c.content) (a = c.content), B(a); - else - for (a = document.createDocumentFragment(); c.firstChild; ) - a.appendChild(c.firstChild); - if ((c = a.querySelector("base"))) - (b = e.c(c.getAttribute("href"), b)), c.removeAttribute("href"); - var d = 0; - g( - k( - a, - 'link[rel=import],link[rel=stylesheet][href][type=import-disable],style:not([type]),link[rel=stylesheet][href]:not([type]),script:not([type]),script[type="application/javascript"],script[type="text/javascript"]' - ), - function (a) { - t(a); - e.u(a, b); - a.setAttribute("import-dependency", ""); - "script" === a.localName && - !a.src && - a.textContent && - (a.setAttribute( - "src", - "data:text/javascript;charset=utf-8," + - encodeURIComponent( - a.textContent + - ("\n//# sourceURL=" + b + (d ? "-" + d : "") + ".js\n") - ) - ), - (a.textContent = ""), - d++); - } - ); - return a; - }; - h.prototype.m = function () { - var a = this; - if (!this.b) { - this.g.disconnect(); - this.flatten(document); - var b = !1, - c = !1, - d = function () { - c && - b && - (a.loadImports(document), - a.b || - (a.g.observe(document.head, { childList: !0, subtree: !0 }), - a.v())); - }; - this.C(function () { - c = !0; - d(); - }); - this.B(function () { - b = !0; - d(); - }); - } - }; - h.prototype.flatten = function (a) { - var b = this; - g(k(a, "link[rel=import]"), function (a) { - var c = b.a[a.href]; - (a.__import = c) && - c.nodeType === Node.DOCUMENT_FRAGMENT_NODE && - ((b.a[a.href] = a), - (a.readyState = "loading"), - (a.__import = a), - b.flatten(c), - a.appendChild(c)); - }); - }; - h.prototype.B = function (a) { - function b(f) { - if (f < d) { - var l = c[f], - e = document.createElement("script"); - l.removeAttribute("import-dependency"); - g(l.attributes, function (a) { - return e.setAttribute(a.name, a.value); - }); - w = e; - l.parentNode.replaceChild(e, l); - t(e, function () { - w = null; - b(f + 1); - }); - } else a(); - } - var c = k(document, "script[import-dependency]"), - d = c.length; - b(0); - }; - h.prototype.C = function (a) { - var b = k( - document, - "style[import-dependency],link[rel=stylesheet][import-dependency]" - ), - c = b.length; - if (c) { - var d = - v && - !!document.querySelector( - "link[rel=stylesheet][href][type=import-disable]" - ); - g(b, function (b) { - t(b, function () { - b.removeAttribute("import-dependency"); - 0 === --c && a(); - }); - if (d && b.parentNode !== document.head) { - var e = document.createElement(b.localName); - e.__appliedElement = b; - e.setAttribute("type", "import-placeholder"); - b.parentNode.insertBefore(e, b.nextSibling); - for (e = m(b); e && m(e); ) e = m(e); - e.parentNode !== document.head && (e = null); - document.head.insertBefore(b, e); - b.removeAttribute("type"); - } - }); - } else a(); - }; - h.prototype.v = function () { - var a = this; - g( - k(document, "link[rel=import]"), - function (b) { - return a.j(b); - }, - !0 - ); - }; - h.prototype.j = function (a) { - a.__loaded || - ((a.__loaded = !0), - a.import && (a.import.readyState = "complete"), - a.dispatchEvent( - y(a.import ? "load" : "error", { - bubbles: !1, - cancelable: !1, - detail: void 0, - }) - )); - }; - h.prototype.w = function (a) { - var b = this; - g(a, function (a) { - return g(a.addedNodes, function (a) { - a && - a.nodeType === Node.ELEMENT_NODE && - (r(a) ? b.l(a) : b.loadImports(a)); - }); - }); - }; - var x = null; - if (u) - g(k(document, "link[rel=import]"), function (a) { - (a.import && "loading" === a.import.readyState) || (a.__loaded = !0); - }), - (n = function (a) { - a = a.target; - r(a) && (a.__loaded = !0); - }), - document.addEventListener("load", n, !0), - document.addEventListener("error", n, !0); - else { - var p = Object.getOwnPropertyDescriptor(Node.prototype, "baseURI"); - Object.defineProperty( - (!p || p.configurable ? Node : Element).prototype, - "baseURI", - { - get: function () { - var a = r(this) ? this : m(this); - return a - ? a.href - : p && p.get - ? p.get.call(this) - : (document.querySelector("base") || window.location).href; - }, - configurable: !0, - enumerable: !0, - } - ); - Object.defineProperty(HTMLLinkElement.prototype, "import", { - get: function () { - return this.__import || null; - }, - configurable: !0, - enumerable: !0, - }); - z(function () { - x = new h(); - }); - } - A(function () { - return document.dispatchEvent( - y("HTMLImportsLoaded", { cancelable: !0, bubbles: !0, detail: void 0 }) - ); - }); - q.useNative = u; - q.whenReady = A; - q.importForElement = m; - q.loadImports = function (a) { - x && x.loadImports(a); - }; -})((window.HTMLImports = window.HTMLImports || {})); diff --git a/src/util/custom-panel/load-custom-panel.ts b/src/util/custom-panel/load-custom-panel.ts index c674e0f4ed..1286b6588f 100644 --- a/src/util/custom-panel/load-custom-panel.ts +++ b/src/util/custom-panel/load-custom-panel.ts @@ -47,17 +47,6 @@ export const loadCustomPanel = ( ): Promise => { const panelSource = getUrl(panelConfig); - if (panelSource.type === "html") { - const toLoad = [ - import( - /* webpackChunkName: "import-href-polyfill" */ "../../resources/html-import/import-href" - ), - ]; - - return Promise.all(toLoad).then(([{ importHrefPromise }]) => - importHrefPromise(panelSource.url) - ); - } if (panelSource.type === "js") { if (!(panelSource.url in JS_CACHE)) { JS_CACHE[panelSource.url] = loadJS(panelSource.url); From 4e676b1dba0854c5fc0303c735ca618af78a8c5c Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 8 Sep 2020 16:17:01 +0200 Subject: [PATCH 10/29] Fix light more info (#6855) --- src/components/ha-color-picker.js | 11 +++++++++++ src/dialogs/more-info/controls/more-info-light.ts | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/components/ha-color-picker.js b/src/components/ha-color-picker.js index 49fce6c7f5..a50601c0ea 100644 --- a/src/components/ha-color-picker.js +++ b/src/components/ha-color-picker.js @@ -176,6 +176,11 @@ class HaColorPicker extends EventsMixin(PolymerElement) { this.drawColorWheel(); this.drawMarker(); + if (this.desiredHsColor) { + this.setMarkerOnColor(this.desiredHsColor); + this.applyColorToCanvas(this.desiredHsColor); + } + this.interactionLayer.addEventListener("mousedown", (ev) => this.onMouseDown(ev) ); @@ -319,6 +324,9 @@ class HaColorPicker extends EventsMixin(PolymerElement) { // set marker position to the given color setMarkerOnColor(hs) { + if (!this.marker || !this.tooltip) { + return; + } const dist = hs.s * this.radius; const theta = ((hs.h - 180) / 180) * Math.PI; const markerdX = -dist * Math.cos(theta); @@ -330,6 +338,9 @@ class HaColorPicker extends EventsMixin(PolymerElement) { // apply given color to interface elements applyColorToCanvas(hs) { + if (!this.interactionLayer) { + return; + } // we're not really converting hs to hsl here, but we keep it cheap // setting the color on the interactionLayer, the svg elements can inherit this.interactionLayer.style.color = `hsl(${hs.h}, 100%, ${ diff --git a/src/dialogs/more-info/controls/more-info-light.ts b/src/dialogs/more-info/controls/more-info-light.ts index 6b0bba5572..772d0ea29d 100644 --- a/src/dialogs/more-info/controls/more-info-light.ts +++ b/src/dialogs/more-info/controls/more-info-light.ts @@ -134,7 +134,7 @@ class MoreInfoLight extends LitElement { attr-for-selected="item-name" >${this.stateObj.attributes.effect_list.map( (effect: string) => html` - ${effect} ` @@ -170,7 +170,7 @@ class MoreInfoLight extends LitElement { } private _effectChanged(ev: CustomEvent) { - const newVal = ev.detail.value; + const newVal = ev.detail.item.itemName; if (!newVal || this.stateObj!.attributes.effect === newVal) { return; From 909cff215836cf69cd10f2fd1dfff62d38150882 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 8 Sep 2020 17:01:04 +0200 Subject: [PATCH 11/29] Fix timer entity display (#6849) --- src/common/entity/timer_time_remaining.ts | 7 ++++++- src/dialogs/more-info/controls/more-info-timer.ts | 13 +++++-------- .../lovelace/entity-rows/hui-timer-entity-row.ts | 6 ++++-- src/state-summary/state-card-timer.js | 8 +++++--- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/common/entity/timer_time_remaining.ts b/src/common/entity/timer_time_remaining.ts index cd7c90ef8f..5b2f54654d 100644 --- a/src/common/entity/timer_time_remaining.ts +++ b/src/common/entity/timer_time_remaining.ts @@ -1,7 +1,12 @@ import { HassEntity } from "home-assistant-js-websocket"; import durationToSeconds from "../datetime/duration_to_seconds"; -export const timerTimeRemaining = (stateObj: HassEntity) => { +export const timerTimeRemaining = ( + stateObj: HassEntity +): undefined | number => { + if (!stateObj.attributes.remaining) { + return undefined; + } let timeRemaining = durationToSeconds(stateObj.attributes.remaining); if (stateObj.state === "active") { diff --git a/src/dialogs/more-info/controls/more-info-timer.ts b/src/dialogs/more-info/controls/more-info-timer.ts index 809d697c70..c06f549896 100644 --- a/src/dialogs/more-info/controls/more-info-timer.ts +++ b/src/dialogs/more-info/controls/more-info-timer.ts @@ -26,15 +26,12 @@ class MoreInfoTimer extends LitElement { return html`
${this.stateObj.state === "idle" || this.stateObj.state === "paused" ? html` - + ${this.hass!.localize("ui.card.timer.actions.start")} ` @@ -42,7 +39,7 @@ class MoreInfoTimer extends LitElement { ${this.stateObj.state === "active" ? html` ${this.hass!.localize("ui.card.timer.actions.pause")} @@ -52,13 +49,13 @@ class MoreInfoTimer extends LitElement { ${this.stateObj.state === "active" || this.stateObj.state === "paused" ? html` ${this.hass!.localize("ui.card.timer.actions.cancel")} ${this.hass!.localize("ui.card.timer.actions.finish")} 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 e744313f26..b77225c28d 100644 --- a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts @@ -2,9 +2,9 @@ import { HassEntity } from "home-assistant-js-websocket"; import { customElement, html, + internalProperty, LitElement, property, - internalProperty, PropertyValues, TemplateResult, } from "lit-element"; @@ -125,7 +125,9 @@ class HuiTimerEntityRow extends LitElement { } if (stateObj.state === "idle" || this._timeRemaining === 0) { - return this.hass!.localize("state.timer." + stateObj.state); + return ( + this.hass!.localize(`state.timer.${stateObj.state}`) || stateObj.state + ); } let display = secondsToDuration(this._timeRemaining || 0); diff --git a/src/state-summary/state-card-timer.js b/src/state-summary/state-card-timer.js index 96586e8804..17d39fde5c 100644 --- a/src/state-summary/state-card-timer.js +++ b/src/state-summary/state-card-timer.js @@ -23,7 +23,7 @@ class StateCardTimer extends PolymerElement {
${this.stateInfoTemplate} -
[[_secondsToDuration(timeRemaining)]]
+
[[_displayState(timeRemaining, stateObj)]]
`; } @@ -90,8 +90,10 @@ class StateCardTimer extends PolymerElement { this.timeRemaining = timerTimeRemaining(stateObj); } - _secondsToDuration(time) { - return secondsToDuration(time); + _displayState(time, stateObj) { + return time + ? secondsToDuration(time) + : this.hass.localize(`state.timer.${stateObj.state}`) || stateObj.state; } } customElements.define("state-card-timer", StateCardTimer); From 4d0d1ed2a1d8705abb9f9d936a996ca6e3d0ecef Mon Sep 17 00:00:00 2001 From: Zack Barett Date: Tue, 8 Sep 2020 13:52:21 -0500 Subject: [PATCH 12/29] Undo my commit into dev (#6864) --- src/dialogs/more-info/controls/more-info-light.ts | 6 +++--- src/dialogs/more-info/ha-more-info-tab-history.ts | 13 +------------ 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/dialogs/more-info/controls/more-info-light.ts b/src/dialogs/more-info/controls/more-info-light.ts index 605e3210f5..772d0ea29d 100644 --- a/src/dialogs/more-info/controls/more-info-light.ts +++ b/src/dialogs/more-info/controls/more-info-light.ts @@ -105,12 +105,12 @@ class MoreInfoLight extends LitElement { ? html`
`; diff --git a/src/dialogs/more-info/ha-more-info-tab-history.ts b/src/dialogs/more-info/ha-more-info-tab-history.ts index eeb00cef33..18624a11ef 100644 --- a/src/dialogs/more-info/ha-more-info-tab-history.ts +++ b/src/dialogs/more-info/ha-more-info-tab-history.ts @@ -85,18 +85,7 @@ export class MoreInfoTabHistoryDialog extends LitElement { clearInterval(this._historyRefreshInterval); } - if (!this.hass) { - return; - } - - const oldHass = changedProps.get("hass") as HomeAssistant; - const newStateObj = this.hass.states[this.entityId]; - const oldStateObj = oldHass?.states[this.entityId]; - - if ( - changedProps.has("entityId") || - (oldHass && newStateObj !== oldStateObj) - ) { + if (changedProps.has("entityId")) { this._stateHistory = undefined; this._entries = undefined; From 869b7c85cafddefa81da4ba47702de1dd4a25bc9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 8 Sep 2020 13:56:45 -0500 Subject: [PATCH 13/29] Ensure we pickup all the reloadable domains (#6861) --- src/common/config/components_with_service.ts | 9 ++++ .../ha-config-server-control.ts | 50 ++++++++----------- 2 files changed, 31 insertions(+), 28 deletions(-) create mode 100644 src/common/config/components_with_service.ts diff --git a/src/common/config/components_with_service.ts b/src/common/config/components_with_service.ts new file mode 100644 index 0000000000..9775b8c6f6 --- /dev/null +++ b/src/common/config/components_with_service.ts @@ -0,0 +1,9 @@ +import { HomeAssistant } from "../../types"; + +/** Return an array of domains with the service. */ +export const componentsWithService = ( + hass: HomeAssistant, + service: string +): Array => + hass && + Object.keys(hass.services).filter((key) => service in hass.services[key]); diff --git a/src/panels/config/server_control/ha-config-server-control.ts b/src/panels/config/server_control/ha-config-server-control.ts index 04fbc5b237..62622baeab 100644 --- a/src/panels/config/server_control/ha-config-server-control.ts +++ b/src/panels/config/server_control/ha-config-server-control.ts @@ -12,7 +12,7 @@ import { property, TemplateResult, } from "lit-element"; -import { isServiceLoaded } from "../../../common/config/is_service_loaded"; +import { componentsWithService } from "../../../common/config/components_with_service"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/ha-card"; import { checkCoreConfig } from "../../../data/core"; @@ -23,8 +23,6 @@ import { HomeAssistant, Route } from "../../../types"; import "../ha-config-section"; import { configSections } from "../ha-panel-config"; -const platformsWithReload = ["template"]; - @customElement("ha-config-server-control") export class HaConfigServerControl extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -51,13 +49,10 @@ export class HaConfigServerControl extends LitElement { changedProperties.has("hass") && (!oldHass || oldHass.config.components !== this.hass.config.components) ) { - this._reloadableDomains = this.hass.config.components - .concat(platformsWithReload) - .filter( - (component) => - !component.includes(".") && - isServiceLoaded(this.hass, component, "reload") - ); + this._reloadableDomains = componentsWithService( + this.hass, + "reload" + ).sort(); } } @@ -207,24 +202,23 @@ export class HaConfigServerControl extends LitElement { )}
- ${this._reloadableDomains.map((domain) => - isServiceLoaded(this.hass, domain, "reload") - ? html`
- ${this.hass.localize( - `ui.panel.config.server_control.section.reloading.${domain}` - ) || - this.hass.localize( - "ui.panel.config.server_control.section.reloading.reload", - "domain", - domainToName(this.hass.localize, domain) - )} - -
` - : "" + ${this._reloadableDomains.map( + (domain) => + html`
+ ${this.hass.localize( + `ui.panel.config.server_control.section.reloading.${domain}` + ) || + this.hass.localize( + "ui.panel.config.server_control.section.reloading.reload", + "domain", + domainToName(this.hass.localize, domain) + )} + +
` )} ` From b30ee884a72fe39f87e75fbe80aceeba7714c2ac Mon Sep 17 00:00:00 2001 From: Zack Barett Date: Tue, 8 Sep 2020 13:57:17 -0500 Subject: [PATCH 14/29] Fix for Camera streams that don't support stream (#6863) --- src/components/ha-camera-stream.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ha-camera-stream.ts b/src/components/ha-camera-stream.ts index a8d34c8a18..51794b3ad3 100644 --- a/src/components/ha-camera-stream.ts +++ b/src/components/ha-camera-stream.ts @@ -66,7 +66,7 @@ class HaCameraStream extends LitElement { } protected updated(changedProps: PropertyValues): void { - if (changedProps.has("stateObj")) { + if (changedProps.has("stateObj") && !this._shouldRenderMJPEG) { this._forceMJPEG = undefined; this._getStreamUrl(); } From 0e021e7d7def0c84f557f1dfec4562bbaf9d4d7d Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 8 Sep 2020 20:58:47 +0200 Subject: [PATCH 15/29] Bumped version to 20200908.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b1a1ef7a73..8bec01eb50 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="home-assistant-frontend", - version="20200907.0", + version="20200908.0", description="The Home Assistant frontend", url="https://github.com/home-assistant/home-assistant-polymer", author="The Home Assistant Authors", From 7c5a78a1cf692eeac3757ddbae2080ae10bf7401 Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Tue, 8 Sep 2020 23:36:44 +0200 Subject: [PATCH 16/29] Media player visual improvements (#6817) Co-authored-by: Bram Kragten --- .../media-player/ha-media-player-browse.ts | 12 +++++++++++- src/panels/media-browser/ha-panel-media-browser.ts | 14 ++++++-------- .../hui-dialog-select-media-player.ts | 2 -- .../hui-dialog-web-browser-play-media.ts | 2 -- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/components/media-player/ha-media-player-browse.ts b/src/components/media-player/ha-media-player-browse.ts index 0d9cde1946..ad80b0d524 100644 --- a/src/components/media-player/ha-media-player-browse.ts +++ b/src/components/media-player/ha-media-player-browse.ts @@ -335,6 +335,7 @@ export class HaMediaPlayerBrowse extends LitElement { .item=${child} graphic="avatar" hasMeta + dir=${computeRTLDirection(this.hass)} >
- ${child.title} + ${child.title}
  • ` @@ -620,6 +621,7 @@ export class HaMediaPlayerBrowse extends LitElement { mwc-list { --mdc-list-vertical-padding: 0; + --mdc-list-item-graphic-margin: 0; --mdc-theme-text-icon-on-background: var(--secondary-text-color); margin-top: 10px; } @@ -728,6 +730,14 @@ export class HaMediaPlayerBrowse extends LitElement { background-color: transparent; } + mwc-list-item .title { + margin-left: 16px; + } + mwc-list-item[dir="rtl"] .title { + margin-right: 16px; + margin-left: 0; + } + /* ============= Narrow ============= */ :host([narrow]) { diff --git a/src/panels/media-browser/ha-panel-media-browser.ts b/src/panels/media-browser/ha-panel-media-browser.ts index 33cd43dd0c..a58243857e 100644 --- a/src/panels/media-browser/ha-panel-media-browser.ts +++ b/src/panels/media-browser/ha-panel-media-browser.ts @@ -64,14 +64,12 @@ class PanelMediaBrowser extends LitElement { "ui.components.media-browser.media-player-browser" )}
    - - - + + + ${this.hass.localize( + "ui.components.media-browser.choose_player" + )} +
    diff --git a/src/panels/media-browser/hui-dialog-select-media-player.ts b/src/panels/media-browser/hui-dialog-select-media-player.ts index 0c45026e81..d19cebe0ee 100644 --- a/src/panels/media-browser/hui-dialog-select-media-player.ts +++ b/src/panels/media-browser/hui-dialog-select-media-player.ts @@ -40,8 +40,6 @@ export class HuiDialogSelectMediaPlayer extends LitElement { return html` Date: Wed, 9 Sep 2020 00:32:22 +0000 Subject: [PATCH 17/29] [ci skip] Translation update --- translations/frontend/ca.json | 23 +++++++++- translations/frontend/cs.json | 23 +++++++++- translations/frontend/es.json | 23 +++++++++- translations/frontend/fr.json | 16 ++++++- translations/frontend/it.json | 68 +++++++++++++++++++++++++++--- translations/frontend/nb.json | 23 +++++++++- translations/frontend/nl.json | 34 ++++++++++++++- translations/frontend/ru.json | 36 +++++++++++++--- translations/frontend/zh-Hans.json | 28 ++++++++++-- 9 files changed, 248 insertions(+), 26 deletions(-) diff --git a/translations/frontend/ca.json b/translations/frontend/ca.json index 9e2888ab08..61e6b7e55d 100644 --- a/translations/frontend/ca.json +++ b/translations/frontend/ca.json @@ -553,6 +553,10 @@ "toggle": "Commuta" }, "entity": { + "entity-attribute-picker": { + "attribute": "Atribut", + "show_attributes": "Mostra els atributs" + }, "entity-picker": { "clear": "Esborra", "entity": "Entitat", @@ -929,7 +933,13 @@ "label": "Crida servei", "service_data": "Dades de servei" }, + "wait_for_trigger": { + "continue_timeout": "Continua amb temps d'espera", + "label": "Espera disparador", + "timeout": "Temps màxim d'espera (opcional)" + }, "wait_template": { + "continue_timeout": "Continua amb temps d'espera", "label": "Espera", "timeout": "Temps màxim d'espera (opcional)", "wait_template": "Plantilla d'espera" @@ -993,7 +1003,9 @@ "time": { "after": "Després", "before": "Abans", - "label": "Temporal" + "label": "Temporal", + "type_input": "Valor d'un ajudant de data/hora", + "type_value": "Temps fix" }, "zone": { "entity": "Entitat amb ubicació", @@ -1081,6 +1093,7 @@ "value_template": "Plantilla de valor (opcional)" }, "state": { + "attribute": "Atribut (opcional)", "for": "Durant", "from": "Des de", "label": "Estat", @@ -1108,7 +1121,9 @@ }, "time": { "at": "A les", - "label": "Temporal" + "label": "Temporal", + "type_input": "Valor d'un ajudant de data/hora", + "type_value": "Temps fix" }, "webhook": { "label": "Webhook", @@ -1131,6 +1146,8 @@ "add_automation": "Afegeix automatització", "delete_automation": "Elimina l'automatització", "delete_confirm": "Estàs segur que vols eliminar aquesta automatització?", + "duplicate": "Duplica", + "duplicate_automation": "Duplica l'automatització", "edit_automation": "Edita automatització", "header": "Editor d'automatitzacions", "headers": { @@ -1531,6 +1548,7 @@ }, "integrations": { "add_integration": "Afegeix integració", + "attention": "Cal atenció", "caption": "Integracions", "config_entry": { "area": "A {area}", @@ -1601,6 +1619,7 @@ "none_found_detail": "Ajusta els paràmetres de cerca.", "note_about_integrations": "Encara no es poden configurar totes les integracions a través de la UI.", "note_about_website_reference": "N'hi ha més disponibles al ", + "reconfigure": "Reconfigura", "rename_dialog": "Edita el nom de l'entrada de configuració", "rename_input_label": "Nom de l'entrada", "search": "Cerca integracions" diff --git a/translations/frontend/cs.json b/translations/frontend/cs.json index e8048e50a0..2c11c2fd88 100644 --- a/translations/frontend/cs.json +++ b/translations/frontend/cs.json @@ -553,6 +553,10 @@ "toggle": "Přepnout" }, "entity": { + "entity-attribute-picker": { + "attribute": "Atribut", + "show_attributes": "Zobrazit atributy" + }, "entity-picker": { "clear": "Zrušit", "entity": "Entita", @@ -929,7 +933,13 @@ "label": "Zavolat službu", "service_data": "Data služby" }, + "wait_for_trigger": { + "continue_timeout": "Pokračovat po časovém limitu", + "label": "Počkat na spouštěč", + "timeout": "Časový limit (volitelný)" + }, "wait_template": { + "continue_timeout": "Pokračovat po časovém limitu", "label": "Čekání", "timeout": "Časový limit (volitelné)", "wait_template": "Šablona pro čekání" @@ -993,7 +1003,9 @@ "time": { "after": "Po", "before": "Před", - "label": "Čas" + "label": "Čas", + "type_input": "Hodnota pomocníka \"Datum a/nebo čas\"", + "type_value": "Pevný čas" }, "zone": { "entity": "Entita s umístěním", @@ -1081,6 +1093,7 @@ "value_template": "Šablona hodnoty (volitelné)" }, "state": { + "attribute": "Atribut (volitelný)", "for": "Po dobu", "from": "Z", "label": "Stav", @@ -1108,7 +1121,9 @@ }, "time": { "at": "V", - "label": "Čas" + "label": "Čas", + "type_input": "Hodnota pomocníka \"Datum a/nebo čas\"", + "type_value": "Pevný čas" }, "webhook": { "label": "Webhook", @@ -1131,6 +1146,8 @@ "add_automation": "Přidat automatizaci", "delete_automation": "Odstranit automatizaci", "delete_confirm": "Opravdu chcete odstranit tuto automatizaci?", + "duplicate": "Duplikovat", + "duplicate_automation": "Duplikovat automatizaci", "edit_automation": "Upravit automatizaci", "header": "Editor automatizací", "headers": { @@ -1531,6 +1548,7 @@ }, "integrations": { "add_integration": "Přidat integraci", + "attention": "Vyžadována pozornost", "caption": "Integrace", "config_entry": { "area": "V {area}", @@ -1601,6 +1619,7 @@ "none_found_detail": "Upravte kritéria vyhledávání.", "note_about_integrations": "Ne všechny integrace lze prozatím konfigurovat prostřednictvím uživatelského rozhraní.", "note_about_website_reference": "Další jsou k dispozici na ", + "reconfigure": "Překonfigurovat", "rename_dialog": "Upravit název této položky nastavení", "rename_input_label": "Název položky", "search": "Hledat integraci" diff --git a/translations/frontend/es.json b/translations/frontend/es.json index 9b22dc0cde..93eaa86477 100644 --- a/translations/frontend/es.json +++ b/translations/frontend/es.json @@ -553,6 +553,10 @@ "toggle": "Interruptor" }, "entity": { + "entity-attribute-picker": { + "attribute": "Atributo", + "show_attributes": "Mostrar atributos" + }, "entity-picker": { "clear": "Limpiar", "entity": "Entidad", @@ -929,7 +933,13 @@ "label": "Llamar servicio", "service_data": "Datos de servicio" }, + "wait_for_trigger": { + "continue_timeout": "Continuar tras el límite de tiempo", + "label": "Esperar al disparador", + "timeout": "Límite de tiempo (opcional)" + }, "wait_template": { + "continue_timeout": "Continuar tras el límite de tiempo", "label": "Esperar", "timeout": "Límite de tiempo (opcional)", "wait_template": "Plantilla de espera" @@ -993,7 +1003,9 @@ "time": { "after": "Después de", "before": "Antes de", - "label": "Hora" + "label": "Hora", + "type_input": "Valor de un ayudante de fecha/hora", + "type_value": "Horario fijo" }, "zone": { "entity": "Entidad con la ubicación", @@ -1081,6 +1093,7 @@ "value_template": "Valor de la plantilla (opcional)" }, "state": { + "attribute": "Atributo (Opcional)", "for": "Durante", "from": "De", "label": "Estado", @@ -1108,7 +1121,9 @@ }, "time": { "at": "A las", - "label": "Hora" + "label": "Hora", + "type_input": "Valor de un ayudante de fecha/hora", + "type_value": "Horario fijo" }, "webhook": { "label": "Webhook", @@ -1131,6 +1146,8 @@ "add_automation": "Añadir automatización", "delete_automation": "Eliminar la automatización", "delete_confirm": "¿Estás seguro de que quieres eliminar esta automatización?", + "duplicate": "Duplicar", + "duplicate_automation": "Duplicar la automatización", "edit_automation": "Editar automatización", "header": "Editor de automatización", "headers": { @@ -1531,6 +1548,7 @@ }, "integrations": { "add_integration": "Añadir integración", + "attention": "Atención requerida", "caption": "Integraciones", "config_entry": { "area": "En {area}", @@ -1601,6 +1619,7 @@ "none_found_detail": "Ajusta tus criterios de búsqueda.", "note_about_integrations": "Todavía no se pueden configurar todas las integraciones a través de la interfaz de usuario.", "note_about_website_reference": "Hay más disponibles en el ", + "reconfigure": "Reconfigurar", "rename_dialog": "Edita el nombre de esta entrada de configuración", "rename_input_label": "Nombre de la entrada", "search": "Buscar integraciones" diff --git a/translations/frontend/fr.json b/translations/frontend/fr.json index 8af22d4ab6..714fc4320a 100644 --- a/translations/frontend/fr.json +++ b/translations/frontend/fr.json @@ -553,6 +553,10 @@ "toggle": "Permuter" }, "entity": { + "entity-attribute-picker": { + "attribute": "Attribut", + "show_attributes": "Afficher les attributs" + }, "entity-picker": { "clear": "Effacer", "entity": "Entité", @@ -929,6 +933,9 @@ "label": "Appeler un service", "service_data": "Données du service" }, + "wait_for_trigger": { + "label": "Attendre le déclencheur" + }, "wait_template": { "label": "Attendre", "timeout": "Délai d'expiration (optionnel)", @@ -1081,6 +1088,7 @@ "value_template": "Contenu du template (optionnel)" }, "state": { + "attribute": "Attribut (facultatif)", "for": "Pendant", "from": "De", "label": "État", @@ -1108,7 +1116,9 @@ }, "time": { "at": "À", - "label": "Heure" + "label": "Heure", + "type_input": "Valeur d'une aide de date/heure", + "type_value": "Temps fixe" }, "webhook": { "label": "Webhook", @@ -1131,6 +1141,8 @@ "add_automation": "Ajouter une automatisation", "delete_automation": "Supprimer l'automatisation", "delete_confirm": "Voulez-vous vraiment supprimer cette automatisation ?", + "duplicate": "Dupliquer", + "duplicate_automation": "Dupliquer l'automatisation", "edit_automation": "Modifier l'automatisation", "header": "Éditeur d'automatisation", "headers": { @@ -1531,6 +1543,7 @@ }, "integrations": { "add_integration": "Ajouter l'intégration", + "attention": "Attention requise", "caption": "Intégrations", "config_entry": { "area": "Dans {area}", @@ -1600,6 +1613,7 @@ "none_found_detail": "Ajustez vos critères de recherche.", "note_about_integrations": "Toutes les intégrations ne peuvent pas encore être configurées via l'interface utilisateur.", "note_about_website_reference": "D'autres sont disponibles sur le ", + "reconfigure": "Reconfigurer", "rename_dialog": "Modifier le nom de cette entrée de configuration", "rename_input_label": "Nom de l'entrée", "search": "Chercher les intégrations" diff --git a/translations/frontend/it.json b/translations/frontend/it.json index 13c8d8aeaf..fa2f1fb908 100644 --- a/translations/frontend/it.json +++ b/translations/frontend/it.json @@ -19,6 +19,7 @@ "logbook": "Registro", "mailbox": "Posta", "map": "Mappa", + "media_browser": "Browser multimediale", "profile": "Profilo", "shopping_list": "Lista della spesa", "states": "Panoramica" @@ -505,6 +506,7 @@ "back": "Indietro", "cancel": "Annulla", "close": "Chiudi", + "continue": "Continua", "delete": "Elimina", "error_required": "Necessario", "loading": "Caricamento", @@ -551,6 +553,10 @@ "toggle": "Azionare" }, "entity": { + "entity-attribute-picker": { + "attribute": "Attributo", + "show_attributes": "Mostra attributi" + }, "entity-picker": { "clear": "Cancella", "entity": "Entità", @@ -562,6 +568,8 @@ "no_history_found": "Nessuno storico trovato." }, "media-browser": { + "audio_not_supported": "Il tuo browser non supporta l'elemento audio.", + "choose_player": "Scegli il lettore", "choose-source": "Scegli origine", "content-type": { "album": "Album", @@ -570,12 +578,17 @@ "playlist": "Elenco di riproduzione", "server": "Server" }, + "media_browsing_error": "Errore di navigazione multimediale", + "media_not_supported": "Il Browser Media Player non supporta questo tipo di file multimediali", + "media_player": "Lettore multimediale", "media-player-browser": "Lettore multimediale", "no_items": "Nessun elemento", "pick": "Scegli", "pick-media": "Seleziona file multimediali", "play": "Riproduci", - "play-media": "Riproduci file multimediali" + "play-media": "Riproduci file multimediali", + "video_not_supported": "Il tuo browser non supporta l'elemento video.", + "web-browser": "Web Browser" }, "picture-upload": { "label": "Immagine", @@ -689,8 +702,10 @@ "crop": "Ritaglia" }, "more_info_control": { + "controls": "Controlli", "dismiss": "Chiudi finestra di dialogo", "edit": "Modifica entità", + "history": "Storico", "person": { "create_zone": "Crea zona dalla posizione corrente" }, @@ -918,7 +933,13 @@ "label": "Chiama servizio", "service_data": "Dati del servizio" }, + "wait_for_trigger": { + "continue_timeout": "Continua al timeout", + "label": "In attesa dell'attivazione", + "timeout": "Timeout (opzionale)" + }, "wait_template": { + "continue_timeout": "Continua al timeout", "label": "Attendere", "timeout": "Timeout (opzionale)", "wait_template": "Modello di attesa" @@ -982,7 +1003,9 @@ "time": { "after": "Dopo", "before": "Prima", - "label": "Tempo" + "label": "Tempo", + "type_input": "Valore di un aiutante data/ora", + "type_value": "Tempo fisso" }, "zone": { "entity": "Entità con posizione", @@ -1070,6 +1093,7 @@ "value_template": "Valore modello (opzionale)" }, "state": { + "attribute": "Attributo (opzionale)", "for": "Per", "from": "Da", "label": "Stato", @@ -1096,8 +1120,10 @@ "seconds": "Secondi" }, "time": { - "at": "Alle", - "label": "Ora" + "at": "Al tempo", + "label": "Ora", + "type_input": "Valore di un aiutante data/ora", + "type_value": "Tempo fisso" }, "webhook": { "label": "Webhook", @@ -1120,6 +1146,8 @@ "add_automation": "Aggiungi Automazione", "delete_automation": "Cancellare l'automazione", "delete_confirm": "Sei sicuro di voler eliminare questa automazione?", + "duplicate": "Duplica", + "duplicate_automation": "Duplica automazione", "edit_automation": "Modifica automazione", "header": "Editor di Automazione", "headers": { @@ -1520,6 +1548,7 @@ }, "integrations": { "add_integration": "Aggiungi integrazione", + "attention": "Attenzione richiesta", "caption": "Integrazioni", "config_entry": { "area": "In {area}", @@ -1543,6 +1572,7 @@ "reload_restart_confirm": "Riavvia Home Assistant per completare il ricaricamento di questa integrazione", "rename": "Rinomina", "restart_confirm": "Riavvia Home Assistant per completare la rimozione di questa integrazione", + "services": "{count} {count, plural,\n one {service}\n other {services}\n}", "settings_button": "Modificare le impostazioni per {integration}.", "system_options": "Opzioni di sistema", "system_options_button": "Opzioni di sistema per {integration}", @@ -1589,6 +1619,7 @@ "none_found_detail": "Modifica i criteri di ricerca.", "note_about_integrations": "Non tutte le integrazioni possono ancora essere configurate tramite l'interfaccia utente.", "note_about_website_reference": "Ulteriori informazioni sono disponibili su ", + "reconfigure": "Riconfigurare", "rename_dialog": "Modifica il nome di questa voce di configurazione", "rename_input_label": "Nome della voce", "search": "Cerca integrazioni" @@ -1762,8 +1793,21 @@ "versions": "Recupero di informazioni sulle versioni del firmware e della classe di comando", "wakeup": "Configurazione del supporto per code di riattivazione e messaggi " }, + "node": { + "button": "Dettagli del nodo", + "not_found": "Nodo non trovato" + }, + "nodes_table": { + "failed": "Fallito", + "id": "ID", + "manufacturer": "Produttore", + "model": "Modello", + "query_stage": "Fase di richiesta", + "zwave_plus": "Z-Wave Plus" + }, "refresh_node": { "battery_note": "Se il nodo è alimentato a batteria, assicurarsi di riattivarlo prima di procedere", + "button": "Aggiorna nodo", "complete": "Aggiornamento del nodo completato", "description": "In questo modo si dirà a OpenZWave di re-interrogare un nodo e aggiornare le classi di comando, le funzionalità e i valori del nodo.", "node_status": "Stato del nodo", @@ -1912,7 +1956,7 @@ "filter": "Ricaricare le entità filtro", "generic": "Ricaricare le entità delle generiche telecamere IP", "generic_thermostat": "Ricaricare le entità termostati generiche", - "group": "Ricarica i Gruppi", + "group": "Ricarica gruppi, entità di gruppo e servizi di notifica", "heading": "Ricarica Configurazione YAML", "history_stats": "Ricarica le entità delle statistiche della cronologia", "homekit": "Ricarica HomeKit", @@ -1923,12 +1967,17 @@ "input_text": "Ricarica input testuali", "introduction": "Alcune parti di Home Assistant possono essere ricaricate senza richiedere un riavvio. Premendo su Ricarica si rimuoverà la loro Configurazione YAML attuale e si caricherà la versione aggiornata.", "min_max": "Ricaricare le entità min/max", + "mqtt": "Ricarica le entità mqtt", "person": "Ricarica le persone", "ping": "Ricarica le entità del sensore binario ping", - "rest": "Ricarica le entità della piattaforma rest", + "reload": "Ricarica {domain}", + "rest": "Ricarica le entità di rest e i servizi di notifica", + "rpi_gpio": "Ricarica le entità GPIO di Raspberry Pi ", "scene": "Ricarica le Scene", "script": "Ricarica gli Script", + "smtp": "Ricarica i servizi di notifica smtp", "statistics": "Ricaricare le entità statistiche", + "telegram": "Ricarica i servizi di notifica telegram", "template": "Ricaricare le entità modello", "trend": "Ricaricare le entità di tendenza", "universal": "Ricarica le entità del lettore multimediale universale", @@ -2017,7 +2066,7 @@ "system": "Sistema" } }, - "users_privileges_note": "Il gruppo di utenti è in fase di elaborazione. L'utente non sarà in grado di amministrare l'istanza tramite l'interfaccia utente. Stiamo ancora verificando tutti gli endpoint dell'API di gestione per garantire che limitino correttamente l'accesso agli amministratori." + "users_privileges_note": "La funzionalità del gruppo di utenti è in fase di elaborazione. L'utente non sarà in grado di amministrare l'istanza tramite l'Interfaccia Utente. Stiamo ancora verificando tutti gli endpoint dell'API di gestione per garantire che limitino correttamente l'accesso solo agli amministratori." }, "zha": { "add_device_page": { @@ -2549,7 +2598,11 @@ } }, "cardpicker": { + "by_card": "Per Scheda", + "by_entity": "Per Entità", "custom_card": "Personalizzato", + "domain": "Dominio", + "entity": "Entità", "no_description": "Nessuna descrizione disponibile." }, "edit_card": { @@ -2563,6 +2616,7 @@ "options": "Altre opzioni", "pick_card": "Quale scheda vorresti aggiungere?", "pick_card_view_title": "Quale scheda vorresti aggiungere alla tua vista {name}?", + "search_cards": "Schede di ricerca", "show_code_editor": "Mostra Editor di Codice", "show_visual_editor": "Mostra Editor Visivo", "toggle_editor": "Attiva / disattiva l'editor", diff --git a/translations/frontend/nb.json b/translations/frontend/nb.json index 523a9a2718..f650fd7020 100644 --- a/translations/frontend/nb.json +++ b/translations/frontend/nb.json @@ -553,6 +553,10 @@ "toggle": "Veksle" }, "entity": { + "entity-attribute-picker": { + "attribute": "Attributt", + "show_attributes": "Vis attributter" + }, "entity-picker": { "clear": "Tøm", "entity": "Entitet", @@ -929,7 +933,13 @@ "label": "Tilkall tjeneste", "service_data": "Tjenestedata" }, + "wait_for_trigger": { + "continue_timeout": "Fortsett ved tidsavbrudd", + "label": "Vent på utløser", + "timeout": "Tidsavbrudd" + }, "wait_template": { + "continue_timeout": "Fortsett ved tidsavbrudd", "label": "Vent", "timeout": "Tidsavbrudd (valgfritt)", "wait_template": "Ventemal" @@ -993,7 +1003,9 @@ "time": { "after": "Etter", "before": "Før", - "label": "Tid" + "label": "Tid", + "type_input": "Verdien til en tid/dato hjelper", + "type_value": "Bestemt tid" }, "zone": { "entity": "Entitet med posisjon", @@ -1081,6 +1093,7 @@ "value_template": "Verdi fra mal (valgfritt)" }, "state": { + "attribute": "Attributt (valgfritt)", "for": "", "from": "Fra", "label": "Tilstand", @@ -1108,7 +1121,9 @@ }, "time": { "at": "Klokken", - "label": "Tid" + "label": "Tid", + "type_input": "Verdien til en tid/dato hjelper", + "type_value": "Bestemt tid" }, "webhook": { "label": "", @@ -1131,6 +1146,8 @@ "add_automation": "Legg til automasjon", "delete_automation": "Slett automasjon", "delete_confirm": "Er du sikker på at du vil slette denne automasjonen?", + "duplicate": "Dupliser", + "duplicate_automation": "Dupliser automasjon", "edit_automation": "Rediger automasjon", "header": "Automasjonsredigering", "headers": { @@ -1531,6 +1548,7 @@ }, "integrations": { "add_integration": "Legg til integrasjon", + "attention": "Oppmerksomhet kreves", "caption": "Integrasjoner", "config_entry": { "area": "I {area}", @@ -1601,6 +1619,7 @@ "none_found_detail": "Juster dine søkekriterier", "note_about_integrations": "Ikke alle integrasjoner kan konfigureres via brukergrensesnittet ennå.", "note_about_website_reference": "Flere er tilgjengelige på", + "reconfigure": "Konfigurer på nytt", "rename_dialog": "Redigere navnet på denne config-oppføringen", "rename_input_label": "Navn på oppføring", "search": "Søk i integrasjoner" diff --git a/translations/frontend/nl.json b/translations/frontend/nl.json index 8e5aaece5d..20dec55c5e 100644 --- a/translations/frontend/nl.json +++ b/translations/frontend/nl.json @@ -505,6 +505,7 @@ "back": "Terug", "cancel": "Annuleren", "close": "Sluiten", + "continue": "Ga verder", "delete": "Verwijderen", "error_required": "Verplicht", "loading": "Bezig met laden", @@ -562,6 +563,7 @@ "no_history_found": "Geen geschiedenis gevonden" }, "media-browser": { + "choose_player": "Kies speler", "choose-source": "Kies bron", "content-type": { "album": "Album", @@ -570,12 +572,16 @@ "playlist": "Afspeellijst", "server": "Server" }, + "media_not_supported": "De Browser Media Player ondersteunt dit type media niet", + "media_player": "Mediaspeler", "media-player-browser": "Mediaspeler-browser", "no_items": "Niets gevonden", "pick": "Kies", "pick-media": "Kies Media", "play": "Speel", - "play-media": "Media afspelen" + "play-media": "Media afspelen", + "video_not_supported": "Uw browser ondersteunt het video-element niet.", + "web-browser": "Webbrowser" }, "picture-upload": { "label": "Afbeelding", @@ -617,6 +623,7 @@ "update": "Bijwerken" }, "domain_toggler": { + "reset_entities": "Entiteiten opnieuw instellen", "title": "Domeinen in- en uitschakelen" }, "entity_registry": { @@ -688,8 +695,10 @@ "crop": "Snijd bij" }, "more_info_control": { + "controls": "Besturing", "dismiss": "Dialoogvenster sluiten", "edit": "Entiteit bewerken", + "history": "Geschiedenis", "person": { "create_zone": "Creëer zone van huidige locatie" }, @@ -917,7 +926,11 @@ "label": "Service aanroepen", "service_data": "Service data" }, + "wait_for_trigger": { + "label": "Wacht op trigger" + }, "wait_template": { + "continue_timeout": "Ga verder op time-out", "label": "Wacht", "timeout": "Timeout (optioneel)", "wait_template": "Wachtsjabloon" @@ -1200,8 +1213,12 @@ }, "alexa": { "banner": "Het bewerken van de entiteiten die via deze gebruikersinterface worden weergegeven is uitgeschakeld, omdat je entiteitenfilters hebt geconfigureerd in configuration.yaml.", + "dont_expose_entity": "Entiteit niet beschikbaar maken", "expose": "Blootstellen aan Alexa", + "expose_entity": "Enititeit beschikbaar maken", "exposed_entities": "Blootgestelde entiteiten", + "follow_domain": "Domein volgen", + "manage_domains": "Beheer domeinen", "not_exposed_entities": "Niet blootgestelde entiteiten", "title": "Alexa" }, @@ -1239,8 +1256,11 @@ "google": { "banner": "Het bewerken van de entiteiten die via deze gebruikersinterface worden weergegeven is uitgeschakeld, omdat je entiteitenfilters hebt geconfigureerd in configuration.yaml.", "disable_2FA": "Schakel tweestapsverificatie uit", + "dont_expose_entity": "Entiteit niet beschikbaar maken", "expose": "Blootstellen aan Google Assistant", + "expose_entity": "Enititeit beschikbaar maken", "exposed_entities": "Blootgestelde entiteiten", + "manage_domains": "Beheer domeinen", "not_exposed_entities": "Niet blootgestelde entiteiten", "sync_to_google": "Wijzigingen synchroniseren met Google.", "title": "Google Assistant" @@ -1507,6 +1527,7 @@ }, "integrations": { "add_integration": "Integratie toevoegen", + "attention": "Aandacht vereist", "caption": "Integraties", "config_entry": { "area": "In {area}", @@ -1576,6 +1597,7 @@ "none_found_detail": "Pas uw zoekcriteria aan.", "note_about_integrations": "Nog niet alle integraties kunnen via de UI worden geconfigureerd.", "note_about_website_reference": "Meer zijn beschikbaar op de ", + "reconfigure": "Herconfigureer", "rename_dialog": "Bewerk de naam van dit configuratie item", "rename_input_label": "Invoernaam", "search": "Zoek integraties" @@ -1749,6 +1771,9 @@ "versions": "Het verkrijgen van informatie over firmware en commandoklasseversies", "wakeup": "Ondersteuning instellen voor waakwachtrijen en berichten" }, + "nodes_table": { + "failed": "Mislukt" + }, "refresh_node": { "battery_note": "Als het knooppunt op batterijen werkt, moet u het uit de sluimerstand halen voordat u verder gaat", "complete": "Knooppunt vernieuwen voltooid", @@ -1910,12 +1935,16 @@ "input_text": "Herlaad input texts", "introduction": "Sommige delen van Home Assistant kunnen opnieuw worden geladen zonder dat een herstart vereist is. Als je herladen gebruikt, wordt de huidige configuratie leeggemaakt en wordt de nieuwe geladen.", "min_max": "Herlaad min/max entiteiten", + "mqtt": "Herlaad mqtt entiteiten", "person": "Herlaad personen", "ping": "Herlaad ping binaire sensor entiteiten", "rest": "Herlaad rust-entiteiten", + "rpi_gpio": "Herlaad Raspberry Pi GPIO-entiteiten", "scene": "Herlaad scenes", "script": "Herlaad scripts", + "smtp": "Herlaad telegram notify services", "statistics": "Herlaad statistische entiteiten", + "telegram": "Herlaad telegram notify services", "template": "Herlaad sjabloon-entiteiten", "trend": "Herlaad trend-entiteiten", "universal": "Herlaad universele mediaspeler entiteiten", @@ -2537,6 +2566,8 @@ }, "cardpicker": { "custom_card": "Aangepaste", + "domain": "Domein", + "entity": "Entiteit", "no_description": "Er is geen beschrijving beschikbaar" }, "edit_card": { @@ -2550,6 +2581,7 @@ "options": "Meer opties", "pick_card": "Welke kaart wil je toevoegen?", "pick_card_view_title": "Welke kaart wil je toevoegen aan je {name} weergave?", + "search_cards": "Zoek kaarten", "show_code_editor": "Code-editor weergeven", "show_visual_editor": "Visual Editor weergeven", "toggle_editor": "Toggle Editor", diff --git a/translations/frontend/ru.json b/translations/frontend/ru.json index 8bc907ffb4..0ff93c88b1 100644 --- a/translations/frontend/ru.json +++ b/translations/frontend/ru.json @@ -19,6 +19,7 @@ "logbook": "Журнал событий", "mailbox": "Почта", "map": "Карта", + "media_browser": "Браузер мультимедиа", "profile": "Профиль", "shopping_list": "Список покупок", "states": "Обзор" @@ -552,6 +553,10 @@ "toggle": "Переключить" }, "entity": { + "entity-attribute-picker": { + "attribute": "Атрибут", + "show_attributes": "Показать атрибуты" + }, "entity-picker": { "clear": "Очистить", "entity": "Объект", @@ -563,6 +568,7 @@ "no_history_found": "История не найдена." }, "media-browser": { + "audio_not_supported": "Ваш браузер не поддерживает аудио.", "choose_player": "Выберите медиаплеер", "choose-source": "Выбрать источник", "content-type": { @@ -572,6 +578,8 @@ "playlist": "Плейлист", "server": "Сервер" }, + "media_browsing_error": "Ошибка просмотра мультимедиа", + "media_not_supported": "Браузер медиаплеера не поддерживает этот тип мультимедиа.", "media_player": "Медиаплеер", "media-player-browser": "Браузер медиаплеера", "no_items": "Нет элементов", @@ -579,6 +587,7 @@ "pick-media": "Выбрать Медиа", "play": "Воспроизведение", "play-media": "Воспроизведение Медиа", + "video_not_supported": "Ваш браузер не поддерживает видео.", "web-browser": "Веб-браузер" }, "picture-upload": { @@ -864,7 +873,7 @@ "add": "Добавить действие", "delete": "Удалить", "delete_confirm": "Вы уверены, что хотите удалить?", - "duplicate": "Дублировать", + "duplicate": "Копировать", "header": "Действия", "introduction": "Действия — это то, что сделает Home Assistant, когда правило автоматизации сработает.", "learn_more": "Узнайте больше о действиях", @@ -924,7 +933,13 @@ "label": "Вызов службы", "service_data": "Данные" }, + "wait_for_trigger": { + "continue_timeout": "Продолжить по истечении времени", + "label": "Ожидать триггера", + "timeout": "Тайм-аут (необязательно)" + }, "wait_template": { + "continue_timeout": "Продолжить по истечении времени", "label": "Ожидание", "timeout": "Тайм-аут (необязательно)", "wait_template": "Шаблон ожидания" @@ -937,7 +952,7 @@ "add": "Добавить условие", "delete": "Удалить", "delete_confirm": "Вы уверены, что хотите удалить?", - "duplicate": "Дублировать", + "duplicate": "Копировать", "header": "Условия", "introduction": "Условия — это необязательная часть правила автоматизации. Действие автоматизации не будет выполнено, пока не будут удовлетворены все условия.", "learn_more": "Узнайте больше об условиях", @@ -988,7 +1003,9 @@ "time": { "after": "После", "before": "До", - "label": "Время" + "label": "Время", + "type_input": "Вспомогательный элемент даты и времени", + "type_value": "Фиксированное время" }, "zone": { "entity": "Объект с местоположением", @@ -1029,7 +1046,7 @@ "add": "Добавить триггер", "delete": "Удалить", "delete_confirm": "Вы уверены, что хотите удалить?", - "duplicate": "Дублировать", + "duplicate": "Копировать", "header": "Триггеры", "introduction": "Триггеры — это то, что запускает процесс автоматизации. Можно указать несколько триггеров на одно и то же правило. Когда триггер сработает, Home Assistant будет проверять условия (если таковые имеются), и выполнять действия.", "learn_more": "Узнайте больше о триггерах", @@ -1076,6 +1093,7 @@ "value_template": "Шаблон значения (необязательно)" }, "state": { + "attribute": "Атрибут (необязательно)", "for": "В течение", "from": "С", "label": "Состояние", @@ -1102,8 +1120,10 @@ "seconds": "Секунд" }, "time": { - "at": "В", - "label": "Время" + "at": "Время", + "label": "Время", + "type_input": "Вспомогательный элемент даты и времени", + "type_value": "Фиксированное время" }, "webhook": { "label": "Webhook", @@ -1126,6 +1146,8 @@ "add_automation": "Добавить автоматизацию", "delete_automation": "Удалить автоматизацию", "delete_confirm": "Вы уверены, что хотите удалить эту автоматизацию?", + "duplicate": "Копировать", + "duplicate_automation": "Копировать автоматизацию", "edit_automation": "Редактировать автоматизацию", "header": "Редактор автоматизаций", "headers": { @@ -1526,6 +1548,7 @@ }, "integrations": { "add_integration": "Добавить интеграцию", + "attention": "Требуется внимание", "caption": "Интеграции", "config_entry": { "area": "Помещение: {area}", @@ -1596,6 +1619,7 @@ "none_found_detail": "Измените критерии поиска", "note_about_integrations": "Пока что не все интеграции могут быть настроены через пользовательский интерфейс.", "note_about_website_reference": "Все доступные интеграции Вы можете найти на ", + "reconfigure": "Перенастроить", "rename_dialog": "Название интеграции", "rename_input_label": "Название", "search": "Поиск интеграций" diff --git a/translations/frontend/zh-Hans.json b/translations/frontend/zh-Hans.json index 525efe5654..fef4a36abf 100644 --- a/translations/frontend/zh-Hans.json +++ b/translations/frontend/zh-Hans.json @@ -19,6 +19,7 @@ "logbook": "日志", "mailbox": "邮箱", "map": "地图", + "media_browser": "媒体浏览器", "profile": "用户资料", "shopping_list": "购物清单", "states": "概览" @@ -552,6 +553,10 @@ "toggle": "切换" }, "entity": { + "entity-attribute-picker": { + "attribute": "属性", + "show_attributes": "显示属性" + }, "entity-picker": { "clear": "清除", "entity": "实体", @@ -573,6 +578,7 @@ "playlist": "播放列表", "server": "服务器" }, + "media_browsing_error": "媒体浏览错误", "media_not_supported": "浏览器媒体播放器不支持此类型的媒体", "media_player": "媒体播放器", "media-player-browser": "媒体播放浏览器", @@ -927,7 +933,13 @@ "label": "调用服务", "service_data": "服务数据" }, + "wait_for_trigger": { + "continue_timeout": "超时继续", + "label": "等待触发", + "timeout": "超时(可选)" + }, "wait_template": { + "continue_timeout": "超时继续", "label": "等待", "timeout": "超时(可选)", "wait_template": "等待模板" @@ -991,7 +1003,9 @@ "time": { "after": "晚于", "before": "早于", - "label": "时间" + "label": "时间", + "type_input": "“日期/时间”辅助元素的值", + "type_value": "固定时间" }, "zone": { "entity": "位置追踪设备", @@ -1079,6 +1093,7 @@ "value_template": "自定义值(可选)" }, "state": { + "attribute": "属性(可选)", "for": "持续", "from": "从", "label": "状态", @@ -1105,8 +1120,10 @@ "seconds": "秒" }, "time": { - "at": "当", - "label": "时间" + "at": "时间为", + "label": "时间", + "type_input": "“日期/时间”辅助元素的值", + "type_value": "固定时间" }, "webhook": { "label": "Webhook", @@ -1129,6 +1146,8 @@ "add_automation": "添加自动化", "delete_automation": "删除自动化", "delete_confirm": "您确定要删除此自动化吗?", + "duplicate": "制作副本", + "duplicate_automation": "复制自动化", "edit_automation": "编辑自动化", "header": "自动化编辑器", "headers": { @@ -1529,6 +1548,7 @@ }, "integrations": { "add_integration": "添加集成", + "attention": "需要注意", "caption": "集成", "config_entry": { "area": "位于:{area}", @@ -1552,6 +1572,7 @@ "reload_restart_confirm": "重启 Home Assistant 以完成此集成的重载", "rename": "重命名", "restart_confirm": "重启 Home Assistant 以完成此集成的删除", + "services": "{count} {count, plural,\n one {个服务}\n other {个服务}\n}", "settings_button": "编辑{integration}设置", "system_options": "系统选项", "system_options_button": "{integration}系统选项", @@ -1598,6 +1619,7 @@ "none_found_detail": "请调整搜索条件。", "note_about_integrations": "并非所有集成都可以通过 UI 进行配置。", "note_about_website_reference": "更多可用信息,尽在 ", + "reconfigure": "重新配置", "rename_dialog": "编辑此配置项的名称", "rename_input_label": "条目名称", "search": "搜索集成" From b3a763a48d1c14412e9e54444bed7b4541d5a903 Mon Sep 17 00:00:00 2001 From: Ludeeus Date: Wed, 9 Sep 2020 10:16:54 +0000 Subject: [PATCH 18/29] Add fallback for renderExternalStepHeader --- src/dialogs/config-flow/show-dialog-config-flow.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dialogs/config-flow/show-dialog-config-flow.ts b/src/dialogs/config-flow/show-dialog-config-flow.ts index 1ac015ecde..ae3c755631 100644 --- a/src/dialogs/config-flow/show-dialog-config-flow.ts +++ b/src/dialogs/config-flow/show-dialog-config-flow.ts @@ -97,8 +97,13 @@ export const showConfigFlowDialog = ( }, renderExternalStepHeader(hass, step) { - return hass.localize( - `component.${step.handler}.config.step.${step.step_id}.title` + return ( + hass.localize( + `component.${step.handler}.config.${step.step_id}.title` + ) || + hass.localize( + "ui.panel.config.integrations.config_flow.external_step.open_site" + ) ); }, From 5b8f97e0f60f1ccb02695199c966eab3db6f9cec Mon Sep 17 00:00:00 2001 From: Ludeeus Date: Wed, 9 Sep 2020 10:17:57 +0000 Subject: [PATCH 19/29] fix missing step --- src/dialogs/config-flow/show-dialog-config-flow.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dialogs/config-flow/show-dialog-config-flow.ts b/src/dialogs/config-flow/show-dialog-config-flow.ts index ae3c755631..92bbb21597 100644 --- a/src/dialogs/config-flow/show-dialog-config-flow.ts +++ b/src/dialogs/config-flow/show-dialog-config-flow.ts @@ -99,7 +99,7 @@ export const showConfigFlowDialog = ( renderExternalStepHeader(hass, step) { return ( hass.localize( - `component.${step.handler}.config.${step.step_id}.title` + `component.${step.handler}.config.step.${step.step_id}.title` ) || hass.localize( "ui.panel.config.integrations.config_flow.external_step.open_site" From 2dffe7ba9e0c0ec60058ed2c2e6fefb0f492f7d8 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Wed, 9 Sep 2020 13:27:54 +0200 Subject: [PATCH 20/29] Add binary sensor icon for DEVICE_CLASS_BATTERY_CHARGING (#6876) * Add binary sensor icon for DEVICE_CLASS_BATTERY_CHARGING * Update icons for DEVICE_CLASS_BATTERY_CHARGING --- src/common/entity/binary_sensor_icon.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/entity/binary_sensor_icon.ts b/src/common/entity/binary_sensor_icon.ts index c1eb694afe..845e096403 100644 --- a/src/common/entity/binary_sensor_icon.ts +++ b/src/common/entity/binary_sensor_icon.ts @@ -7,6 +7,8 @@ export const binarySensorIcon = (state: HassEntity) => { switch (state.attributes.device_class) { case "battery": return activated ? "hass:battery" : "hass:battery-outline"; + case "battery_charging": + return activated ? "hass:battery" : "hass:battery-charging"; case "cold": return activated ? "hass:thermometer" : "hass:snowflake"; case "connectivity": From f7ab52fe9a4c8567e57f8d20aedd816936e433c7 Mon Sep 17 00:00:00 2001 From: Zack Barett Date: Wed, 9 Sep 2020 10:22:34 -0500 Subject: [PATCH 21/29] Remove sort from frontend for now (#6886) --- src/components/media-player/ha-media-player-browse.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/components/media-player/ha-media-player-browse.ts b/src/components/media-player/ha-media-player-browse.ts index ad80b0d524..b2468fbbd3 100644 --- a/src/components/media-player/ha-media-player-browse.ts +++ b/src/components/media-player/ha-media-player-browse.ts @@ -21,7 +21,6 @@ import { ifDefined } from "lit-html/directives/if-defined"; import { styleMap } from "lit-html/directives/style-map"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../common/dom/fire_event"; -import { compare } from "../../common/string/compare"; import { computeRTLDirection } from "../../common/util/compute_rtl"; import { debounce } from "../../common/util/debounce"; import { @@ -478,13 +477,6 @@ export class HaMediaPlayerBrowse extends LitElement { mediaContentType ) : await browseLocalMediaPlayer(this.hass, mediaContentId); - itemData.children = itemData.children?.sort((first, second) => - !first.can_expand && second.can_expand - ? 1 - : first.can_expand && !second.can_expand - ? -1 - : compare(first.title, second.title) - ); return itemData; } From 432e3ba6363d9b711797ec11396e741b74a78bce Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 9 Sep 2020 17:23:03 +0200 Subject: [PATCH 22/29] Fix entity drag (#6884) --- .../lovelace/components/hui-entity-editor.ts | 44 ++++++++++++------- .../editor/card-editor/hui-card-editor.ts | 17 ++++--- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/panels/lovelace/components/hui-entity-editor.ts b/src/panels/lovelace/components/hui-entity-editor.ts index b22bc775fd..90e4b5eeb4 100644 --- a/src/panels/lovelace/components/hui-entity-editor.ts +++ b/src/panels/lovelace/components/hui-entity-editor.ts @@ -34,7 +34,9 @@ export class HuiEntityEditor extends LitElement { @internalProperty() private _attached = false; - private _sortable?; + @internalProperty() private _renderEmptySortable = false; + + private _sortable?: Sortable; public connectedCallback() { super.connectedCallback(); @@ -60,21 +62,23 @@ export class HuiEntityEditor extends LitElement { ")"}
    - ${guard([this.entities], () => - this.entities!.map((entityConf, index) => { - return html` -
    - - -
    - `; - }) + ${guard([this.entities, this._renderEmptySortable], () => + this._renderEmptySortable + ? "" + : this.entities!.map((entityConf, index) => { + return html` +
    + + +
    + `; + }) )}
    entity.entity)); + this._handleEntitiesChanged(); } } + private async _handleEntitiesChanged() { + this._renderEmptySortable = true; + await this.updateComplete; + this._renderEmptySortable = false; + } + private _createSortable() { this._sortable = new Sortable(this.shadowRoot!.querySelector(".entities"), { animation: 150, diff --git a/src/panels/lovelace/editor/card-editor/hui-card-editor.ts b/src/panels/lovelace/editor/card-editor/hui-card-editor.ts index f081cc65ae..5c786ad71e 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-editor.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-editor.ts @@ -5,14 +5,16 @@ import { CSSResult, customElement, html, + internalProperty, LitElement, property, - internalProperty, - TemplateResult, query, + TemplateResult, } from "lit-element"; import { fireEvent } from "../../../../common/dom/fire_event"; import { computeRTL } from "../../../../common/util/compute_rtl"; +import { deepEqual } from "../../../../common/util/deep-equal"; +import "../../../../components/ha-circular-progress"; import "../../../../components/ha-code-editor"; import type { HaCodeEditor } from "../../../../components/ha-code-editor"; import type { @@ -20,14 +22,12 @@ import type { LovelaceConfig, } from "../../../../data/lovelace"; import type { HomeAssistant } from "../../../../types"; +import { handleStructError } from "../../common/structs/handle-errors"; import { getCardElementClass } from "../../create-element/create-card-element"; import type { EntityConfig } from "../../entity-rows/types"; import type { LovelaceCardEditor } from "../../types"; -import type { GUIModeChangedEvent } from "../types"; -import "../../../../components/ha-circular-progress"; -import { deepEqual } from "../../../../common/util/deep-equal"; -import { handleStructError } from "../../common/structs/handle-errors"; import { GUISupportError } from "../gui-support-error"; +import type { GUIModeChangedEvent } from "../types"; export interface ConfigChangedEvent { config: LovelaceCardConfig; @@ -78,6 +78,9 @@ export class HuiCardEditor extends LitElement { @query("ha-code-editor") _yamlEditor?: HaCodeEditor; public get yaml(): string { + if (!this._yaml) { + this._yaml = safeDump(this._config); + } return this._yaml || ""; } @@ -101,7 +104,7 @@ export class HuiCardEditor extends LitElement { return; } this._config = config; - this._yaml = safeDump(config); + this._yaml = undefined; this._error = undefined; this._setConfig(); } From 5ff52ea1137c6d8640d6e6979686441940031966 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Wed, 9 Sep 2020 17:24:13 +0200 Subject: [PATCH 23/29] Update constant name to make it clearer (#6881) --- src/common/entity/binary_sensor_icon.ts | 42 ++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/common/entity/binary_sensor_icon.ts b/src/common/entity/binary_sensor_icon.ts index 845e096403..5442e432ff 100644 --- a/src/common/entity/binary_sensor_icon.ts +++ b/src/common/entity/binary_sensor_icon.ts @@ -3,51 +3,51 @@ import { HassEntity } from "home-assistant-js-websocket"; /** Return an icon representing a binary sensor state. */ export const binarySensorIcon = (state: HassEntity) => { - const activated = state.state && state.state === "off"; + const is_off = state.state && state.state === "off"; switch (state.attributes.device_class) { case "battery": - return activated ? "hass:battery" : "hass:battery-outline"; + return is_off ? "hass:battery" : "hass:battery-outline"; case "battery_charging": - return activated ? "hass:battery" : "hass:battery-charging"; + return is_off ? "hass:battery" : "hass:battery-charging"; case "cold": - return activated ? "hass:thermometer" : "hass:snowflake"; + return is_off ? "hass:thermometer" : "hass:snowflake"; case "connectivity": - return activated ? "hass:server-network-off" : "hass:server-network"; + return is_off ? "hass:server-network-off" : "hass:server-network"; case "door": - return activated ? "hass:door-closed" : "hass:door-open"; + return is_off ? "hass:door-closed" : "hass:door-open"; case "garage_door": - return activated ? "hass:garage" : "hass:garage-open"; + return is_off ? "hass:garage" : "hass:garage-open"; case "gas": case "power": case "problem": case "safety": case "smoke": - return activated ? "hass:shield-check" : "hass:alert"; + return is_off ? "hass:shield-check" : "hass:alert"; case "heat": - return activated ? "hass:thermometer" : "hass:fire"; + return is_off ? "hass:thermometer" : "hass:fire"; case "light": - return activated ? "hass:brightness-5" : "hass:brightness-7"; + return is_off ? "hass:brightness-5" : "hass:brightness-7"; case "lock": - return activated ? "hass:lock" : "hass:lock-open"; + return is_off ? "hass:lock" : "hass:lock-open"; case "moisture": - return activated ? "hass:water-off" : "hass:water"; + return is_off ? "hass:water-off" : "hass:water"; case "motion": - return activated ? "hass:walk" : "hass:run"; + return is_off ? "hass:walk" : "hass:run"; case "occupancy": - return activated ? "hass:home-outline" : "hass:home"; + return is_off ? "hass:home-outline" : "hass:home"; case "opening": - return activated ? "hass:square" : "hass:square-outline"; + return is_off ? "hass:square" : "hass:square-outline"; case "plug": - return activated ? "hass:power-plug-off" : "hass:power-plug"; + return is_off ? "hass:power-plug-off" : "hass:power-plug"; case "presence": - return activated ? "hass:home-outline" : "hass:home"; + return is_off ? "hass:home-outline" : "hass:home"; case "sound": - return activated ? "hass:music-note-off" : "hass:music-note"; + return is_off ? "hass:music-note-off" : "hass:music-note"; case "vibration": - return activated ? "hass:crop-portrait" : "hass:vibrate"; + return is_off ? "hass:crop-portrait" : "hass:vibrate"; case "window": - return activated ? "hass:window-closed" : "hass:window-open"; + return is_off ? "hass:window-closed" : "hass:window-open"; default: - return activated ? "hass:radiobox-blank" : "hass:checkbox-marked-circle"; + return is_off ? "hass:radiobox-blank" : "hass:checkbox-marked-circle"; } }; From 42bf350034b7a53f0c6ba76791ea9d2a65bf6d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Wed, 9 Sep 2020 17:26:22 +0200 Subject: [PATCH 24/29] Add ha-user-badge to view visibility editor (#6885) --- src/components/user/ha-person-badge.ts | 3 +++ src/components/user/ha-user-badge.ts | 3 +++ .../view-editor/hui-view-visibility-editor.ts | 14 ++++++++++---- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/components/user/ha-person-badge.ts b/src/components/user/ha-person-badge.ts index 70c47d6023..eead0784c2 100644 --- a/src/components/user/ha-person-badge.ts +++ b/src/components/user/ha-person-badge.ts @@ -39,6 +39,9 @@ class PersonBadge extends LitElement { static get styles(): CSSResult { return css` + :host { + display: contents; + } .picture { width: 40px; height: 40px; diff --git a/src/components/user/ha-user-badge.ts b/src/components/user/ha-user-badge.ts index 09972237fc..cb978dd004 100644 --- a/src/components/user/ha-user-badge.ts +++ b/src/components/user/ha-user-badge.ts @@ -104,6 +104,9 @@ class UserBadge extends LitElement { static get styles(): CSSResult { return css` + :host { + display: contents; + } .picture { width: 40px; height: 40px; diff --git a/src/panels/lovelace/editor/view-editor/hui-view-visibility-editor.ts b/src/panels/lovelace/editor/view-editor/hui-view-visibility-editor.ts index 8bb8f62f07..f5ed39cf9b 100644 --- a/src/panels/lovelace/editor/view-editor/hui-view-visibility-editor.ts +++ b/src/panels/lovelace/editor/view-editor/hui-view-visibility-editor.ts @@ -1,13 +1,13 @@ -import "@polymer/paper-item/paper-item"; +import "@polymer/paper-item/paper-icon-item"; import "@polymer/paper-item/paper-item-body"; import { css, CSSResult, customElement, html, + internalProperty, LitElement, property, - internalProperty, PropertyValues, TemplateResult, } from "lit-element"; @@ -15,6 +15,7 @@ import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../common/dom/fire_event"; import { compare } from "../../../../common/string/compare"; import { HaSwitch } from "../../../../components/ha-switch"; +import "../../../../components/user/ha-user-badge"; import { LovelaceViewConfig, ShowViewConfig } from "../../../../data/lovelace"; import { fetchUsers, User } from "../../../../data/user"; import { HomeAssistant } from "../../../../types"; @@ -69,14 +70,19 @@ export class HuiViewVisibilityEditor extends LitElement {

    ${this._sortedUsers(this._users).map( (user) => html` - + + ${user.name} - + ` )} `; From 1890aab1e60020f03390d679bfab29c6e011f058 Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Wed, 9 Sep 2020 20:48:51 +0200 Subject: [PATCH 25/29] Color all deletion options consistenly red (#6891) * Color all deletion options consistenly red * CSS cleanup * Color the "Remove Selected" entity config button * Make eslint happy * Getting rid of a wayward bracket --- .../action/ha-automation-action-row.ts | 1 - .../config/automation/ha-automation-editor.ts | 1 + .../config/entities/ha-config-entities.ts | 219 +++++++++--------- src/panels/config/scene/ha-scene-editor.ts | 1 + src/panels/config/script/ha-script-editor.ts | 1 + 5 files changed, 115 insertions(+), 108 deletions(-) diff --git a/src/panels/config/automation/action/ha-automation-action-row.ts b/src/panels/config/automation/action/ha-automation-action-row.ts index d9cf65ce8c..f9f82bbd5b 100644 --- a/src/panels/config/automation/action/ha-automation-action-row.ts +++ b/src/panels/config/automation/action/ha-automation-action-row.ts @@ -336,7 +336,6 @@ export default class HaAutomationActionRow extends LitElement { --mdc-theme-text-primary-on-background: var(--disabled-text-color); } .warning { - color: var(--warning-color); margin-bottom: 8px; } .warning ul { diff --git a/src/panels/config/automation/ha-automation-editor.ts b/src/panels/config/automation/ha-automation-editor.ts index 1c6f0c125c..f76f44ac67 100644 --- a/src/panels/config/automation/ha-automation-editor.ts +++ b/src/panels/config/automation/ha-automation-editor.ts @@ -104,6 +104,7 @@ export class HaAutomationEditor extends LitElement { - ${this.hass.localize( "ui.panel.config.entities.picker.remove_selected.button" )} mwc-button, - .header-btns > ha-icon-button { - margin: 8px; - } - .active-filters { - color: var(--primary-text-color); - position: relative; - display: flex; - align-items: center; - padding: 2px 2px 2px 8px; - margin-left: 4px; - font-size: 14px; - } - .active-filters ha-icon { - color: var(--primary-color); - } - .active-filters mwc-button { - margin-left: 8px; - } - .active-filters::before { - background-color: var(--primary-color); - opacity: 0.12; - border-radius: 4px; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - content: ""; - } - `; + static get styles(): CSSResult[] { + return [ + haStyle, + css` + hass-loading-screen { + --app-header-background-color: var(--sidebar-background-color); + --app-header-text-color: var(--sidebar-text-color); + } + a { + color: var(--primary-color); + } + h2 { + margin-top: 0; + font-family: var(--paper-font-headline_-_font-family); + -webkit-font-smoothing: var( + --paper-font-headline_-_-webkit-font-smoothing + ); + font-size: var(--paper-font-headline_-_font-size); + font-weight: var(--paper-font-headline_-_font-weight); + letter-spacing: var(--paper-font-headline_-_letter-spacing); + line-height: var(--paper-font-headline_-_line-height); + opacity: var(--dark-primary-opacity); + } + p { + font-family: var(--paper-font-subhead_-_font-family); + -webkit-font-smoothing: var( + --paper-font-subhead_-_-webkit-font-smoothing + ); + font-weight: var(--paper-font-subhead_-_font-weight); + line-height: var(--paper-font-subhead_-_line-height); + } + ha-data-table { + width: 100%; + --data-table-border-width: 0; + } + :host(:not([narrow])) ha-data-table { + height: calc(100vh - 65px); + display: block; + } + ha-button-menu { + margin-right: 8px; + } + .table-header { + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid rgba(var(--rgb-primary-text-color), 0.12); + } + search-input { + margin-left: 16px; + flex-grow: 1; + position: relative; + top: 2px; + } + .search-toolbar search-input { + margin-left: 8px; + top: 1px; + } + .search-toolbar { + display: flex; + justify-content: space-between; + align-items: center; + color: var(--secondary-text-color); + } + .search-toolbar ha-button-menu { + position: static; + } + .selected-txt { + font-weight: bold; + padding-left: 16px; + } + .table-header .selected-txt { + margin-top: 20px; + } + .search-toolbar .selected-txt { + font-size: 16px; + } + .header-btns > mwc-button, + .header-btns > ha-icon-button { + margin: 8px; + } + .active-filters { + color: var(--primary-text-color); + position: relative; + display: flex; + align-items: center; + padding: 2px 2px 2px 8px; + margin-left: 4px; + font-size: 14px; + } + .active-filters ha-icon { + color: var(--primary-color); + } + .active-filters mwc-button { + margin-left: 8px; + } + .active-filters::before { + background-color: var(--primary-color); + opacity: 0.12; + border-radius: 4px; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + content: ""; + } + `, + ]; } } diff --git a/src/panels/config/scene/ha-scene-editor.ts b/src/panels/config/scene/ha-scene-editor.ts index 77bec1b7db..73f0e29ce3 100644 --- a/src/panels/config/scene/ha-scene-editor.ts +++ b/src/panels/config/scene/ha-scene-editor.ts @@ -198,6 +198,7 @@ export class HaSceneEditor extends SubscribeMixin(LitElement) { ? "" : html` Date: Wed, 9 Sep 2020 20:49:56 +0200 Subject: [PATCH 26/29] Disable "Execute" if automation is unavailable (#6866) --- src/dialogs/more-info/controls/more-info-automation.ts | 5 ++++- src/panels/config/automation/ha-automation-picker.ts | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dialogs/more-info/controls/more-info-automation.ts b/src/dialogs/more-info/controls/more-info-automation.ts index 8a25e93fe4..a63a10d819 100644 --- a/src/dialogs/more-info/controls/more-info-automation.ts +++ b/src/dialogs/more-info/controls/more-info-automation.ts @@ -34,7 +34,10 @@ class MoreInfoAutomation extends LitElement {
    - + ${this.hass.localize("ui.card.automation.trigger")}
    diff --git a/src/panels/config/automation/ha-automation-picker.ts b/src/panels/config/automation/ha-automation-picker.ts index e56b62fe2b..221f7f1e14 100644 --- a/src/panels/config/automation/ha-automation-picker.ts +++ b/src/panels/config/automation/ha-automation-picker.ts @@ -91,10 +91,11 @@ class HaAutomationPicker extends LitElement { if (!narrow) { columns.execute = { title: "", - template: (_info, automation) => html` + template: (_info, automation: any) => html` this._execute(ev)} + .disabled=${automation.state === "unavailable"} > ${this.hass.localize("ui.card.automation.trigger")} From d99d092784fbf28b59bf9a6e7027525cbf9a6259 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 9 Sep 2020 21:02:14 +0200 Subject: [PATCH 27/29] Enlarge touch target delete button (#6893) --- src/components/ha-sidebar.ts | 9 +++++---- src/resources/ha-sortable-style.ts | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/ha-sidebar.ts b/src/components/ha-sidebar.ts index d02c7bbd60..41d460fc9f 100644 --- a/src/components/ha-sidebar.ts +++ b/src/components/ha-sidebar.ts @@ -526,7 +526,7 @@ class HaSidebar extends LitElement { private async _hidePanel(ev: Event) { ev.preventDefault(); - const panel = (ev.target as any).panel; + const panel = (ev.currentTarget as any).panel; if (this._hiddenPanels.includes(panel)) { return; } @@ -692,12 +692,13 @@ class HaSidebar extends LitElement { : html``} ${title} ${this._editMode - ? html`` + > + + ` : ""}
    diff --git a/src/resources/ha-sortable-style.ts b/src/resources/ha-sortable-style.ts index 5751f54819..b6e3d377c5 100644 --- a/src/resources/ha-sortable-style.ts +++ b/src/resources/ha-sortable-style.ts @@ -57,7 +57,7 @@ export const sortableStyles = css` .hide-panel { display: none; position: absolute; - right: 8px; + right: 0; } :host([expanded]) .hide-panel { From 1130007d14106bf15ae2a806194f3c6d01a7b24a Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 9 Sep 2020 22:09:56 +0200 Subject: [PATCH 28/29] Fix mjpeg player (#6896) --- src/components/ha-camera-stream.ts | 10 ++++++---- src/dialogs/more-info/controls/more-info-camera.ts | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/ha-camera-stream.ts b/src/components/ha-camera-stream.ts index 51794b3ad3..b2db579890 100644 --- a/src/components/ha-camera-stream.ts +++ b/src/components/ha-camera-stream.ts @@ -35,7 +35,7 @@ class HaCameraStream extends LitElement { @internalProperty() private _url?: string; protected render(): TemplateResult { - if (!this.stateObj || (!this._forceMJPEG && !this._url)) { + if (!this.stateObj) { return html``; } @@ -52,16 +52,18 @@ class HaCameraStream extends LitElement { )} camera.`} /> ` - : html` + : this._url + ? html` - `} + ` + : ""} `; } diff --git a/src/dialogs/more-info/controls/more-info-camera.ts b/src/dialogs/more-info/controls/more-info-camera.ts index d990cf25a0..4bc02b6a79 100644 --- a/src/dialogs/more-info/controls/more-info-camera.ts +++ b/src/dialogs/more-info/controls/more-info-camera.ts @@ -4,9 +4,9 @@ import { css, CSSResult, html, + internalProperty, LitElement, property, - internalProperty, PropertyValues, TemplateResult, } from "lit-element"; @@ -47,7 +47,7 @@ class MoreInfoCamera extends LitElement { return html` ${this._cameraPrefs From e0bdef98a65777846a97b4678f2e2cc5557a1293 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 9 Sep 2020 22:10:23 +0200 Subject: [PATCH 29/29] Only show history tabs for certain domains (#6895) Co-authored-by: Zack Barett --- .../controls/more-info-automation.ts | 2 +- src/dialogs/more-info/ha-more-info-dialog.ts | 30 ++++++++++++++----- ...tab-history.ts => ha-more-info-history.ts} | 23 +++++++------- src/panels/logbook/ha-logbook.ts | 2 +- src/translations/en.json | 6 ++-- 5 files changed, 41 insertions(+), 22 deletions(-) rename src/dialogs/more-info/{ha-more-info-tab-history.ts => ha-more-info-history.ts} (89%) diff --git a/src/dialogs/more-info/controls/more-info-automation.ts b/src/dialogs/more-info/controls/more-info-automation.ts index a63a10d819..8b4ff441c2 100644 --- a/src/dialogs/more-info/controls/more-info-automation.ts +++ b/src/dialogs/more-info/controls/more-info-automation.ts @@ -55,7 +55,7 @@ class MoreInfoAutomation extends LitElement { justify-content: space-between; } .actions { - margin: 36px 0 8px 0; + margin: 8px 0; text-align: right; } `; diff --git a/src/dialogs/more-info/ha-more-info-dialog.ts b/src/dialogs/more-info/ha-more-info-dialog.ts index 7738ee7349..63381e3251 100644 --- a/src/dialogs/more-info/ha-more-info-dialog.ts +++ b/src/dialogs/more-info/ha-more-info-dialog.ts @@ -29,9 +29,19 @@ import { haStyleDialog } from "../../resources/styles"; import "../../state-summary/state-card-content"; import { HomeAssistant } from "../../types"; import { showConfirmationDialog } from "../generic/show-dialog-box"; +import "./ha-more-info-history"; import "./more-info-content"; const DOMAINS_NO_INFO = ["camera", "configurator"]; +const CONTROL_DOMAINS = [ + "light", + "media_player", + "vacuum", + "alarm_control_panel", + "climate", + "humidifier", + "weather", +]; const EDITABLE_DOMAINS_WITH_ID = ["scene", "automation"]; const EDITABLE_DOMAINS = ["script"]; @@ -127,7 +137,8 @@ export class MoreInfoDialog extends LitElement { ` : ""} - ${this._computeShowHistoryComponent(entityId) + ${CONTROL_DOMAINS.includes(domain) && + this._computeShowHistoryComponent(entityId) ? html` + ${!CONTROL_DOMAINS.includes(domain) || + !this._computeShowHistoryComponent(entityId) + ? "" + : html``} ${stateObj.attributes.restored ? html`

    @@ -188,10 +206,10 @@ export class MoreInfoDialog extends LitElement { : ""} ` : html` - + > ` )}

    @@ -199,10 +217,6 @@ export class MoreInfoDialog extends LitElement { `; } - protected firstUpdated(): void { - import("./ha-more-info-tab-history"); - } - private _enlarge() { this.large = !this.large; } diff --git a/src/dialogs/more-info/ha-more-info-tab-history.ts b/src/dialogs/more-info/ha-more-info-history.ts similarity index 89% rename from src/dialogs/more-info/ha-more-info-tab-history.ts rename to src/dialogs/more-info/ha-more-info-history.ts index 18624a11ef..4c57bbd2c3 100644 --- a/src/dialogs/more-info/ha-more-info-tab-history.ts +++ b/src/dialogs/more-info/ha-more-info-history.ts @@ -16,11 +16,11 @@ import { getRecentWithCache } from "../../data/cached-history"; import { HistoryResult } from "../../data/history"; import { getLogbookData, LogbookEntry } from "../../data/logbook"; import "../../panels/logbook/ha-logbook"; -import { haStyleDialog } from "../../resources/styles"; +import { haStyle } from "../../resources/styles"; import { HomeAssistant } from "../../types"; -@customElement("ha-more-info-tab-history") -export class MoreInfoTabHistoryDialog extends LitElement { +@customElement("ha-more-info-history") +export class MoreInfoHistory extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property() public entityId!: string; @@ -43,8 +43,7 @@ export class MoreInfoTabHistoryDialog extends LitElement { return html``; } - return html` - ` - : ""} - `; + : html`
    + ${this.hass.localize("ui.components.logbook.entries_not_found")} +
    `}`; } protected firstUpdated(): void { @@ -139,13 +139,16 @@ export class MoreInfoTabHistoryDialog extends LitElement { static get styles() { return [ - haStyleDialog, + haStyle, css` state-history-charts { display: block; margin-bottom: 16px; } - + .no-entries { + text-align: center; + padding: 16px; + } ha-logbook { max-height: 360px; } @@ -161,6 +164,6 @@ export class MoreInfoTabHistoryDialog extends LitElement { declare global { interface HTMLElementTagNameMap { - "ha-more-info-tab-history": MoreInfoTabHistoryDialog; + "ha-more-info-history": MoreInfoHistory; } } diff --git a/src/panels/logbook/ha-logbook.ts b/src/panels/logbook/ha-logbook.ts index cf49dd24ba..2eb994cae1 100644 --- a/src/panels/logbook/ha-logbook.ts +++ b/src/panels/logbook/ha-logbook.ts @@ -67,7 +67,7 @@ class HaLogbook extends LitElement { if (!this.entries?.length) { return html`
    - ${this.hass.localize("ui.panel.logbook.entries_not_found")} + ${this.hass.localize("ui.components.logbook.entries_not_found")}
    `; } diff --git a/src/translations/en.json b/src/translations/en.json index 219471c422..24f05139cc 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -281,6 +281,9 @@ "error_required": "Required" }, "components": { + "logbook": { + "entries_not_found": "No logbook entries found." + }, "entity": { "entity-picker": { "entity": "Entity", @@ -401,7 +404,7 @@ "dismiss": "Dismiss dialog", "settings": "Entity settings", "edit": "Edit entity", - "controls": "Controls", + "details": "Details", "history": "History", "script": { "last_action": "Last Action", @@ -2045,7 +2048,6 @@ } }, "logbook": { - "entries_not_found": "No logbook entries found.", "ranges": { "today": "Today", "yesterday": "Yesterday",