From 310b81de04a494259cfab796221c7b193dbd675a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 11 Feb 2019 14:14:29 -0800 Subject: [PATCH 01/66] Convert HUI-IMAGE to TypeScript/Lit (#2713) * Fix gallery demos * Convert HUI-IMAGE to TypeScript/Lit * Clean up --- .../src/demos/demo-hui-picture-entity-card.ts | 23 +- .../src/demos/demo-hui-picture-glance-card.ts | 27 ++- gallery/webpack.config.js | 2 +- src/common/file/b64-to-blob.ts | 20 ++ src/data/camera.ts | 12 + src/panels/lovelace/components/hui-image.js | 199 --------------- src/panels/lovelace/components/hui-image.ts | 226 ++++++++++++++++++ 7 files changed, 307 insertions(+), 202 deletions(-) create mode 100644 src/common/file/b64-to-blob.ts create mode 100644 src/data/camera.ts delete mode 100644 src/panels/lovelace/components/hui-image.js create mode 100644 src/panels/lovelace/components/hui-image.ts diff --git a/gallery/src/demos/demo-hui-picture-entity-card.ts b/gallery/src/demos/demo-hui-picture-entity-card.ts index 7940a5ad00..1378707e45 100644 --- a/gallery/src/demos/demo-hui-picture-entity-card.ts +++ b/gallery/src/demos/demo-hui-picture-entity-card.ts @@ -2,6 +2,17 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../components/demo-cards"; +import { provideHass } from "../../../src/fake_data/provide_hass"; +import { getEntity } from "../../../src/fake_data/entity"; + +const ENTITIES = [ + getEntity("light", "kitchen_lights", "on", { + friendly_name: "Kitchen Lights", + }), + getEntity("light", "bed_light", "off", { + friendly_name: "Bed Light", + }), +]; const CONFIGS = [ { @@ -10,6 +21,8 @@ const CONFIGS = [ - type: picture-entity image: /images/kitchen.png entity: light.kitchen_lights + tap_action: + action: toggle `, }, { @@ -18,6 +31,8 @@ const CONFIGS = [ - type: picture-entity image: /images/bed.png entity: light.bed_light + tap_action: + action: toggle `, }, { @@ -68,7 +83,7 @@ const CONFIGS = [ class DemoPicEntity extends PolymerElement { static get template() { return html` - + `; } @@ -80,6 +95,12 @@ class DemoPicEntity extends PolymerElement { }, }; } + + public ready() { + super.ready(); + const hass = provideHass(this.$.demos); + hass.addEntities(ENTITIES); + } } customElements.define("demo-hui-picture-entity-card", DemoPicEntity); diff --git a/gallery/src/demos/demo-hui-picture-glance-card.ts b/gallery/src/demos/demo-hui-picture-glance-card.ts index 2ab8d7c32c..faae58bd7b 100644 --- a/gallery/src/demos/demo-hui-picture-glance-card.ts +++ b/gallery/src/demos/demo-hui-picture-glance-card.ts @@ -2,6 +2,25 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../components/demo-cards"; +import { getEntity } from "../../../src/fake_data/entity"; +import { provideHass } from "../../../src/fake_data/provide_hass"; + +const ENTITIES = [ + getEntity("switch", "decorative_lights", "on", { + friendly_name: "Decorative Lights", + }), + getEntity("light", "ceiling_lights", "on", { + friendly_name: "Ceiling Lights", + }), + getEntity("binary_sensor", "movement_backyard", "on", { + friendly_name: "Movement Backyard", + device_class: "moving", + }), + getEntity("binary_sensor", "basement_floor_wet", "off", { + friendly_name: "Basement Floor Wet", + device_class: "moisture", + }), +]; const CONFIGS = [ { @@ -105,7 +124,7 @@ const CONFIGS = [ class DemoPicGlance extends PolymerElement { static get template() { return html` - + `; } @@ -117,6 +136,12 @@ class DemoPicGlance extends PolymerElement { }, }; } + + public ready() { + super.ready(); + const hass = provideHass(this.$.demos); + hass.addEntities(ENTITIES); + } } customElements.define("demo-hui-picture-glance-card", DemoPicGlance); diff --git a/gallery/webpack.config.js b/gallery/webpack.config.js index 763bed55c7..82a7008709 100644 --- a/gallery/webpack.config.js +++ b/gallery/webpack.config.js @@ -1,7 +1,7 @@ const path = require("path"); const CopyWebpackPlugin = require("copy-webpack-plugin"); const { babelLoaderConfig } = require("../config/babel.js"); -const webpackBase = require("../config/babel.js"); +const webpackBase = require("../config/webpack.js"); const isProd = process.env.NODE_ENV === "production"; const chunkFilename = isProd ? "chunk.[chunkhash].js" : "[name].chunk.js"; diff --git a/src/common/file/b64-to-blob.ts b/src/common/file/b64-to-blob.ts new file mode 100644 index 0000000000..969cfcae1a --- /dev/null +++ b/src/common/file/b64-to-blob.ts @@ -0,0 +1,20 @@ +// https://stackoverflow.com/a/16245768 +export const b64toBlob = (b64Data, contentType = "", sliceSize = 512) => { + const byteCharacters = atob(b64Data); + const byteArrays: Uint8Array[] = []; + + for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { + const slice = byteCharacters.slice(offset, offset + sliceSize); + + const byteNumbers = new Array(slice.length); + for (let i = 0; i < slice.length; i++) { + byteNumbers[i] = slice.charCodeAt(i); + } + + const byteArray = new Uint8Array(byteNumbers); + + byteArrays.push(byteArray); + } + + return new Blob(byteArrays, { type: contentType }); +}; diff --git a/src/data/camera.ts b/src/data/camera.ts new file mode 100644 index 0000000000..cde6abb596 --- /dev/null +++ b/src/data/camera.ts @@ -0,0 +1,12 @@ +import { HomeAssistant } from "../types"; + +export interface CameraThumbnail { + content_type: string; + content: string; +} + +export const fetchThumbnail = (hass: HomeAssistant, entityId: string) => + hass.callWS({ + type: "camera_thumbnail", + entity_id: entityId, + }); diff --git a/src/panels/lovelace/components/hui-image.js b/src/panels/lovelace/components/hui-image.js deleted file mode 100644 index 1ad89c3bac..0000000000 --- a/src/panels/lovelace/components/hui-image.js +++ /dev/null @@ -1,199 +0,0 @@ -import { html } from "@polymer/polymer/lib/utils/html-tag"; -import { PolymerElement } from "@polymer/polymer/polymer-element"; -import "@polymer/paper-toggle-button/paper-toggle-button"; - -import { STATES_OFF } from "../../../common/const"; -import LocalizeMixin from "../../../mixins/localize-mixin"; - -import parseAspectRatio from "../../../common/util/parse-aspect-ratio"; - -const UPDATE_INTERVAL = 10000; -const DEFAULT_FILTER = "grayscale(100%)"; - -/* - * @appliesMixin LocalizeMixin - */ -class HuiImage extends LocalizeMixin(PolymerElement) { - static get template() { - return html` - ${this.styleTemplate} -
- -
-
- `; - } - - static get styleTemplate() { - return html` - - `; - } - - static get properties() { - return { - hass: { - type: Object, - observer: "_hassChanged", - }, - entity: String, - image: String, - stateImage: Object, - cameraImage: String, - aspectRatio: String, - filter: String, - stateFilter: Object, - _imageSrc: String, - }; - } - - static get observers() { - return ["_configChanged(image, stateImage, cameraImage, aspectRatio)"]; - } - - connectedCallback() { - super.connectedCallback(); - if (this.cameraImage) { - this.timer = setInterval( - () => this._updateCameraImageSrc(), - UPDATE_INTERVAL - ); - } - } - - disconnectedCallback() { - super.disconnectedCallback(); - clearInterval(this.timer); - } - - _configChanged(image, stateImage, cameraImage, aspectRatio) { - const ratio = parseAspectRatio(aspectRatio); - - if (ratio && ratio.w > 0 && ratio.h > 0) { - this.$.wrapper.style.paddingBottom = `${( - (100 * ratio.h) / - ratio.w - ).toFixed(2)}%`; - this.$.wrapper.classList.add("ratio"); - } - - if (cameraImage) { - this._updateCameraImageSrc(); - } else if (image && !stateImage) { - this._imageSrc = image; - } - } - - _onImageError() { - this._imageSrc = null; - this.$.image.classList.add("hidden"); - if (!this.$.wrapper.classList.contains("ratio")) { - this.$.brokenImage.style.setProperty( - "height", - `${this._lastImageHeight || "100"}px` - ); - } - this.$.brokenImage.classList.remove("hidden"); - } - - _onImageLoad() { - this.$.image.classList.remove("hidden"); - this.$.brokenImage.classList.add("hidden"); - if (!this.$.wrapper.classList.contains("ratio")) { - this._lastImageHeight = this.$.image.offsetHeight; - } - } - - _hassChanged(hass) { - if (this.cameraImage || !this.entity) { - return; - } - - const stateObj = hass.states[this.entity]; - const newState = !stateObj ? "unavailable" : stateObj.state; - - if (newState === this._currentState) return; - this._currentState = newState; - - this._updateStateImage(); - this._updateStateFilter(stateObj); - } - - _updateStateImage() { - if (!this.stateImage) { - this._imageFallback = true; - return; - } - const stateImg = this.stateImage[this._currentState]; - this._imageSrc = stateImg || this.image; - this._imageFallback = !stateImg; - } - - _updateStateFilter(stateObj) { - let filter; - if (!this.stateFilter) { - filter = this.filter; - } else { - filter = this.stateFilter[this._currentState] || this.filter; - } - - const isOff = !stateObj || STATES_OFF.includes(stateObj.state); - this.$.image.style.filter = - filter || (isOff && this._imageFallback && DEFAULT_FILTER) || ""; - } - - async _updateCameraImageSrc() { - try { - const { content_type: contentType, content } = await this.hass.callWS({ - type: "camera_thumbnail", - entity_id: this.cameraImage, - }); - this._imageSrc = `data:${contentType};base64, ${content}`; - this._onImageLoad(); - } catch (err) { - this._onImageError(); - } - } -} - -customElements.define("hui-image", HuiImage); diff --git a/src/panels/lovelace/components/hui-image.ts b/src/panels/lovelace/components/hui-image.ts new file mode 100644 index 0000000000..cdc7b06aa1 --- /dev/null +++ b/src/panels/lovelace/components/hui-image.ts @@ -0,0 +1,226 @@ +import "@polymer/paper-toggle-button/paper-toggle-button"; + +import { STATES_OFF } from "../../../common/const"; + +import parseAspectRatio from "../../../common/util/parse-aspect-ratio"; +import { + LitElement, + TemplateResult, + html, + property, + CSSResult, + css, + PropertyValues, + query, +} from "lit-element"; +import { HomeAssistant } from "../../../types"; +import { styleMap } from "lit-html/directives/style-map"; +import { classMap } from "lit-html/directives/class-map"; +import { b64toBlob } from "../../../common/file/b64-to-blob"; +import { fetchThumbnail } from "../../../data/camera"; + +const UPDATE_INTERVAL = 10000; +const DEFAULT_FILTER = "grayscale(100%)"; + +export interface StateSpecificConfig { + [state: string]: string; +} + +/* + * @appliesMixin LocalizeMixin + */ +class HuiImage extends LitElement { + @property() public hass?: HomeAssistant; + @property() public entity?: string; + @property() public image?: string; + @property() public stateImage?: StateSpecificConfig; + @property() public cameraImage?: string; + @property() public aspectRatio?: string; + @property() public filter?: string; + @property() public stateFilter?: StateSpecificConfig; + + @property() private _loadError?: boolean; + @property() private _cameraImageSrc?: string; + @query("img") private _image!: HTMLImageElement; + private _lastImageHeight?: number; + private _cameraUpdater?: number; + private _attached?: boolean; + + public connectedCallback() { + super.connectedCallback(); + this._attached = true; + this._startUpdateCameraInterval(); + } + + public disconnectedCallback() { + super.disconnectedCallback(); + this._attached = false; + this._stopUpdateCameraInterval(); + } + + protected render(): TemplateResult | void { + const ratio = this.aspectRatio ? parseAspectRatio(this.aspectRatio) : null; + const stateObj = + this.hass && this.entity ? this.hass.states[this.entity] : undefined; + const state = stateObj ? stateObj.state : "unavailable"; + + // Figure out image source to use + let imageSrc: string | undefined; + // Track if we are we using a fallback image, used for filter. + let imageFallback = !this.stateImage; + + if (this.cameraImage) { + imageSrc = this._cameraImageSrc; + } else if (this.stateImage) { + const stateImage = this.stateImage[state]; + + if (stateImage) { + imageSrc = stateImage; + } else { + imageSrc = this.image; + imageFallback = true; + } + } else { + imageSrc = this.image; + } + + // Figure out filter to use + let filter = this.filter || ""; + + if (this.stateFilter && this.stateFilter[state]) { + filter = this.stateFilter[state]; + } + + if (!filter && this.entity) { + const isOff = !stateObj || STATES_OFF.includes(state); + filter = isOff && imageFallback ? DEFAULT_FILTER : ""; + } + + return html` +
0 && ratio.h > 0 + ? `${((100 * ratio.h) / ratio.w).toFixed(2)}%` + : "", + })} + class=${classMap({ + ratio: Boolean(ratio && ratio.w > 0 && ratio.h > 0), + })} + > + +
+
+ `; + } + + protected updated(changedProps: PropertyValues): void { + if (changedProps.has("cameraImage")) { + this._updateCameraImageSrc(); + this._startUpdateCameraInterval(); + return; + } + } + + private _startUpdateCameraInterval() { + this._stopUpdateCameraInterval(); + if (this.cameraImage && this._attached) { + this._cameraUpdater = window.setInterval( + () => this._updateCameraImageSrc(), + UPDATE_INTERVAL + ); + } + } + + private _stopUpdateCameraInterval() { + if (this._cameraUpdater) { + clearInterval(this._cameraUpdater); + } + } + + private _onImageError() { + this._loadError = true; + } + + private async _onImageLoad() { + this._loadError = false; + await this.updateComplete; + this._lastImageHeight = this._image.offsetHeight; + } + + private async _updateCameraImageSrc() { + if (!this.hass || !this.cameraImage) { + return; + } + if (this._cameraImageSrc) { + URL.revokeObjectURL(this._cameraImageSrc); + this._cameraImageSrc = undefined; + } + try { + const { content_type: contentType, content } = await fetchThumbnail( + this.hass, + this.cameraImage + ); + this._cameraImageSrc = URL.createObjectURL( + b64toBlob(content, contentType) + ); + this._onImageLoad(); + } catch (err) { + this._onImageError(); + } + } + + static get styles(): CSSResult { + return css` + img { + display: block; + height: auto; + transition: filter 0.2s linear; + width: 100%; + } + + .ratio { + position: relative; + width: 100%; + height: 0; + } + + .ratio img, + .ratio div { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + #brokenImage { + background: grey url("/static/images/image-broken.svg") center/36px + no-repeat; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-image": HuiImage; + } +} + +customElements.define("hui-image", HuiImage); From 44dca3b86dd6c985b8cab1b6b482eb8ebd1953fc Mon Sep 17 00:00:00 2001 From: yosilevy <37745463+yosilevy@users.noreply.github.com> Date: Tue, 12 Feb 2019 00:18:17 +0200 Subject: [PATCH 02/66] Make yaml editor scrollabel in RTL mode (#2706) * Make yaml editor scrollabel in RTL mode * Refactor * Refactor scopped CSS * Refactor * Fixes * Refactor --- .../lovelace/components/hui-yaml-editor.ts | 66 ++++++++++++++----- .../editor/card-editor/hui-edit-card.ts | 1 + src/panels/lovelace/ha-panel-lovelace.ts | 1 + src/panels/lovelace/hui-editor.ts | 5 +- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/src/panels/lovelace/components/hui-yaml-editor.ts b/src/panels/lovelace/components/hui-yaml-editor.ts index ae2a9b65ad..2162225ae3 100644 --- a/src/panels/lovelace/components/hui-yaml-editor.ts +++ b/src/panels/lovelace/components/hui-yaml-editor.ts @@ -3,7 +3,10 @@ import CodeMirror from "codemirror"; import "codemirror/mode/yaml/yaml"; // @ts-ignore import codeMirrorCSS from "codemirror/lib/codemirror.css"; +import { HomeAssistant } from "../../../types"; import { fireEvent } from "../../../common/dom/fire_event"; +import { computeRTL } from "../../../common/util/compute_rtl"; + declare global { interface HASSDomEvents { "yaml-changed": { @@ -14,6 +17,7 @@ declare global { } export class HuiYamlEditor extends HTMLElement { + public _hass?: HomeAssistant; public codemirror: CodeMirror; private _value: string; @@ -26,25 +30,40 @@ export class HuiYamlEditor extends HTMLElement { const shadowRoot = this.attachShadow({ mode: "open" }); shadowRoot.innerHTML = ` `; } + set hass(hass: HomeAssistant) { + this._hass = hass; + if (this._hass) { + this.setScrollBarDirection(); + } + } + set value(value: string) { if (this.codemirror) { if (value !== this.codemirror.getValue()) { @@ -76,7 +95,12 @@ export class HuiYamlEditor extends HTMLElement { cm.replaceSelection(spaces); }, }, + gutters: + this._hass && computeRTL(this._hass!) + ? ["rtl-gutter", "CodeMirror-linenumbers"] + : [], }); + this.setScrollBarDirection(); this.codemirror.on("changes", () => this._onChange()); } else { this.codemirror.refresh(); @@ -86,6 +110,16 @@ export class HuiYamlEditor extends HTMLElement { private _onChange(): void { fireEvent(this, "yaml-changed", { value: this.codemirror.getValue() }); } + + private setScrollBarDirection() { + if (!this.codemirror) { + return; + } + + this.codemirror + .getWrapperElement() + .classList.toggle("rtl", computeRTL(this._hass!)); + } } declare global { diff --git a/src/panels/lovelace/editor/card-editor/hui-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-edit-card.ts index 0022c045b2..1e08ff49dd 100644 --- a/src/panels/lovelace/editor/card-editor/hui-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-edit-card.ts @@ -119,6 +119,7 @@ export class HuiEditCard extends LitElement { ? this._configElement : html` diff --git a/src/panels/lovelace/hui-editor.ts b/src/panels/lovelace/hui-editor.ts index 87bdd6daed..f92de99ca8 100644 --- a/src/panels/lovelace/hui-editor.ts +++ b/src/panels/lovelace/hui-editor.ts @@ -18,6 +18,7 @@ import "./components/hui-yaml-editor"; // This is not a duplicate import, one is for types, one is for element. // tslint:disable-next-line import { HuiYamlEditor } from "./components/hui-yaml-editor"; +import { HomeAssistant } from "../../types"; const lovelaceStruct = struct.interface({ title: "string?", @@ -26,6 +27,7 @@ const lovelaceStruct = struct.interface({ }); class LovelaceFullConfigEditor extends LitElement { + public hass?: HomeAssistant; public lovelace?: Lovelace; public closeEditor?: () => void; private _saving?: boolean; @@ -34,6 +36,7 @@ class LovelaceFullConfigEditor extends LitElement { static get properties() { return { + hass: {}, lovelace: {}, _saving: {}, _changed: {}, @@ -62,6 +65,7 @@ class LovelaceFullConfigEditor extends LitElement {
@@ -102,7 +106,6 @@ class LovelaceFullConfigEditor extends LitElement { .content { height: calc(100vh - 68px); - direction: ltr; } hui-code-editor { From 9d6c0773c5c14318d0ffc8b046ac8ee43237f203 Mon Sep 17 00:00:00 2001 From: yosilevy <37745463+yosilevy@users.noreply.github.com> Date: Tue, 12 Feb 2019 00:40:09 +0200 Subject: [PATCH 03/66] Rtl configuration fixes (#2720) * RTL fixes to config pages * Disconnect toast RTL * RTL user editor - force LTR (only the user box - not the action box) * Many RTL fixes in configuration. Keeping scrollbar in RTL so it's not obstructed. Added missing localization. * Update disconnect-toast-mixin.ts --- src/layouts/app/disconnect-toast-mixin.ts | 10 ++++-- .../dialog-area-registry-detail.ts | 22 ++++++++++--- .../area_registry/ha-config-area-registry.ts | 14 ++++++--- .../config/automation/ha-automation-editor.ts | 13 +++++++- .../config/cloud/ha-config-cloud-account.js | 1 + .../cloud/ha-config-cloud-forgot-password.js | 1 + .../config/cloud/ha-config-cloud-login.js | 1 + .../config/cloud/ha-config-cloud-register.js | 4 +++ .../config/customize/ha-config-customize.js | 8 ++--- .../dialog-entity-registry-detail.ts | 14 +++++++-- .../ha-config-entity-registry.ts | 11 +++++-- src/panels/config/ha-entity-config.js | 1 + .../config/js/condition/numeric_state.js | 1 + src/panels/config/js/condition/template.js | 1 + src/panels/config/js/json_textarea.js | 1 + src/panels/config/js/script/wait.js | 1 + src/panels/config/js/trigger/numeric_state.js | 1 + src/panels/config/js/trigger/template.js | 1 + src/panels/config/users/ha-user-editor.js | 3 ++ src/translations/en.json | 31 +++++++++++++++++-- 20 files changed, 116 insertions(+), 24 deletions(-) diff --git a/src/layouts/app/disconnect-toast-mixin.ts b/src/layouts/app/disconnect-toast-mixin.ts index 70411c3a0b..2905ed40f6 100644 --- a/src/layouts/app/disconnect-toast-mixin.ts +++ b/src/layouts/app/disconnect-toast-mixin.ts @@ -1,13 +1,14 @@ import { Constructor, LitElement } from "lit-element"; import { HassBaseEl } from "./hass-base-mixin"; import { HaToast } from "../../components/ha-toast"; +import { computeRTL } from "../../common/util/compute_rtl"; export default (superClass: Constructor) => class extends superClass { private _discToast?: HaToast; - protected hassConnected() { - super.hassConnected(); + protected firstUpdated(changedProps) { + super.firstUpdated(changedProps); // Need to load in advance because when disconnected, can't dynamically load code. import(/* webpackChunkName: "ha-toast" */ "../../components/ha-toast"); } @@ -24,10 +25,13 @@ export default (superClass: Constructor) => if (!this._discToast) { const el = document.createElement("ha-toast"); el.duration = 0; - el.text = this.hass!.localize("ui.notification_toast.connection_lost"); this._discToast = el; this.shadowRoot!.appendChild(el as any); } + this._discToast.dir = computeRTL(this.hass!); + this._discToast.text = this.hass!.localize( + "ui.notification_toast.connection_lost" + ); this._discToast.opened = true; } }; diff --git a/src/panels/config/area_registry/dialog-area-registry-detail.ts b/src/panels/config/area_registry/dialog-area-registry-detail.ts index bf8e0d8425..6a777ba1f3 100644 --- a/src/panels/config/area_registry/dialog-area-registry-detail.ts +++ b/src/panels/config/area_registry/dialog-area-registry-detail.ts @@ -51,7 +51,13 @@ class DialogAreaDetail extends LitElement { opened @opened-changed="${this._openedChanged}" > -

${this._params.entry ? this._params.entry.name : "New Area"}

+

+ ${this._params.entry + ? this._params.entry.name + : this.hass.localize( + "ui.panel.config.area_registry.editor.default_name" + )} +

${this._error ? html` @@ -62,7 +68,7 @@ class DialogAreaDetail extends LitElement { @@ -76,7 +82,9 @@ class DialogAreaDetail extends LitElement { @click="${this._deleteEntry}" .disabled=${this._submitting} > - DELETE + ${this.hass.localize( + "ui.panel.config.area_registry.editor.delete" + )} ` : html``} @@ -84,7 +92,13 @@ class DialogAreaDetail extends LitElement { @click="${this._updateEntry}" .disabled=${nameInvalid || this._submitting} > - ${this._params.entry ? "UPDATE" : "CREATE"} + ${this._params.entry + ? this.hass.localize( + "ui.panel.config.area_registry.editor.update" + ) + : this.hass.localize( + "ui.panel.config.area_registry.editor.create" + )}
diff --git a/src/panels/config/area_registry/ha-config-area-registry.ts b/src/panels/config/area_registry/ha-config-area-registry.ts index 8fe412539e..43fb8bdc6f 100644 --- a/src/panels/config/area_registry/ha-config-area-registry.ts +++ b/src/panels/config/area_registry/ha-config-area-registry.ts @@ -50,7 +50,9 @@ class HaConfigAreaRegistry extends LitElement { return html` - Area Registry + + ${this.hass.localize("ui.panel.config.area_registry.picker.header")} + Areas are used to organize where devices are. This information will be used throughout Home Assistant to help you in organizing your @@ -74,10 +76,14 @@ class HaConfigAreaRegistry extends LitElement { ${this._items.length === 0 ? html`
- Looks like you have no areas yet! + ${this.hass.localize( + "ui.panel.config.area_registry.picker.no_areas" + )} - CREATE AREA + ${this.hass.localize( + "ui.panel.config.area_registry.picker.create_area" + )} +
` : html``} diff --git a/src/panels/config/automation/ha-automation-editor.ts b/src/panels/config/automation/ha-automation-editor.ts index 4d00ececa8..02d50e67f5 100644 --- a/src/panels/config/automation/ha-automation-editor.ts +++ b/src/panels/config/automation/ha-automation-editor.ts @@ -11,6 +11,7 @@ import "@polymer/app-layout/app-header/app-header"; import "@polymer/app-layout/app-toolbar/app-toolbar"; import "@polymer/paper-icon-button/paper-icon-button"; import "@polymer/paper-fab/paper-fab"; +import { classMap } from "lit-html/directives/class-map"; import { h, render } from "preact"; @@ -24,6 +25,7 @@ import { haStyle } from "../../../resources/ha-style"; import { HomeAssistant } from "../../../types"; import { AutomationEntity, AutomationConfig } from "../../../data/automation"; import { navigate } from "../../../common/navigate"; +import { computeRTL } from "../../../common/util/compute_rtl"; function AutomationEditor(mountEl, props, mergeEl) { return render(h(Automation, props), mountEl, mergeEl); @@ -92,7 +94,12 @@ class HaAutomationEditor extends LitElement {
${this._errors}
` : ""} -
+
.content { padding-bottom: 24px; + direction: ltr; } paper-card { diff --git a/src/panels/config/cloud/ha-config-cloud-login.js b/src/panels/config/cloud/ha-config-cloud-login.js index 549569ee7c..17a47c497d 100644 --- a/src/panels/config/cloud/ha-config-cloud-login.js +++ b/src/panels/config/cloud/ha-config-cloud-login.js @@ -26,6 +26,7 @@ class HaConfigCloudLogin extends NavigateMixin(EventsMixin(PolymerElement)) { diff --git a/src/translations/en.json b/src/translations/en.json index 56f68e88d4..01aca9f1e3 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -530,7 +530,18 @@ "introduction": "Here it is possible to configure your components and Home Assistant. Not everything is possible to configure from the UI yet, but we're working on it.", "area_registry": { "caption": "Area Registry", - "description": "Overview of all areas in your home." + "description": "Overview of all areas in your home.", + "picker": { + "header": "Area Registry" + }, + "no_areas": "Looks like you have no areas yet!", + "create_area": "CREATE AREA", + "editor": { + "default_name": "New Area", + "delete": "DELETE", + "update": "UPDATE", + "create": "CREATE" + } }, "core": { "caption": "General", @@ -565,7 +576,11 @@ }, "customize": { "caption": "Customization", - "description": "Customize your entities" + "description": "Customize your entities", + "picker": { + "header": "Customization", + "introduction": "Tweak per-entity attributes. Added/edited customizations will take effect immediately. Removed customizations will take effect when the entity is updated." + } }, "automation": { "caption": "Automation", @@ -755,7 +770,17 @@ }, "entity_registry": { "caption": "Entity Registry", - "description": "Overview of all known entities." + "description": "Overview of all known entities.", + "picker": { + "header": "Entity Registry", + "unavailable": "(unavailable)" + }, + "editor": { + "unavailable": "This entity is not currently available.", + "default_name": "New Area", + "delete": "DELETE", + "update": "UPDATE" + } }, "person": { "caption": "People", From 5cc23ab084d7fe228a7e81ebd7a3ef89a3e10c42 Mon Sep 17 00:00:00 2001 From: aquarium Date: Mon, 11 Feb 2019 17:45:05 -0500 Subject: [PATCH 04/66] Update Store Auth card to use primary-text-color (#2725) --- src/dialogs/ha-store-auth-card.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/dialogs/ha-store-auth-card.js b/src/dialogs/ha-store-auth-card.js index 9284e175f0..2fb802650a 100644 --- a/src/dialogs/ha-store-auth-card.js +++ b/src/dialogs/ha-store-auth-card.js @@ -18,6 +18,10 @@ class HaStoreAuth extends LocalizeMixin(PolymerElement) { right: 16px; } + .card-content { + color: var(--primary-text-color); + } + .card-actions { text-align: right; border-top: 0; From f71612d6cfc5059f7eccc9f2e5a439c253c74eb8 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 11 Feb 2019 23:40:15 -0800 Subject: [PATCH 05/66] Update translations --- translations/ca.json | 14 +++- translations/cs.json | 27 +++++- translations/da.json | 73 ++++++++++++++-- translations/de.json | 17 +++- translations/el.json | 36 +++++++- translations/es.json | 37 ++++++++- translations/fr.json | 49 ++++++++++- translations/he.json | 16 ++-- translations/hu.json | 18 ++-- translations/it.json | 51 ++++++++++-- translations/ko.json | 10 +-- translations/lb.json | 15 ++-- translations/lt.json | 18 +++- translations/nl.json | 45 ++++++++-- translations/pl.json | 14 +++- translations/pt.json | 61 ++++++++++++-- translations/ru.json | 2 +- translations/sk.json | 46 +++++++--- translations/uk.json | 171 ++++++++++++++++++++++++++++++++++---- translations/zh-Hans.json | 36 +++++++- 20 files changed, 656 insertions(+), 100 deletions(-) diff --git a/translations/ca.json b/translations/ca.json index 4e1ac7db7f..a341c12cc5 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -301,7 +301,8 @@ "period": "Període" }, "logbook": { - "showing_entries": "Mostrant entrades de" + "showing_entries": "Mostrant entrades de", + "period": "Període" }, "mailbox": { "empty": "No tens missatges", @@ -789,10 +790,16 @@ "para_sure": "Estàs segur que vols prendre el control de la interfície d'usuari?", "cancel": "M'ho he repensat", "save": "Prendre el control" + }, + "menu": { + "raw_editor": "Editor de codi" } }, "menu": { - "configure_ui": "Configurar la interfície d'usuari" + "configure_ui": "Configurar la interfície d'usuari", + "unused_entities": "Entitats sense utilitzar", + "help": "Ajuda", + "refresh": "Actualitzar" } } }, @@ -1028,7 +1035,8 @@ "zha": "ZHA", "hassio": "Hass.io", "homeassistant": "Home Assistant", - "lovelace": "Lovelace" + "lovelace": "Lovelace", + "system_health": "Estat del sistema" }, "attribute": { "weather": { diff --git a/translations/cs.json b/translations/cs.json index 1aa8ddb202..3812fff1e2 100644 --- a/translations/cs.json +++ b/translations/cs.json @@ -427,6 +427,10 @@ "webhook": { "label": "Webhook", "webhook_id": "Webhook ID" + }, + "geo_location": { + "label": "Geolokace", + "zone": "Zóna" } } }, @@ -556,6 +560,12 @@ "device_unavailable": "zařízení není k dispozici", "entity_unavailable": "entita není k dispozici" } + }, + "zha": { + "caption": "ZHA" + }, + "area_registry": { + "description": "Přehled všech oblastí ve vaší domácnosti." } }, "profile": { @@ -758,7 +768,9 @@ } }, "menu": { - "configure_ui": "Konfigurovat UI" + "configure_ui": "Konfigurovat UI", + "help": "Pomoc", + "refresh": "Obnovit" } } }, @@ -928,6 +940,14 @@ "save": "Uložit", "name": "Název", "entity_id": "Entity ID" + }, + "more_info_control": { + "script": { + "last_action": "Poslední akce" + }, + "updater": { + "title": "Pokyny pro aktualizaci" + } } }, "auth_store": { @@ -978,7 +998,10 @@ "weblink": "Webový odkaz", "zwave": "Z-Wave", "vacuum": "Vysavač", - "zha": "ZHA" + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace" }, "attribute": { "weather": { diff --git a/translations/da.json b/translations/da.json index c646247b8a..d2bc987dd3 100644 --- a/translations/da.json +++ b/translations/da.json @@ -301,7 +301,8 @@ "period": "Periode" }, "logbook": { - "showing_entries": "Viser emner for" + "showing_entries": "Viser emner for", + "period": "Periode" }, "mailbox": { "empty": "Du har ingen beskeder", @@ -420,13 +421,27 @@ "label": "Zone", "entity": "Enhed med placering", "zone": "Zone", - "event": "Begivenhed", + "event": "Begivenhed:", "enter": "Ankom", "leave": "Forlade" }, "webhook": { "label": "Webhook", "webhook_id": "Webhook-ID" + }, + "time_pattern": { + "label": "Tidsmønster", + "hours": "Timer", + "minutes": "Minutter", + "seconds": "Sekunder" + }, + "geo_location": { + "label": "Geolokation", + "source": "Kilde", + "zone": "Zone", + "event": "Begivenhed", + "enter": "Ankommer", + "leave": "Forlad" } } }, @@ -437,7 +452,7 @@ "duplicate": "Kopier", "delete": "Slet", "delete_confirm": "Er du sikker på du vil slette?", - "unsupported_condition": "Ikke-understøttet betingelse: {betingelse}", + "unsupported_condition": "Ikke-understøttet betingelse: {condition}", "type_select": "Betingelsestype", "type": { "state": { @@ -448,7 +463,7 @@ "label": "Numerisk stadie", "above": "Over", "below": "Under", - "value_template": "Værdi skabelon (ikke krævet)" + "value_template": "Værdi skabelon (valgfri)" }, "sun": { "label": "Sol", @@ -556,12 +571,27 @@ "device_unavailable": "enhed utilgængelig", "entity_unavailable": "entitet utilgængelig" } + }, + "zha": { + "caption": "ZHA", + "description": "Zigbee Home Automation opsætning", + "services": { + "reconfigure": "Genkonfigurer ZHA-enhed (helbred enhed). Brug dette hvis du har problemer med enheden. Hvis den pågældende enhed er en batteridrevet enhed skal du sørge for at den er vågen og accepterer kommandoer når du bruger denne service." + } + }, + "area_registry": { + "caption": "Område registrering", + "description": "Oversigt over alle områder i dit hjem." + }, + "entity_registry": { + "caption": "Enheds registrering", + "description": "Oversigt over alle kendte enheder." } }, "profile": { "push_notifications": { "header": "Push notifikationer", - "description": "Send meddelelser til denne enhed", + "description": "Send meddelelser til denne enhed.", "error_load_platform": "Konfigurer notify.html5", "error_use_https": "Kræver SSL aktiveret til frontend.", "push_notifications": "Push-meddelelser", @@ -724,6 +754,11 @@ "checked_items": "Markerede elementer", "clear_items": "Ryd markerede elementer", "add_item": "Tilføj element" + }, + "empty_state": { + "title": "Velkommen hjem", + "no_devices": "Denne side giver dig mulighed for at styre dine enheder, men det ser ud til, at du endnu ikke har konfigureret enheder. Gå til integrationssiden for at komme i gang.", + "go_to_integrations_page": "Gå til integrationssiden." } }, "editor": { @@ -755,10 +790,16 @@ "para_sure": "Er du sikker på du ønsker at tage kontrol over din brugergrænseflade?", "cancel": "Glem det", "save": "tag kontrol" + }, + "menu": { + "raw_editor": "Tekstbaseret redigering" } }, "menu": { - "configure_ui": "Konfigurer UI" + "configure_ui": "Konfigurer UI", + "unused_entities": "Ubrugte enheder", + "help": "Hjælp", + "refresh": "Opdater" } } }, @@ -928,6 +969,19 @@ "save": "Gem", "name": "Navn", "entity_id": "Enheds ID" + }, + "more_info_control": { + "script": { + "last_action": "Senest udløst" + }, + "sun": { + "elevation": "Elevation", + "rising": "Solopgang", + "setting": "Indstilling" + }, + "updater": { + "title": "Opdateringsvejledning" + } } }, "auth_store": { @@ -977,7 +1031,12 @@ "updater": "Opdater", "weblink": "Link", "zwave": "Z-Wave", - "vacuum": "Støvsuger" + "vacuum": "Støvsuger", + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "System sundhed" }, "attribute": { "weather": { diff --git a/translations/de.json b/translations/de.json index f716c40018..caacb550f7 100644 --- a/translations/de.json +++ b/translations/de.json @@ -433,6 +433,11 @@ "hours": "Stunden", "minutes": "Minuten", "seconds": "Sekunden" + }, + "geo_location": { + "source": "Quelle", + "enter": "Betrenten", + "leave": "Verlassen" } } }, @@ -566,6 +571,9 @@ "zha": { "caption": "ZHA", "description": "Zigbee Home Automation Netzwerkmanagement" + }, + "entity_registry": { + "description": "Überblick aller bekannten Elemente." } }, "profile": { @@ -734,6 +742,9 @@ "checked_items": "Markierte Artikel", "clear_items": "Markierte Elemente löschen", "add_item": "Artikel hinzufügen" + }, + "empty_state": { + "title": "Willkommen zu Hause" } }, "editor": { @@ -768,7 +779,9 @@ } }, "menu": { - "configure_ui": "Benutzeroberfläche konfigurieren" + "configure_ui": "Benutzeroberfläche konfigurieren", + "unused_entities": "Ungenutzte Elemente", + "help": "Hilfe" } } }, @@ -946,7 +959,7 @@ "sun": { "elevation": "Höhe", "rising": "Aufgehend", - "setting": "Einstellung" + "setting": "Untergang" }, "updater": { "title": "Update-Anweisungen" diff --git a/translations/el.json b/translations/el.json index 5e5e7b7cb4..1a3cc56a83 100644 --- a/translations/el.json +++ b/translations/el.json @@ -301,7 +301,8 @@ "period": "Περίοδος" }, "logbook": { - "showing_entries": "Εμφανίζοντα καταχωρήσεις για" + "showing_entries": "Εμφανίζοντα καταχωρήσεις για", + "period": "Περίοδος" }, "mailbox": { "empty": "Δεν έχετε μηνύματα", @@ -433,6 +434,13 @@ "hours": "Ώρες", "minutes": "Λεπτά", "seconds": "Δευτερόλεπτα" + }, + "geo_location": { + "label": "Γεωγραφική θέση", + "source": "Πηγή", + "zone": "Ζώνη", + "enter": "Είσοδος", + "leave": "Αποχώρηση" } } }, @@ -556,7 +564,7 @@ "no_device": "Οντότητες χωρίς συσκευές", "delete_confirm": "Είστε σίγουρος ότι θέλετε να διαγραφεί αυτή η ενοποίηση;", "restart_confirm": "Επανεκκινήστε το Home Assistant για να ολοκληρώσετε την κατάργηση αυτής της ενοποίησης", - "manuf": "από {κατασκευαστής}", + "manuf": "από {manufacturer}", "hub": "Συνδεδεμένο μέσω", "firmware": "Υλικολογισμικό: {έκδοση}", "device_unavailable": "συσκευή μη διαθέσιμη", @@ -566,6 +574,14 @@ "zha": { "caption": "ZHA", "description": "Διαχείριση του δικτύου ZigBee Home Automation" + }, + "area_registry": { + "caption": "Περιοχή Μητρώου", + "description": "Επισκόπηση όλων των περιοχών στο σπίτι σας." + }, + "entity_registry": { + "caption": "Μητρώο οντοτήτων", + "description": "Επισκόπηση όλων των γνωστών οντοτήτων." } }, "profile": { @@ -734,6 +750,11 @@ "checked_items": "Επιλεγμένα στοιχεία", "clear_items": "Εκκαθάριση επιλεγμένων στοιχείων", "add_item": "Προσθήκη στοιχείου" + }, + "empty_state": { + "title": "Καλωσορίσατε στην αρχική σελίδα", + "no_devices": "Αυτή η σελίδα σάς επιτρέπει να ελέγχετε τις συσκευές σας, ωστόσο φαίνεται ότι δεν έχετε ακόμα ρυθμίσει συσκευές. Μεταβείτε στη σελίδα ενοποίησης για να ξεκινήσετε.", + "go_to_integrations_page": "Μεταβείτε στη σελίδα ενοποίησης." } }, "editor": { @@ -768,7 +789,10 @@ } }, "menu": { - "configure_ui": "Διαμορφώστε το περιβάλλον χρήστη" + "configure_ui": "Διαμορφώστε το περιβάλλον χρήστη", + "unused_entities": "Αχρησιμοποίητες οντότητες", + "help": "Βοήθεια", + "refresh": "Ανανέωση" } } }, @@ -1001,7 +1025,11 @@ "weblink": "Σύνδεσμος", "zwave": "Z-Wave", "vacuum": "Εκκένωση ", - "zha": "ΖΗΑ" + "zha": "ΖΗΑ", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "Υγεία Συστήματος" }, "attribute": { "weather": { diff --git a/translations/es.json b/translations/es.json index 977ee77bf4..4e28024f72 100644 --- a/translations/es.json +++ b/translations/es.json @@ -301,7 +301,8 @@ "period": "Periodo" }, "logbook": { - "showing_entries": "Mostrando entradas del" + "showing_entries": "Mostrando entradas del", + "period": "Periodo" }, "mailbox": { "empty": "No tiene ningún mensaje", @@ -433,6 +434,14 @@ "hours": "Horas", "minutes": "Minutos", "seconds": "Segundos" + }, + "geo_location": { + "label": "Geolocalización", + "source": "Fuente", + "zone": "Zona", + "event": "Evento:", + "enter": "Entrar", + "leave": "Salir" } } }, @@ -566,6 +575,14 @@ "zha": { "caption": "ZHA", "description": "Gestión de red de Zigbee Home Automation" + }, + "area_registry": { + "caption": "Registro de área", + "description": "Visión general de todas las áreas de tu casa." + }, + "entity_registry": { + "caption": "Registro de Entidades", + "description": "Resumen de todas las entidades conocidas." } }, "profile": { @@ -734,6 +751,10 @@ "checked_items": "Elementos marcados", "clear_items": "Borrar elementos marcados", "add_item": "Añadir artículo" + }, + "empty_state": { + "title": "Bienvenido a casa", + "go_to_integrations_page": "Ir a la página de integraciones." } }, "editor": { @@ -765,10 +786,16 @@ "para_sure": "¿Está seguro de que desea tomar el control de su interfaz de usuario?", "cancel": "No importa", "save": "Tomar el control" + }, + "menu": { + "raw_editor": "Editor de configuración en bruto" } }, "menu": { - "configure_ui": "Configurar la interfaz de usuario" + "configure_ui": "Configurar la interfaz de usuario", + "unused_entities": "Entidades no utilizadas", + "help": "Ayuda", + "refresh": "Refrescar" } } }, @@ -1001,7 +1028,11 @@ "weblink": "Enlace web", "zwave": "Z-Wave", "vacuum": "Aspiradora", - "zha": "ZHA" + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "Salud del sistema" }, "attribute": { "weather": { diff --git a/translations/fr.json b/translations/fr.json index 07d65addcb..3e93ff16a6 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -301,7 +301,8 @@ "period": "Période" }, "logbook": { - "showing_entries": "Afficher les entrées pour le" + "showing_entries": "Afficher les entrées pour le", + "period": "Période" }, "mailbox": { "empty": "Vous n'avez aucun message", @@ -433,6 +434,14 @@ "hours": "Heures", "minutes": "Minutes", "seconds": "Secondes" + }, + "geo_location": { + "label": "Géolocalisation", + "source": "Source", + "zone": "Zone", + "event": "Événement :", + "enter": "Entre", + "leave": "Quitte" } } }, @@ -562,6 +571,21 @@ "device_unavailable": "appareil indisponible", "entity_unavailable": "entité indisponible" } + }, + "zha": { + "caption": "ZHA", + "description": "Gestion de réseau domotique ZigBee", + "services": { + "reconfigure": "Reconfigurer le périphérique ZHA. Utilisez cette option si vous rencontrez des problèmes avec le périphérique. Si l'appareil en question est un appareil alimenté par batterie, assurez-vous qu'il soit allumé et qu'il accepte les commandes lorsque vous utilisez ce service." + } + }, + "area_registry": { + "caption": "Registre des pièces", + "description": "Vue d'ensemble de toutes les pièces de votre maison." + }, + "entity_registry": { + "caption": "Registre des entités", + "description": "Vue d'ensemble de toutes les entités connues." } }, "profile": { @@ -730,6 +754,11 @@ "checked_items": "Éléments cochés", "clear_items": "Effacer éléments cochés", "add_item": "Ajouter un élément" + }, + "empty_state": { + "title": "Bienvenue à la maison", + "no_devices": "Cette page vous permet de contrôler vos périphériques. Toutefois, il semble que vous n’ayez pas encore configuré de périphériques. Rendez-vous sur la page des intégrations pour commencer.", + "go_to_integrations_page": "Aller à la page des intégrations." } }, "editor": { @@ -761,10 +790,16 @@ "para_sure": "Êtes-vous sûr de vouloir prendre le controle de l'interface utilisateur?", "cancel": "Oublie ce que j'ai dit, c'est pas grave.", "save": "Prenez le contrôle" + }, + "menu": { + "raw_editor": "Éditeur de configuration" } }, "menu": { - "configure_ui": "Configurer l'interface utilisateur" + "configure_ui": "Configurer l'interface utilisateur", + "unused_entities": "Entités inutilisées", + "help": "Aide", + "refresh": "Actualiser" } } }, @@ -941,7 +976,8 @@ }, "sun": { "elevation": "Élévation", - "rising": "Lever" + "rising": "Lever", + "setting": "Coucher" }, "updater": { "title": "Instructions de mise à jour" @@ -995,7 +1031,12 @@ "updater": "Mise à jour", "weblink": "Lien", "zwave": "Z-Wave", - "vacuum": "Aspirateur" + "vacuum": "Aspirateur", + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "Santé du système" }, "attribute": { "weather": { diff --git a/translations/he.json b/translations/he.json index 204ca0327c..362981d2e2 100644 --- a/translations/he.json +++ b/translations/he.json @@ -353,20 +353,20 @@ "description": "צור וערוך אוטומציות", "picker": { "header": "עורך אוטומציה", - "introduction": "עורך אוטומציה מאפשר לך ליצור ולערוך אוטומציה. אנא קרא את [ההוראות] (https:\/\/home-assistant.io\/docs\/automation\/editor\/) כדי לוודא שהגדרת את ה - Home Assistant כהלכה.", + "introduction": "עורך אוטומציה מאפשר לך ליצור ולערוך אוטומציות. אנא קרא את [ההוראות](https:\/\/home-assistant.io\/docs\/automation\/editor\/) כדי לוודא שהגדרת את ה - Home Assistant כהלכה.", "pick_automation": "בחר אוטומציה לעריכה", "no_automations": "לא הצלחנו למצוא שום אוטומציה הניתנת לעריכה", "add_automation": "הוסף אוטומציה" }, "editor": { - "introduction": "השתמש אוטומציות להביא את החיים לבית שלך", + "introduction": "השתמש באוטומציות להביא את הבית שלך לחיים", "default_name": "אוטומציה חדשה", "save": "שמור", "unsaved_confirm": "יש לך שינויים שלא נשמרו. אתה בטוח שאתה רוצה לעזוב?", "alias": "שם", "triggers": { "header": "טריגרים", - "introduction": "טריגרים הם מה שמתחיל כל אוטומציה. ניתן לציין מספר טריגרים עבור אותו כלל. לאחר הפעלת טריגר, ה - Assistant Assistant יאמת את התנאים, אם קיימים, ויקרא לפעולה. \n\n [למידע נוסף על גורמים טריגרים.) (Https:\/\/home-assistant.io\/docs\/automation\/trigger\/)", + "introduction": "טריגרים הם מה שמתחיל כל אוטומציה. ניתן לציין מספר טריגרים עבור אותו כלל. לאחר הפעלת טריגר, ה - Home Assistant יאמת את התנאים, אם קיימים, ויקרא לפעולה. \n\n[למד עוד על טריגרים](https:\/\/home-assistant.io\/docs\/automation\/trigger\/)", "add": "הוספת טריגר", "duplicate": "שכפל", "delete": "מחק", @@ -447,7 +447,7 @@ }, "conditions": { "header": "תנאים", - "introduction": "התנאים הם חלק אופציונלי של כלל אוטומציה, וניתן להשתמש בהם כדי למנוע פעולה כלשהי בעת הפעלתה. התנאים נראים דומים מאוד לטריגרים אך הם שונים מאוד. הטריגר יסתכל על האירועים המתרחשים במערכת בעוד תנאי רק מסתכל על איך המערכת נראית עכשיו. הטריגר יכול שמתג נדלק. תנאי יכול לראות רק אם מתג מופעל או כבוי. \n\n [למידע נוסף על תנאים.] (Https:\/\/home-assistant.io\/docs\/scripts\/conditions\/)", + "introduction": "התנאים הם חלק אופציונלי של כלל אוטומציה, וניתן להשתמש בהם כדי למנוע פעולה כלשהי בעת הפעלתה. התנאים נראים דומים מאוד לטריגרים אך הם שונים מאוד. הטריגר יסתכל על האירועים המתרחשים במערכת בעוד תנאי רק מסתכל על איך המערכת נראית עכשיו. הטריגר יכול שמתג נדלק. תנאי יכול לראות רק אם מתג מופעל או כבוי. \n\n[למידע נוסף על תנאים](Https:\/\/home-assistant.io\/docs\/scripts\/conditions\/)", "add": "הוסף תנאי", "duplicate": "שכפל", "delete": "מחק", @@ -492,7 +492,7 @@ }, "actions": { "header": "פעולות", - "introduction": "הפעולות הן מה שHome Assistant יעשה כאשר אוטומציה מופעלת. \n\n [למידע נוסף על פעולות.] (https:\/\/home-assistant.io\/docs\/automation\/action\/)", + "introduction": "הפעולות הן מה שHome Assistant יעשה כאשר אוטומציה מופעלת. \n\n[למידע נוסף על פעולות](https:\/\/home-assistant.io\/docs\/automation\/action\/)", "add": "הוסף פעולה", "duplicate": "שכפל", "delete": "מחק", @@ -506,7 +506,7 @@ }, "delay": { "label": "עיכוב", - "delay": "עיקוב" + "delay": "עיכוב" }, "wait_template": { "label": "לחכות", @@ -517,7 +517,7 @@ "label": "תנאי" }, "event": { - "label": "אירוע אש", + "label": "ירה אירוע", "event": "ארוע", "service_data": "נתוני שירות" } @@ -557,7 +557,7 @@ "description": "ניהול התקנים ושירותים מחוברים", "discovered": "זוהו", "configured": "הוגדר", - "new": "הגדר אינטגריצה", + "new": "הגדר אינטגרציה", "configure": "הגדר", "none": "כלום אינו הוגדר עדיין", "config_entry": { diff --git a/translations/hu.json b/translations/hu.json index 7f99f3fcf0..e3bc5bbf51 100644 --- a/translations/hu.json +++ b/translations/hu.json @@ -576,10 +576,12 @@ "description": "Zigbee Home Automation hálózat menedzsment" }, "area_registry": { - "description": "Az összes otthoni terület áttekintése." + "caption": "Terület Nyilvántartás", + "description": "Az összes otthoni terület áttekintése" }, "entity_registry": { - "description": "Az összes ismert entitás áttekintése." + "caption": "Entitás Nyilvántartás", + "description": "Az összes ismert entitás áttekintése" } }, "profile": { @@ -750,7 +752,9 @@ "add_item": "Tétel hozzáadása" }, "empty_state": { - "title": "Üdv Itthon" + "title": "Üdv Itthon", + "no_devices": "Ez az oldal lehetővé teszi az eszközeid vezérlését, de úgy tűnik, hogy még nincs beállítva egy sem. A kezdéshez lépj át az integrációs oldalra.", + "go_to_integrations_page": "Ugrás az 'integrációk' oldalra." } }, "editor": { @@ -782,6 +786,9 @@ "para_sure": "Biztosan át szeretnéd venni az irányítást a felhasználói felületed felett?", "cancel": "Mégsem", "save": "Irányítás átvétele" + }, + "menu": { + "raw_editor": "Konfiguráció szerkesztő" } }, "menu": { @@ -956,7 +963,7 @@ "dialogs": { "more_info_settings": { "save": "Mentés", - "name": "Név", + "name": "Név felülbírálása", "entity_id": "Entitás ID" }, "more_info_control": { @@ -1024,7 +1031,8 @@ "zha": "ZHA", "hassio": "Hass.io", "homeassistant": "Home Assistant", - "lovelace": "Lovelace" + "lovelace": "Lovelace", + "system_health": "Rendszer Állapot" }, "attribute": { "weather": { diff --git a/translations/it.json b/translations/it.json index 91f0762f5f..abba80f194 100644 --- a/translations/it.json +++ b/translations/it.json @@ -301,7 +301,8 @@ "period": "Periodo" }, "logbook": { - "showing_entries": "Mostra registrazioni per" + "showing_entries": "Mostra registrazioni per", + "period": "Periodo" }, "mailbox": { "empty": "Non hai nessun messaggio", @@ -426,13 +427,21 @@ }, "webhook": { "label": "Webhook", - "webhook_id": "ID Webhook" + "webhook_id": "Webhook ID" }, "time_pattern": { "label": "Pattern temporale", "hours": "Ore", "minutes": "Minuti", "seconds": "Secondi" + }, + "geo_location": { + "label": "Geolocalizzazione", + "source": "Fonte", + "zone": "Zona", + "event": "Evento:", + "enter": "Ingresso", + "leave": "Uscita" } } }, @@ -544,7 +553,7 @@ "description_not_login": "Accesso non effettuato" }, "integrations": { - "caption": "integrazioni", + "caption": "Integrazioni", "description": "Gestisci dispositivi e servizi connessi", "discovered": "Scoperto", "configured": "Configurato", @@ -565,7 +574,18 @@ }, "zha": { "caption": "ZHA", - "description": "Gestione rete Zigbee Home Automation" + "description": "Gestione rete Zigbee Home Automation", + "services": { + "reconfigure": "Riconfigurare il dispositivo ZHA (dispositivo di guarigione). Utilizzare questa opzione se si verificano problemi con il dispositivo. Se il dispositivo in questione è un dispositivo alimentato a batteria, assicurarsi che sia sveglio e che accetti i comandi quando si utilizza questo servizio." + } + }, + "area_registry": { + "caption": "Registro di area", + "description": "Panoramica di tutte le aree della tua casa." + }, + "entity_registry": { + "caption": "Registro delle entità", + "description": "Panoramica di tutte le entità conosciute." } }, "profile": { @@ -702,7 +722,7 @@ "data": { "user": "Utente" }, - "description": "Perfavore, scegli l'utente con cui vuoi effettuare l'accesso:" + "description": "Per favore, scegli l'utente con cui vuoi effettuare l'accesso:" } }, "abort": { @@ -734,6 +754,11 @@ "checked_items": "Elementi selezionati", "clear_items": "Cancella gli elementi selezionati", "add_item": "Aggiungi elemento" + }, + "empty_state": { + "title": "Benvenuto a casa", + "no_devices": "Questa pagina ti consente di controllare i tuoi dispositivi, tuttavia sembra che tu non abbia ancora configurato uno. Vai alla pagina delle integrazioni per iniziare.", + "go_to_integrations_page": "Vai alla pagina delle integrazioni." } }, "editor": { @@ -765,10 +790,16 @@ "para_sure": "Sei sicuro di voler prendere il controllo della tua interfaccia utente?", "cancel": "Rinuncia", "save": "Prendere il controllo" + }, + "menu": { + "raw_editor": "Editor di configurazione grezzo" } }, "menu": { - "configure_ui": "Configurare l'interfaccia utente" + "configure_ui": "Configurare l'interfaccia utente", + "unused_entities": "Entità non utilizzate", + "help": "Aiuto", + "refresh": "Aggiorna" } } }, @@ -936,7 +967,7 @@ "dialogs": { "more_info_settings": { "save": "Salva", - "name": "Nome", + "name": "Sovrascrittura del nome", "entity_id": "ID Entità" }, "more_info_control": { @@ -1001,7 +1032,11 @@ "weblink": "Link Web", "zwave": "Z-Wave", "vacuum": "Aspirapolvere", - "zha": "ZHA" + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "Salute del sistema" }, "attribute": { "weather": { diff --git a/translations/ko.json b/translations/ko.json index 1d3acfe9e4..95e3a7a126 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -312,7 +312,7 @@ }, "config": { "header": "Home Assistant 설정", - "introduction": "여기에서 구성요소와 Home Assistant를 설정 할 수 있습니다. 아직 여기서 모두 설정 할 수는 없지만, 곧 구현되도록 작업 중입니다", + "introduction": "여기에서 구성요소와 Home Assistant 를 설정 할 수 있습니다. 아직 여기서 모두 설정 할 수는 없지만, 곧 구현되도록 작업 중입니다", "core": { "caption": "일반", "description": "설정 파일의 유효성을 검사하고 서버를 제어합니다", @@ -329,7 +329,7 @@ }, "reloading": { "heading": "설정 새로고침", - "introduction": "Home Assistant의 일부 설정은 재시작 없이 다시 읽어들일 수 있습니다. 새로고침을 누르면 현재 구성을 내리고 새로운 설정 내용을 읽어들입니다", + "introduction": "Home Assistant 의 일부 설정은 재시작 없이 다시 읽어들일 수 있습니다. 새로고침을 누르면 현재 구성을 내리고 새로운 설정 내용을 읽어들입니다", "core": "코어 새로고침", "group": "그룹 새로고침", "automation": "자동화 새로고침", @@ -366,7 +366,7 @@ "alias": "이름", "triggers": { "header": "트리거", - "introduction": "트리거는 자동화 규칙을 처리하는 시작점 입니다. 같은 자동화 규칙에 여러 개의 트리거를 지정할 수 있습니다. 트리거가 발동되면 Home Assistant는 조건을 확인하고 동작을 호출합니다. \n\n[트리거에 대해 자세히 알아보기](https:\/\/home-assistant.io\/docs\/automation\/trigger\/)", + "introduction": "트리거는 자동화 규칙을 처리하는 시작점 입니다. 같은 자동화 규칙에 여러 개의 트리거를 지정할 수 있습니다. 트리거가 발동되면 Home Assistant 는 조건을 확인하고 동작을 호출합니다. \n\n[트리거에 대해 자세히 알아보기](https:\/\/home-assistant.io\/docs\/automation\/trigger\/)", "add": "트리거 추가", "duplicate": "복제", "delete": "삭제", @@ -492,7 +492,7 @@ }, "actions": { "header": "동작", - "introduction": "동작은 자동화가 트리거 될 때 Home Assistant가 수행할 작업입니다.\n\n [동작에 대해 자세히 알아보기](https:\/\/home-assistant.io\/docs\/automation\/action\/)", + "introduction": "동작은 자동화가 트리거 될 때 Home Assistant 가 수행할 작업입니다.\n\n [동작에 대해 자세히 알아보기](https:\/\/home-assistant.io\/docs\/automation\/action\/)", "add": "동작 추가", "duplicate": "복제", "delete": "삭제", @@ -561,7 +561,7 @@ "configure": "설정하기", "none": "설정된 구성요소가 없습니다", "config_entry": { - "no_devices": "이 통합 구성요소에는 장치가 없습니다.", + "no_devices": "이 통합 구성요소는 설정해야 할 장치가 없습니다.", "no_device": "장치가 없는 구성요소", "delete_confirm": "이 통합 구성요소를 제거 하시겠습니까?", "restart_confirm": "통합 구성요소 제거 완료를 위해 Home Assistant 를 재시작합니다", diff --git a/translations/lb.json b/translations/lb.json index 561a143457..ed17fcbb04 100644 --- a/translations/lb.json +++ b/translations/lb.json @@ -301,7 +301,8 @@ "period": "Zäitraum" }, "logbook": { - "showing_entries": "Weist Beiträg fir" + "showing_entries": "Weist Beiträg fir", + "period": "Zäitraum" }, "mailbox": { "empty": "Dir hutt keng Noriicht", @@ -317,7 +318,7 @@ "description": "Konfiguratioun validéieren an de Server kontrolléieren", "section": { "core": { - "header": "Konfiguracja i konktrola serwera", + "header": "Konfiguratioun an Server Kontroll", "introduction": "D'Ännere vun der Konfiguratioun kann e lästege Prozess sinn. Mir wëssen dat. Dës Sektioun probéiert fir Äert Liewen e bësse méi einfach ze maachen.", "validation": { "heading": "Validatioun vun der Konfiguratioun", @@ -757,7 +758,7 @@ "empty_state": { "title": "Wëllkomm Doheem", "no_devices": "Dës Säit erlaabt et iech är Apparater ze kontrolléiere, awer wéi et schéngt sinn nach keng Apparater ageriicht. Gitt op d'Integratioun's Säit fir unzefänken.", - "go_to_integrations_page": "Zur Integratiouns Säit goen" + "go_to_integrations_page": "Zur Integratiouns Säit goen" } }, "editor": { @@ -792,7 +793,10 @@ } }, "menu": { - "configure_ui": "UI konfiguréieren" + "configure_ui": "UI konfiguréieren", + "unused_entities": "Onbenotzt Entitéiten", + "help": "Hëllef", + "refresh": "Erneieren" } } }, @@ -1028,7 +1032,8 @@ "zha": "ZHA", "hassio": "Hass.io", "homeassistant": "Home Assistant", - "lovelace": "Lovelace" + "lovelace": "Lovelace", + "system_health": "System Zoustand" }, "attribute": { "weather": { diff --git a/translations/lt.json b/translations/lt.json index 9174cf8938..b12f36e64e 100644 --- a/translations/lt.json +++ b/translations/lt.json @@ -61,11 +61,27 @@ } } } + }, + "lovelace": { + "cards": { + "empty_state": { + "go_to_integrations_page": "Į integracijų puslapį" + } + }, + "menu": { + "unused_entities": "Nepanaudoti elementai", + "help": "Pagalba", + "refresh": "Atnaujinti" + } + }, + "logbook": { + "period": "Laikotarpis" } } }, "domain": { - "zwave": "Z-Wave" + "zwave": "Z-Wave", + "system_health": "Sistemos sveikata" }, "state": { "climate": { diff --git a/translations/nl.json b/translations/nl.json index 5b3ec44043..09f08dfc3d 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -301,7 +301,8 @@ "period": "Periode" }, "logbook": { - "showing_entries": "Toont gegevens van" + "showing_entries": "Toont gegevens van", + "period": "Periode" }, "mailbox": { "empty": "Je hebt geen berichten", @@ -433,6 +434,14 @@ "hours": "Uren", "minutes": "Minuten", "seconds": "Seconden" + }, + "geo_location": { + "label": "Geolocatie", + "source": "Bron", + "zone": "Zone", + "event": "Gebeurtenis:", + "enter": "Invoeren", + "leave": "Verlaten" } } }, @@ -565,7 +574,18 @@ }, "zha": { "caption": "ZHA", - "description": "Zigbee Home Automation netwerkbeheer" + "description": "Zigbee Home Automation netwerkbeheer", + "services": { + "reconfigure": "Herconfigureer het ZHA-apparaat (heal device). Gebruik dit als je problemen hebt met het apparaat. Als het een apparaat met batterij is, zorg dan dat het wakker is en commando's accepteert wanneer je deze service gebruikt." + } + }, + "area_registry": { + "caption": "Gebiedenregister", + "description": "Overzicht van alle gebieden in je huis." + }, + "entity_registry": { + "caption": "Entiteiten register", + "description": "Overzicht van alle gekende entiteiten" } }, "profile": { @@ -734,6 +754,11 @@ "checked_items": "Geselecteerde items", "clear_items": "Geselecteerde items wissen", "add_item": "Item toevoegen" + }, + "empty_state": { + "title": "Welkom thuis", + "no_devices": "Op deze pagina kun je je apparaten bedienen, maar het lijkt er op dat je nog geen apparaten hebt ingesteld. Ga naar de integraties-pagina om te beginnen.", + "go_to_integrations_page": "Ga naar de integraties-pagina." } }, "editor": { @@ -765,10 +790,16 @@ "para_sure": "Weet je zeker dat je de controle wilt over je gebruikersinterface?", "cancel": "Laat maar", "save": "Neem over" + }, + "menu": { + "raw_editor": "Platte configuratie-editor" } }, "menu": { - "configure_ui": "Configureer UI" + "configure_ui": "Configureer UI", + "unused_entities": "Ongebruikte entiteiten", + "help": "Help", + "refresh": "Vernieuwen" } } }, @@ -936,7 +967,7 @@ "dialogs": { "more_info_settings": { "save": "Opslaan", - "name": "Naam", + "name": "Naam overschrijven", "entity_id": "Entiteits-ID" }, "more_info_control": { @@ -1001,7 +1032,11 @@ "weblink": "Web link", "zwave": "Z-Wave", "vacuum": "Stofzuigen", - "zha": "ZHA" + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "Systeemstatus" }, "attribute": { "weather": { diff --git a/translations/pl.json b/translations/pl.json index a34e0e4dd9..680d81c343 100644 --- a/translations/pl.json +++ b/translations/pl.json @@ -301,7 +301,8 @@ "period": "Okres" }, "logbook": { - "showing_entries": "Wyświetlanie rekordów dla" + "showing_entries": "Wyświetlanie rekordów dla", + "period": "Okres" }, "mailbox": { "empty": "Nie masz żadnych wiadomości", @@ -789,10 +790,16 @@ "para_sure": "Czy na pewno chcesz przejąć kontrolę nad interfejsem użytkownika?", "cancel": "Nieważne", "save": "Przejmuję kontrolę" + }, + "menu": { + "raw_editor": "Ręczny edytor konfiguracji" } }, "menu": { - "configure_ui": "Konfiguracja interfejsu użytkownika" + "configure_ui": "Konfiguracja interfejsu użytkownika", + "unused_entities": "Nieużywane encje", + "help": "Pomoc", + "refresh": "Odśwież" } } }, @@ -1028,7 +1035,8 @@ "zha": "ZHA", "hassio": "Hass.io", "homeassistant": "Home Assistant", - "lovelace": "Lovelace" + "lovelace": "Lovelace", + "system_health": "Kondycja systemu" }, "attribute": { "weather": { diff --git a/translations/pt.json b/translations/pt.json index 9a47c977c2..fca1749d38 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -301,7 +301,8 @@ "period": "Período" }, "logbook": { - "showing_entries": "Mostrar valores para" + "showing_entries": "Mostrar valores para", + "period": "Período" }, "mailbox": { "empty": "Não tem qualquer mensagem nova", @@ -425,8 +426,22 @@ "leave": "Sair" }, "webhook": { - "label": "", - "webhook_id": "" + "label": "Webhook ID", + "webhook_id": "Webhook ID" + }, + "time_pattern": { + "label": "Padrão de tempo", + "hours": "Horas", + "minutes": "Minutos", + "seconds": "Segundos" + }, + "geo_location": { + "label": "Geolocalização", + "source": "Fonte", + "zone": "Zona", + "event": "Evento:", + "enter": "Entrar", + "leave": "Sair" } } }, @@ -556,6 +571,17 @@ "device_unavailable": "Dispositivo indisponível", "entity_unavailable": "Entidade indisponível" } + }, + "zha": { + "caption": "ZHA" + }, + "area_registry": { + "caption": "Registo de áreas", + "description": "Visão geral de todas as áreas da sua casa." + }, + "entity_registry": { + "caption": "Registo de Entidades", + "description": "Visão geral de todas as entidades conhecidas." } }, "profile": { @@ -724,6 +750,10 @@ "checked_items": "Itens marcados", "clear_items": "Limpar itens marcados", "add_item": "Adicionar Item" + }, + "empty_state": { + "title": "Bem-vindo a casa", + "go_to_integrations_page": "Ir para a página das integrações." } }, "editor": { @@ -758,7 +788,10 @@ } }, "menu": { - "configure_ui": "Configurar UI" + "configure_ui": "Configurar UI", + "unused_entities": "Entidades não utilizadas", + "help": "Ajuda", + "refresh": "Atualizar" } } }, @@ -928,6 +961,19 @@ "save": "Salvar", "name": "Nome", "entity_id": "ID da entidade" + }, + "more_info_control": { + "script": { + "last_action": "Última ação" + }, + "sun": { + "elevation": "Elevação", + "rising": "Nascer do sol", + "setting": "Por do sol" + }, + "updater": { + "title": "Instruções de atualização" + } } }, "auth_store": { @@ -977,7 +1023,12 @@ "updater": "Atualizador", "weblink": "Weblink", "zwave": "Z-Wave", - "vacuum": "Aspiração" + "vacuum": "Aspiração", + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "Integridade Do Sistema" }, "attribute": { "weather": { diff --git a/translations/ru.json b/translations/ru.json index 48d5b93d0a..bc5e3a0161 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -967,7 +967,7 @@ "dialogs": { "more_info_settings": { "save": "Сохранить", - "name": "Название", + "name": "Переопределение имени", "entity_id": "ID объекта" }, "more_info_control": { diff --git a/translations/sk.json b/translations/sk.json index 33d9fb0495..12eb45a830 100644 --- a/translations/sk.json +++ b/translations/sk.json @@ -301,7 +301,8 @@ "period": "Obdobie" }, "logbook": { - "showing_entries": "Zobrazujú sa záznamy za obdobie" + "showing_entries": "Zobrazujú sa záznamy za obdobie", + "period": "Obdobie" }, "mailbox": { "empty": "Nemáte žiadne správy", @@ -433,6 +434,13 @@ "hours": "Hodín", "minutes": "Minút", "seconds": "Sekúnd" + }, + "geo_location": { + "label": "Geolokácia", + "source": "Zdroj", + "zone": "Zóna", + "event": "Udalosť:", + "leave": "Opustiť" } } }, @@ -566,6 +574,14 @@ "zha": { "caption": "ZHA", "description": "Správa siete ZigBee Home Automation" + }, + "area_registry": { + "caption": "Register oblastí", + "description": "Prehľad všetkých oblastí vo vašej domácnosti." + }, + "entity_registry": { + "caption": "Register entít", + "description": "Prehľad všetkých známych entít." } }, "profile": { @@ -593,7 +609,7 @@ "description": "Každý obnovovací token predstavuje prihlásenú reláciu. Obnovovacie tokeny sa po kliknutí na tlačidlo Odhlásiť sa automaticky odstránia. Pre váš účet sú aktívne nasledovné obnovovacie tokeny.", "token_title": "Obnovovací token pre {clientId}", "created_at": "Vytvorený {date}", - "confirm_delete": "Naozaj chcete odstrániť obnovovací token pre {name} ?", + "confirm_delete": "Naozaj chcete odstrániť obnovovací token pre {name}?", "delete_failed": "Nepodarilo sa odstrániť obnovovací token", "last_used": "Naposledy použitý {date} z {location}", "not_used": "Nikdy nebol použitý", @@ -604,7 +620,7 @@ "description": "Vytvorte prístupové tokeny s dlhou životnosťou, ktoré umožnia vašim skriptom komunikovať s vašou inštanciou Home Assistant. Každý token bude platný 10 rokov od vytvorenia. Nasledujúce prístupové tokeny s dlhou životnosťou sú v súčasnosti aktívne.", "learn_auth_requests": "Zistite, ako vytvárať overené požiadavky.", "created_at": "Vytvorený {date}", - "confirm_delete": "Naozaj chcete odstrániť prístupový token pre {name} ?", + "confirm_delete": "Naozaj chcete odstrániť prístupový token pre {name}?", "delete_failed": "Nepodarilo sa odstrániť prístupový token.", "create": "Vytvoriť Token", "create_failed": "Nepodarilo sa vytvoriť prístupový token.", @@ -614,7 +630,7 @@ "last_used": "Naposledy použitý {date} z {location}", "not_used": "Nikdy nebol použitý" }, - "current_user": "Momentálne ste prihlásení ako {fullName} .", + "current_user": "Momentálne ste prihlásení ako {fullName}.", "is_owner": "Ste vlastníkom.", "logout": "Odhlásiť sa", "change_password": { @@ -629,7 +645,7 @@ "header": "Multifaktorové autentifikačné moduly", "disable": "Zakázať", "enable": "Povoliť", - "confirm_disable": "Naozaj chcete zakázať {name} ?" + "confirm_disable": "Naozaj chcete zakázať {name}?" }, "mfa_setup": { "title_aborted": "Prerušené", @@ -642,7 +658,7 @@ "page-authorize": { "initializing": "Inicializácia", "authorizing_client": "Chystáte sa poskytnúť {clientId} prístup k vašej inštancii Home Assistantu.", - "logging_in_with": "Prihlasovanie pomocou ** {authProviderName} **.", + "logging_in_with": "Prihlasovanie pomocou **{authProviderName}**.", "pick_auth_provider": "Alebo sa prihláste prostredníctvom", "abort_intro": "Prihlásenie bolo zrušené", "form": { @@ -661,7 +677,7 @@ "data": { "code": "Kód dvojfaktorovej autentifikácie" }, - "description": "Otvorte ** {mfa_module_name} ** v zariadení, aby ste si pozreli svoj dvojfaktorový autentifikačný kód a overili svoju totožnosť:" + "description": "Otvorte **{mfa_module_name}** v zariadení, aby ste si pozreli svoj dvojfaktorový autentifikačný kód a overili svoju totožnosť:" } }, "error": { @@ -734,6 +750,10 @@ "checked_items": "Označené položky", "clear_items": "Vymazať označené položky", "add_item": "Pridať položku" + }, + "empty_state": { + "title": "Vitajte doma", + "go_to_integrations_page": "Prejsť na stránku integrácií" } }, "editor": { @@ -763,12 +783,15 @@ "header": "Prevziať kontrolu rozhrania Lovelace", "para": "Štandardne bude Home Assistant udržiavať vaše používateľské rozhranie a aktualizovať ho, keď budú k dispozícii nové entity alebo komponenty rozhrania Lovelace. Ak prevezmete kontrolu, už za vás nebudeme automaticky robiť zmeny.", "para_sure": "Skutočne chcete prevziať kontrolu vášho používateľského rozhrania?", - "cancel": "Nevadí", + "cancel": "Zrušiť", "save": "Prevziať kontrolu" } }, "menu": { - "configure_ui": "Konfigurovať používateľské rozhranie" + "configure_ui": "Konfigurovať používateľské rozhranie", + "unused_entities": "Nepoužité entity", + "help": "Pomoc", + "refresh": "Obnoviť" } } }, @@ -1001,7 +1024,10 @@ "weblink": "Webový odkaz", "zwave": "Z-Wave", "vacuum": "Vysávač", - "zha": "ZHA" + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace" }, "attribute": { "weather": { diff --git a/translations/uk.json b/translations/uk.json index 2da28f10ed..37bb91250f 100644 --- a/translations/uk.json +++ b/translations/uk.json @@ -257,7 +257,14 @@ "windy-variant": "Вітряно" }, "vacuum": { - "idle": "Очікування" + "cleaning": "Прибирання", + "docked": "Пристиковано", + "error": "Помилка", + "idle": "Очікування", + "off": "Вимкнено", + "on": "Увімкнено", + "paused": "Призупинено", + "returning": "Повернення до дока" } }, "state_badge": { @@ -294,7 +301,8 @@ "period": "Період" }, "logbook": { - "showing_entries": "Відображення записів за" + "showing_entries": "Відображення записів за", + "period": "Період" }, "mailbox": { "empty": "У вас немає повідомлень", @@ -362,16 +370,37 @@ "add": "Додати тригер", "duplicate": "Дублювати", "delete": "Видалити", + "delete_confirm": "Ви впевнені, що хочете видалити?", "unsupported_platform": "Непідтримувана платформа: {platform}", + "type_select": "Тип подразнювача", "type": { + "event": { + "label": "Подія:", + "event_type": "Тип події", + "event_data": "Дані події " + }, + "state": { + "label": "Статус", + "from": "Від", + "to": "До", + "for": "Протягом" + }, "homeassistant": { + "label": "Home Assistant", "event": "Подія:", "start": "Початок", "shutdown": "Завершення роботи" }, + "mqtt": { + "label": "MQTT", + "topic": "Тема", + "payload": "Корисне навантаження (необов'язково)" + }, "numeric_state": { + "label": "Числовий стан", "above": "Вище", - "below": "Нижче" + "below": "Нижче", + "value_template": "Значення шаблону (необов'язково)" }, "sun": { "label": "Сонце", @@ -380,44 +409,76 @@ "sunset": "Захід сонця", "offset": "Зміщення (необов'язково)" }, + "template": { + "label": "Шаблон", + "value_template": "Значення шаблону" + }, "time": { "label": "Час", "at": "У" }, "zone": { "label": "Зона", + "entity": "Місце розташування об'єкту", "zone": "Зона:", "event": "Подія:", "enter": "Увійшов", "leave": "Залишив" }, - "state": { - "for": "Протягом" + "webhook": { + "label": "Webhook", + "webhook_id": "Webhook ID" }, "time_pattern": { "label": "Шаблон часу", "hours": "Годин", "minutes": "Хвилин", "seconds": "Секунд" + }, + "geo_location": { + "label": "Геолокація", + "source": "Джерело", + "zone": "Зона", + "event": "Подія:", + "enter": "Увійти", + "leave": "Залишити" } } }, "conditions": { "header": "Умови", "introduction": "Умови є необов'язковою частиною правила автоматизації і можуть використовуватися для запобігання дії, що відбувається під час запуску. Умови виглядають дуже схоже на тригери, але вони різні. Тригер буде дивитися на події, що відбуваються в системі, в той час як умова тільки дивиться на те, як система виглядає зараз. Тригер може спостерігати, що перемикач включений. Умова може бачити тільки, якщо перемикач ввімкнено або вимкнено. \n\n [Докладніше про умови.] (Https:\/\/home-assistant.io\/docs\/scripts\/conditions\/)", + "add": "Додати умову", "duplicate": "Дублювати", "delete": "Видалити", "delete_confirm": "Ви впевнені, що хочете видалити?", + "unsupported_condition": "Непідтримувана умова: {condition}", + "type_select": "Тип умови", "type": { + "numeric_state": { + "above": "Над", + "below": "Нижче" + }, "sun": { + "label": "Сонце", "before": "Перед:", "after": "Після:", "before_offset": "Перед зміщенням (необов'язково)", - "after_offset": "Після зміщення (опціонально)" + "after_offset": "Після зміщення (опціонально)", + "sunrise": "Схід", + "sunset": "Захід" + }, + "template": { + "label": "Шаблон" }, "time": { + "label": "Час", "after": "Після", "before": "До" + }, + "zone": { + "label": "Зона", + "zone": "Зона" } } }, @@ -431,12 +492,26 @@ "unsupported_action": "Непідтримувана дія: {action}", "type_select": "Тип дії", "type": { + "service": { + "label": "Викликати послугу", + "service_data": "Дані послуги " + }, "delay": { - "label": "Затримка" + "label": "Затримка", + "delay": "Затримка" }, "wait_template": { "label": "Чекати", + "wait_template": "Шаблон Wait", "timeout": "Тайм-аут (необов'язково)" + }, + "condition": { + "label": "Умова" + }, + "event": { + "label": "Викликати подію", + "event": "Подія:", + "service_data": "Дані послуги" } } } @@ -447,7 +522,8 @@ "description": "Створення та редагування скриптів" }, "zwave": { - "caption": "Z-Wave" + "caption": "Z-Wave", + "description": "Керуйте мережею Z-Wave" }, "users": { "caption": "Користувачі", @@ -487,6 +563,21 @@ "device_unavailable": "пристрій недоступний", "entity_unavailable": "Недоступний" } + }, + "zha": { + "caption": "ZHA", + "description": "Управління мережею домашньої автоматизації Zigbee", + "services": { + "reconfigure": "Переконфігуруйте пристрій ZHA (пристрій загоєння). Використовуйте це, якщо у вас виникли проблеми з пристроєм. Якщо пристрій, про який йде мова, живиться від батареї, будь ласка, переконайтеся, що він є активним і приймає команди під час використання цієї команди." + } + }, + "area_registry": { + "caption": "Реєстр зони", + "description": "Огляд всіх областей у вашому домі." + }, + "entity_registry": { + "caption": "Реєстр об'єктів", + "description": "Огляд всіх відомих об'єктів." } }, "profile": { @@ -608,10 +699,12 @@ } }, "error": { - "invalid_auth": "Невірний пароль API" + "invalid_auth": "Невірний пароль API", + "invalid_code": "Невірний код авторизації" }, "abort": { - "no_api_password_set": "Ви не маєте налаштованого пароля API." + "no_api_password_set": "Ви не маєте налаштованого пароля API.", + "login_expired": "Термін дії сессії закінчився, авторизуйтесь ще раз" } }, "trusted_networks": { @@ -652,6 +745,11 @@ "checked_items": "Позначені елементи", "clear_items": "Очистити позначені елементи", "add_item": "Додати елемент" + }, + "empty_state": { + "title": "Ласкаво просимо додому", + "no_devices": "Ця сторінка дозволяє керувати пристроями, однак, схоже, у вас ще немає налаштованих пристроїв. Щоб почати, перейдіть на сторінку інтеграції.", + "go_to_integrations_page": "Перейти на сторінку інтеграцій." } }, "editor": { @@ -679,14 +777,20 @@ }, "save_config": { "header": "Візьміть під свій контроль Lovelace UI", - "para": "За замовчуванням Home Assistant буде підтримувати ваш користувальницький інтерфейс, оновлюючи його, коли з'являться нові об'єкти або компоненти Lovelace. Якщо ви візьмете під контроль, ми більше не будемо автоматично вносити зміни для вас.", - "para_sure": "Ви впевнені, що хочете взяти під свій контроль користувальницький інтерфейс?", + "para": "За замовчуванням Home Assistant буде підтримувати ваш інтерфейс, оновлюючи його, коли з'являться нові об'єкти або компоненти Lovelace. Якщо ви візьмете під контроль, ми більше не будемо автоматично вносити зміни для вас.", + "para_sure": "Ви впевнені, що хочете взяти під свій контроль інтерфейс?", "cancel": "Неважливо", "save": "Взяти під контроль" + }, + "menu": { + "raw_editor": "Текстовий редактор" } }, "menu": { - "configure_ui": "Налаштувати інтерфейс користувача" + "configure_ui": "Налаштувати інтерфейс користувача", + "unused_entities": "Незадіяні об'єкти", + "help": "Допомога", + "refresh": "Оновити" } } }, @@ -732,6 +836,24 @@ "visibility": "Видимість", "wind_speed": "Швидкість вітру" }, + "cardinal_direction": { + "e": "E", + "ene": "ENE", + "ese": "ESE", + "n": "N", + "ne": "NE", + "nne": "NNE", + "nw": "NW", + "nnw": "NNW", + "s": "S", + "se": "SE", + "sse": "SSE", + "ssw": "SSW", + "sw": "SW", + "w": "W", + "wnw": "WNW", + "wsw": "WSW" + }, "forecast": "Прогноз" }, "alarm_control_panel": { @@ -775,7 +897,8 @@ "operation": "Режим", "fan_mode": "Режим вентилятора", "swing_mode": "Режим гойдання", - "away_mode": "Режиму очікування" + "away_mode": "Режиму очікування", + "aux_heat": "Aux тепла" }, "lock": { "code": "Код", @@ -784,6 +907,9 @@ }, "vacuum": { "actions": { + "resume_cleaning": "Відновити очищення", + "return_to_base": "Повернутись до дока", + "start_cleaning": "Почати очищення", "turn_on": "Ввімкнути", "turn_off": "Вимкнути" } @@ -832,7 +958,8 @@ "dialogs": { "more_info_settings": { "save": "Зберегти", - "name": "Назва" + "name": "Назва", + "entity_id": "Ідентифікатор об'єкта" }, "more_info_control": { "script": { @@ -873,6 +1000,12 @@ "fan": "Вентилятор", "history_graph": "Графік історії", "group": "Група", + "image_processing": "Обробка зображень ", + "input_boolean": "Введення логічного значення", + "input_datetime": "Введення дати", + "input_select": "Вибрати", + "input_number": "Введіть номер", + "input_text": "Введення тексту", "light": "Освітлення", "lock": "Замок", "mailbox": "Поштова скринька", @@ -888,7 +1021,13 @@ "switch": "Перемикач", "updater": "Оновлювач", "weblink": "Посилання", - "zwave": "Z-Wave" + "zwave": "Z-Wave", + "vacuum": "Пилосос", + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "Безпека системи" }, "attribute": { "weather": { diff --git a/translations/zh-Hans.json b/translations/zh-Hans.json index 0734e3e2d9..5acaaad1a5 100644 --- a/translations/zh-Hans.json +++ b/translations/zh-Hans.json @@ -301,7 +301,8 @@ "period": "日期范围" }, "logbook": { - "showing_entries": "显示以下日期的条目" + "showing_entries": "显示以下日期的条目", + "period": "周期" }, "mailbox": { "empty": "您还没有任何消息", @@ -432,6 +433,14 @@ "hours": "小时", "minutes": "分", "seconds": "秒" + }, + "geo_location": { + "label": "地理位置", + "source": "位置来源", + "zone": "区域", + "event": "事件:", + "enter": "进入", + "leave": "离开" } } }, @@ -564,6 +573,12 @@ }, "zha": { "description": "Zigbee 智能家居(ZHA) 网络管理" + }, + "area_registry": { + "description": "您家中所有区域的概览。" + }, + "entity_registry": { + "description": "所有已知实体的概览。" } }, "profile": { @@ -732,6 +747,11 @@ "checked_items": "已完成项目", "clear_items": "清除已完成项目", "add_item": "新增项目" + }, + "empty_state": { + "title": "欢迎回家", + "no_devices": "此页面是用来控制设备的,不过您好像还没有配置好任何设备。请前往集成页面以开始。", + "go_to_integrations_page": "前往集成页面。" } }, "editor": { @@ -763,10 +783,16 @@ "para_sure": "您确定要自行编辑用户界面吗?", "cancel": "没关系", "save": "自行编辑" + }, + "menu": { + "raw_editor": "原始配置编辑器" } }, "menu": { - "configure_ui": "配置 UI" + "configure_ui": "配置 UI", + "unused_entities": "未使用的实体", + "help": "帮助", + "refresh": "刷新" } } }, @@ -998,7 +1024,11 @@ "updater": "更新提示", "weblink": "网址", "zwave": "Z-Wave", - "vacuum": "扫地机" + "vacuum": "扫地机", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "系统状态" }, "attribute": { "weather": { From 0f680bcfd6ab5650bb1116f59679b5d7780a1ae8 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Tue, 12 Feb 2019 11:40:39 -0600 Subject: [PATCH 06/66] Fix typo in alarm editor (#2729) * Fix typo in alarm editor * tacking on decorators, styles and card size fix --- .../lovelace/cards/hui-alarm-panel-card.ts | 41 ++++++++++--------- .../hui-alarm-panel-card-editor.ts | 2 +- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/panels/lovelace/cards/hui-alarm-panel-card.ts b/src/panels/lovelace/cards/hui-alarm-panel-card.ts index aab241299b..8311aec7ad 100644 --- a/src/panels/lovelace/cards/hui-alarm-panel-card.ts +++ b/src/panels/lovelace/cards/hui-alarm-panel-card.ts @@ -2,8 +2,10 @@ import { html, LitElement, PropertyValues, - PropertyDeclarations, TemplateResult, + CSSResult, + css, + property, } from "lit-element"; import { classMap } from "lit-html/directives/class-map"; @@ -50,20 +52,22 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard { return { states: ["arm_home", "arm_away"] }; } - public hass?: HomeAssistant; - private _config?: Config; - private _code?: string; - - static get properties(): PropertyDeclarations { - return { - hass: {}, - _config: {}, - _code: {}, - }; - } + @property() public hass?: HomeAssistant; + @property() private _config?: Config; + @property() private _code?: string; public getCardSize(): number { - return 4; + if (!this._config || !this.hass) { + return 0; + } + + const stateObj = this.hass.states[this._config.entity]; + + if (!stateObj) { + return 0; + } + + return stateObj.attributes.code_format !== FORMAT_NUMBER ? 3 : 8; } public setConfig(config: Config): void { @@ -114,7 +118,6 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard { } return html` - ${this.renderStyle()} + static get styles(): CSSResult[] { + return [ + css` ha-card { padding-bottom: 16px; position: relative; @@ -293,8 +296,8 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard { paper-button#disarm { color: var(--google-red-500); } - - `; + `, + ]; } } diff --git a/src/panels/lovelace/editor/config-elements/hui-alarm-panel-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-alarm-panel-card-editor.ts index 969a48f2e6..d5a3dad07b 100644 --- a/src/panels/lovelace/editor/config-elements/hui-alarm-panel-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-alarm-panel-card-editor.ts @@ -57,7 +57,7 @@ export class HuiAlarmPanelCardEditor extends LitElement return html``; } - const states = ["arm_home", "arm_away", "arm_night", "arm_custom_bypass"]; + const states = ["arm_home", "arm_away", "arm_night", "armed_custom_bypass"]; return html` ${configElementStyle} ${this.renderStyle()} From aae3c26a64da0a85b08e8a68e88fa26fc03480e9 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Tue, 12 Feb 2019 11:43:59 -0600 Subject: [PATCH 07/66] render remote entity-row as a toggle (#2731) --- src/panels/lovelace/common/create-row-element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/panels/lovelace/common/create-row-element.ts b/src/panels/lovelace/common/create-row-element.ts index feafcb8952..510d52a53a 100644 --- a/src/panels/lovelace/common/create-row-element.ts +++ b/src/panels/lovelace/common/create-row-element.ts @@ -46,8 +46,9 @@ const DOMAIN_TO_ELEMENT_TYPE = { input_select: "input-select", input_text: "input-text", light: "toggle", - media_player: "media-player", lock: "lock", + media_player: "media-player", + remote: "toggle", scene: "scene", script: "script", sensor: "sensor", From 2f2cdad16b51245e6cd76f247e393d0d9ca95410 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Tue, 12 Feb 2019 13:52:02 -0600 Subject: [PATCH 08/66] static styles, decorators and width fix (#2727) Not sure how the width got messed up, perhaps changes to ha-card? --- .../lovelace/cards/hui-shopping-list-card.ts | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/panels/lovelace/cards/hui-shopping-list-card.ts b/src/panels/lovelace/cards/hui-shopping-list-card.ts index 78eafecd8a..e98053f36f 100644 --- a/src/panels/lovelace/cards/hui-shopping-list-card.ts +++ b/src/panels/lovelace/cards/hui-shopping-list-card.ts @@ -1,4 +1,11 @@ -import { html, LitElement, TemplateResult } from "lit-element"; +import { + html, + LitElement, + TemplateResult, + css, + CSSResult, + property, +} from "lit-element"; import { repeat } from "lit-html/directives/repeat"; import { PaperInputElement } from "@polymer/paper-input/paper-input"; import "@polymer/paper-checkbox/paper-checkbox"; @@ -26,25 +33,17 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard { await import(/* webpackChunkName: "hui-shopping-list-editor" */ "../editor/config-elements/hui-shopping-list-editor"); return document.createElement("hui-shopping-list-card-editor"); } + public static getStubConfig(): object { return {}; } - public hass?: HomeAssistant; - private _config?: Config; - private _uncheckedItems?: ShoppingListItem[]; - private _checkedItems?: ShoppingListItem[]; + @property() public hass?: HomeAssistant; + @property() private _config?: Config; + @property() private _uncheckedItems?: ShoppingListItem[]; + @property() private _checkedItems?: ShoppingListItem[]; private _unsubEvents?: Promise<() => Promise>; - static get properties() { - return { - hass: {}, - _config: {}, - _uncheckedItems: {}, - _checkedItems: {}, - }; - } - public getCardSize(): number { return (this._config ? (this._config.title ? 1 : 0) : 0) + 3; } @@ -82,7 +81,6 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard { } return html` - ${this.renderStyle()}
+ static get styles(): CSSResult[] { + return [ + css` .editRow, .addRow { display: flex; @@ -192,6 +190,9 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard { padding: 9px 15px 11px 15px; cursor: pointer; } + paper-item-body { + width: 75%; + } paper-checkbox { padding: 11px 11px 11px 18px; } @@ -230,8 +231,8 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard { .addRow > ha-icon { color: var(--secondary-text-color); } - - `; + `, + ]; } private async _fetchData(): Promise { From abbfea0b6ace9e6c0f926d05ce91ee8b2decad3a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 12 Feb 2019 11:52:30 -0800 Subject: [PATCH 09/66] Person: Pick device tracker (#2726) * Allow picking devices to track * Tweak translation * Update translation --- package.json | 2 + src/components/entity/ha-entities-picker.ts | 120 +++++++++++ src/components/entity/ha-entity-picker.js | 179 ---------------- src/components/entity/ha-entity-picker.ts | 200 ++++++++++++++++++ .../config/person/dialog-person-detail.ts | 49 +++-- src/translations/en.json | 10 +- src/types.ts | 7 + yarn.lock | 10 + 8 files changed, 381 insertions(+), 196 deletions(-) create mode 100644 src/components/entity/ha-entities-picker.ts delete mode 100644 src/components/entity/ha-entity-picker.js create mode 100644 src/components/entity/ha-entity-picker.ts diff --git a/package.json b/package.json index d704eb4b9b..111db689f4 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "lit-html": "^1.0.0", "marked": "^0.6.0", "mdn-polyfills": "^5.12.0", + "memoize-one": "^5.0.0", "moment": "^2.22.2", "preact": "^8.3.1", "preact-compat": "^3.18.4", @@ -105,6 +106,7 @@ "@gfx/zopfli": "^1.0.9", "@types/chai": "^4.1.7", "@types/codemirror": "^0.0.71", + "@types/memoize-one": "^4.1.0", "@types/mocha": "^5.2.5", "babel-eslint": "^10", "babel-loader": "^8.0.4", diff --git a/src/components/entity/ha-entities-picker.ts b/src/components/entity/ha-entities-picker.ts new file mode 100644 index 0000000000..5fe0720c95 --- /dev/null +++ b/src/components/entity/ha-entities-picker.ts @@ -0,0 +1,120 @@ +import { + LitElement, + TemplateResult, + property, + html, + customElement, +} from "lit-element"; +import "@polymer/paper-icon-button/paper-icon-button-light"; + +import { HomeAssistant } from "../../types"; +import { PolymerChangedEvent } from "../../polymer-types"; +import { fireEvent } from "../../common/dom/fire_event"; +import isValidEntityId from "../../common/entity/valid_entity_id"; + +import "./ha-entity-picker"; +// Not a duplicate, type import +// tslint:disable-next-line +import { HaEntityPickerEntityFilterFunc } from "./ha-entity-picker"; +import { HassEntity } from "home-assistant-js-websocket"; + +@customElement("ha-entities-picker") +class HaEntitiesPickerLight extends LitElement { + @property() public hass?: HomeAssistant; + @property() public value?: string[]; + @property() public domainFilter?: string; + @property() public pickedEntityLabel?: string; + @property() public pickEntityLabel?: string; + + protected render(): TemplateResult | void { + if (!this.hass) { + return; + } + const currentEntities = this._currentEntities; + return html` + ${currentEntities.map( + (entityId) => html` +
+ +
+ ` + )} +
+ +
+ `; + } + + private _entityFilter: HaEntityPickerEntityFilterFunc = ( + stateObj: HassEntity + ) => !this.value || !this.value.includes(stateObj.entity_id); + + private get _currentEntities() { + return this.value || []; + } + + private async _updateEntities(entities) { + fireEvent(this, "value-changed", { + value: entities, + }); + + this.value = entities; + } + + private _entityChanged(event: PolymerChangedEvent) { + event.stopPropagation(); + const curValue = (event.currentTarget as any).curValue; + const newValue = event.detail.value; + if ( + newValue === curValue || + (newValue !== "" && !isValidEntityId(newValue)) + ) { + return; + } + if (newValue === "") { + this._updateEntities( + this._currentEntities.filter((ent) => ent !== curValue) + ); + } else { + this._updateEntities( + this._currentEntities.map((ent) => (ent === curValue ? newValue : ent)) + ); + } + } + + private async _addEntity(event: PolymerChangedEvent) { + event.stopPropagation(); + const toAdd = event.detail.value; + (event.currentTarget as any).value = ""; + if (!toAdd) { + return; + } + const currentEntities = this._currentEntities; + if (currentEntities.includes(toAdd)) { + return; + } + + this._updateEntities([...currentEntities, toAdd]); + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-entities-picker": HaEntitiesPickerLight; + } +} diff --git a/src/components/entity/ha-entity-picker.js b/src/components/entity/ha-entity-picker.js deleted file mode 100644 index bc4765d8d7..0000000000 --- a/src/components/entity/ha-entity-picker.js +++ /dev/null @@ -1,179 +0,0 @@ -import "@polymer/paper-icon-button/paper-icon-button"; -import "@polymer/paper-input/paper-input"; -import "@polymer/paper-item/paper-icon-item"; -import "@polymer/paper-item/paper-item-body"; -import { html } from "@polymer/polymer/lib/utils/html-tag"; -import { PolymerElement } from "@polymer/polymer/polymer-element"; -import "@vaadin/vaadin-combo-box/vaadin-combo-box-light"; - -import "./state-badge"; - -import computeStateName from "../../common/entity/compute_state_name"; -import LocalizeMixin from "../../mixins/localize-mixin"; -import EventsMixin from "../../mixins/events-mixin"; - -/* - * @appliesMixin LocalizeMixin - */ -class HaEntityPicker extends EventsMixin(LocalizeMixin(PolymerElement)) { - static get template() { - return html` - - - - Clear - - - - - `; - } - - static get properties() { - return { - allowCustomEntity: { - type: Boolean, - value: false, - }, - hass: { - type: Object, - observer: "_hassChanged", - }, - _hass: Object, - _states: { - type: Array, - computed: "_computeStates(_hass, domainFilter, entityFilter)", - }, - autofocus: Boolean, - label: { - type: String, - }, - value: { - type: String, - notify: true, - }, - opened: { - type: Boolean, - value: false, - observer: "_openedChanged", - }, - domainFilter: { - type: String, - value: null, - }, - entityFilter: { - type: Function, - value: null, - }, - disabled: Boolean, - }; - } - - _computeLabel(label, localize) { - return label === undefined - ? localize("ui.components.entity.entity-picker.entity") - : label; - } - - _computeStates(hass, domainFilter, entityFilter) { - if (!hass) return []; - - let entityIds = Object.keys(hass.states); - - if (domainFilter) { - entityIds = entityIds.filter( - (eid) => eid.substr(0, eid.indexOf(".")) === domainFilter - ); - } - - let entities = entityIds.sort().map((key) => hass.states[key]); - - if (entityFilter) { - entities = entities.filter(entityFilter); - } - - return entities; - } - - _computeStateName(state) { - return computeStateName(state); - } - - _openedChanged(newVal) { - if (!newVal) { - this._hass = this.hass; - } - } - - _hassChanged(newVal) { - if (!this.opened) { - this._hass = newVal; - } - } - - _computeToggleIcon(opened) { - return opened ? "hass:menu-up" : "hass:menu-down"; - } - - _fireChanged(ev) { - ev.stopPropagation(); - this.fire("change"); - } -} - -customElements.define("ha-entity-picker", HaEntityPicker); diff --git a/src/components/entity/ha-entity-picker.ts b/src/components/entity/ha-entity-picker.ts new file mode 100644 index 0000000000..3b5bf7ed88 --- /dev/null +++ b/src/components/entity/ha-entity-picker.ts @@ -0,0 +1,200 @@ +import "@polymer/paper-icon-button/paper-icon-button"; +import "@polymer/paper-input/paper-input"; +import "@polymer/paper-item/paper-icon-item"; +import "@polymer/paper-item/paper-item-body"; +import "@vaadin/vaadin-combo-box/vaadin-combo-box-light"; +import memoizeOne from "memoize-one"; + +import "./state-badge"; + +import computeStateName from "../../common/entity/compute_state_name"; +import { + LitElement, + TemplateResult, + html, + css, + CSSResult, + property, + PropertyValues, +} from "lit-element"; +import { HomeAssistant } from "../../types"; +import { HassEntity } from "home-assistant-js-websocket"; +import { PolymerChangedEvent } from "../../polymer-types"; +import { fireEvent } from "../../common/dom/fire_event"; + +export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean; + +const rowRenderer = ( + root: HTMLElement, + _owner, + model: { item: HassEntity } +) => { + if (!root.firstElementChild) { + root.innerHTML = ` + + + + +
[[_computeStateName(item)]]
+
[[item.entity_id]]
+
+
+ `; + } + + root.querySelector("state-badge")!.stateObj = model.item; + root.querySelector(".name")!.textContent = computeStateName(model.item); + root.querySelector("[secondary]")!.textContent = model.item.entity_id; +}; + +class HaEntityPicker extends LitElement { + @property({ type: Boolean }) public autofocus?: boolean; + @property({ type: Boolean }) public disabled?: boolean; + @property({ type: Boolean }) public allowCustomEntity; + @property() public hass?: HomeAssistant; + @property() public label?: string; + @property() public value?: string; + @property() public domainFilter?: string; + @property() public entityFilter?: HaEntityPickerEntityFilterFunc; + @property({ type: Boolean }) private _opened?: boolean; + @property() private _hass?: HomeAssistant; + + private _getStates = memoizeOne( + ( + hass: this["hass"], + domainFilter: this["domainFilter"], + entityFilter: this["entityFilter"] + ) => { + let states: HassEntity[] = []; + + if (!hass) { + return []; + } + let entityIds = Object.keys(hass.states); + + if (domainFilter) { + entityIds = entityIds.filter( + (eid) => eid.substr(0, eid.indexOf(".")) === domainFilter + ); + } + + states = entityIds.sort().map((key) => hass!.states[key]); + + if (entityFilter) { + states = states.filter( + (stateObj) => + // We always want to include the entity of the current value + stateObj.entity_id === this.value || entityFilter!(stateObj) + ); + } + return states; + } + ); + + protected updated(changedProps: PropertyValues) { + super.updated(changedProps); + + if (changedProps.has("hass") && !this._opened) { + this._hass = this.hass; + } + } + + protected render(): TemplateResult | void { + const states = this._getStates( + this._hass, + this.domainFilter, + this.entityFilter + ); + + return html` + + + ${this.value + ? html` + + Clear + + ` + : ""} + ${states.length > 0 + ? html` + + Toggle + + ` + : ""} + + + `; + } + + private get _value() { + return this.value || ""; + } + + private _openedChanged(ev: PolymerChangedEvent) { + this._opened = ev.detail.value; + } + + private _valueChanged(ev: PolymerChangedEvent) { + const newValue = ev.detail.value; + if (newValue !== this._value) { + this.value = ev.detail.value; + setTimeout(() => { + fireEvent(this, "value-changed", { value: this.value }); + fireEvent(this, "change"); + }, 0); + } + } + + static get styles(): CSSResult { + return css` + paper-input > paper-icon-button { + width: 24px; + height: 24px; + padding: 2px; + color: var(--secondary-text-color); + } + [hidden] { + display: none; + } + `; + } +} + +customElements.define("ha-entity-picker", HaEntityPicker); diff --git a/src/panels/config/person/dialog-person-detail.ts b/src/panels/config/person/dialog-person-detail.ts index 2e863e7c80..4497f6204d 100644 --- a/src/panels/config/person/dialog-person-detail.ts +++ b/src/panels/config/person/dialog-person-detail.ts @@ -2,14 +2,15 @@ import { LitElement, html, css, - PropertyDeclarations, CSSResult, TemplateResult, + property, } from "lit-element"; import "@polymer/paper-dialog/paper-dialog"; import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable"; import "@polymer/paper-input/paper-input"; +import "../../../components/entity/ha-entities-picker"; import { PersonDetailDialogParams } from "./show-dialog-person-detail"; import { PolymerChangedEvent } from "../../../polymer-types"; import { haStyleDialog } from "../../../resources/ha-style"; @@ -17,24 +18,20 @@ import { HomeAssistant } from "../../../types"; import { PersonMutableParams } from "../../../data/person"; class DialogPersonDetail extends LitElement { - public hass!: HomeAssistant; - private _name!: string; - private _error?: string; - private _params?: PersonDetailDialogParams; - private _submitting?: boolean; - - static get properties(): PropertyDeclarations { - return { - _error: {}, - _name: {}, - _params: {}, - }; - } + @property() public hass!: HomeAssistant; + @property() private _name!: string; + @property() private _deviceTrackers!: string[]; + @property() private _error?: string; + @property() private _params?: PersonDetailDialogParams; + @property() private _submitting?: boolean; public async showDialog(params: PersonDetailDialogParams): Promise { this._params = params; this._error = undefined; this._name = this._params.entry ? this._params.entry.name : ""; + this._deviceTrackers = this._params.entry + ? this._params.entry.device_trackers || [] + : []; await this.updateComplete; } @@ -64,6 +61,23 @@ class DialogPersonDetail extends LitElement { error-message="Name is required" .invalid=${nameInvalid} > +

+ ${this.hass.localize( + "ui.panel.config.person.detail.device_tracker_intro" + )} +

+
@@ -94,14 +108,19 @@ class DialogPersonDetail extends LitElement { this._name = ev.detail.value; } + private _deviceTrackersChanged(ev: PolymerChangedEvent) { + this._error = undefined; + this._deviceTrackers = ev.detail.value; + } + private async _updateEntry() { this._submitting = true; try { const values: PersonMutableParams = { name: this._name.trim(), + device_trackers: this._deviceTrackers, // Temp, we will add this in a future PR. user_id: null, - device_trackers: [], }; if (this._params!.entry) { await this._params!.updateEntry(values); diff --git a/src/translations/en.json b/src/translations/en.json index 01aca9f1e3..d20f31f8cf 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -783,8 +783,14 @@ } }, "person": { - "caption": "People", - "description": "Manage the people in Home Assistant." + "caption": "Persons", + "description": "Manage the persons that Home Assistant tracks.", + "detail": { + "name": "Name", + "device_tracker_intro": "Select the devices that belong to this person.", + "device_tracker_picked": "Track Device", + "device_tracker_pick": "Pick device to track" + } }, "integrations": { "caption": "Integrations", diff --git a/src/types.ts b/src/types.ts index e72f40b124..50964a2640 100644 --- a/src/types.ts +++ b/src/types.ts @@ -29,6 +29,13 @@ declare global { getComputedStyleValue(element, propertyName); }; } + // for fire event + interface HASSDomEvents { + "value-changed": { + value: unknown; + }; + change: undefined; + } } export interface WebhookError { diff --git a/yarn.lock b/yarn.lock index 800cf3275f..17185f5b93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1642,6 +1642,11 @@ resolved "https://registry.yarnpkg.com/@types/launchpad/-/launchpad-0.6.0.tgz#37296109b7f277f6e6c5fd7e0c0706bc918fbb51" integrity sha1-NylhCbfyd/bmxf1+DAcGvJGPu1E= +"@types/memoize-one@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@types/memoize-one/-/memoize-one-4.1.0.tgz#62119f26055b3193ae43ca1882c5b29b88b71ece" + integrity sha512-cmSgi6JMX/yBwgpVm4GooNWIH+vEeJoa8FAa6ExOhpJbC0Juq32/uYKiKb3VPSqrEA0aOnjvwZanla3O1WZMbw== + "@types/merge-stream@^1.0.28": version "1.1.2" resolved "https://registry.yarnpkg.com/@types/merge-stream/-/merge-stream-1.1.2.tgz#a880ff66b1fbbb5eef4958d015c5947a9334dbb1" @@ -9466,6 +9471,11 @@ mem@^4.0.0: mimic-fn "^1.0.0" p-is-promise "^1.1.0" +memoize-one@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.0.tgz#d55007dffefb8de7546659a1722a5d42e128286e" + integrity sha512-7g0+ejkOaI9w5x6LvQwmj68kUj6rxROywPSCqmclG/HBacmFnZqhVscQ8kovkn9FBCNJmOz6SY42+jnvZzDWdw== + memory-fs@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290" From 3a644621fe1a1571862deda02ec8c0edd881a577 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Tue, 12 Feb 2019 14:55:42 -0500 Subject: [PATCH 10/66] Make ZHA config panel device oriented (#2722) * change to be zha device centric instead of entity centric * clusters by device * device centric API * lit ts and cleanup * type * review comments and fix remove * fix set attribute --- src/data/zha.ts | 51 +++--- src/panels/config/zha/ha-config-zha.ts | 18 +- src/panels/config/zha/types.ts | 11 +- .../config/zha/zha-cluster-attributes.ts | 33 ++-- src/panels/config/zha/zha-cluster-commands.ts | 24 +-- src/panels/config/zha/zha-clusters.ts | 22 +-- src/panels/config/zha/zha-device-card.ts | 118 ++++++++++++ src/panels/config/zha/zha-entities.ts | 170 ------------------ src/panels/config/zha/zha-network.ts | 3 +- src/panels/config/zha/zha-node.ts | 126 ++++++------- 10 files changed, 253 insertions(+), 323 deletions(-) create mode 100644 src/panels/config/zha/zha-device-card.ts delete mode 100644 src/panels/config/zha/zha-entities.ts diff --git a/src/data/zha.ts b/src/data/zha.ts index f5a67dbb12..8c50b82f3c 100644 --- a/src/data/zha.ts +++ b/src/data/zha.ts @@ -7,8 +7,19 @@ export interface ZHADeviceEntity extends HassEntity { }; } -export interface ZHAEntities { - [key: string]: HassEntity[]; +export interface ZHAEntityReference extends HassEntity { + name: string; +} + +export interface ZHADevice { + name: string; + ieee: string; + manufacturer: string; + model: string; + quirk_applied: boolean; + quirk_class: string; + entities: ZHAEntityReference[]; + manufacturer_code: number; } export interface Attribute { @@ -19,6 +30,7 @@ export interface Attribute { export interface Cluster { name: string; id: number; + endpoint_id: number; type: string; } @@ -29,7 +41,8 @@ export interface Command { } export interface ReadAttributeServiceData { - entity_id: string; + ieee: string; + endpoint_id: number; cluster_id: number; cluster_type: string; attribute: number; @@ -41,64 +54,60 @@ export const reconfigureNode = ( ieeeAddress: string ): Promise => hass.callWS({ - type: "zha/nodes/reconfigure", + type: "zha/devices/reconfigure", ieee: ieeeAddress, }); export const fetchAttributesForCluster = ( hass: HomeAssistant, - entityId: string, ieeeAddress: string, + endpointId: number, clusterId: number, clusterType: string ): Promise => hass.callWS({ - type: "zha/entities/clusters/attributes", - entity_id: entityId, + type: "zha/devices/clusters/attributes", ieee: ieeeAddress, + endpoint_id: endpointId, cluster_id: clusterId, cluster_type: clusterType, }); +export const fetchDevices = (hass: HomeAssistant): Promise => + hass.callWS({ + type: "zha/devices", + }); + export const readAttributeValue = ( hass: HomeAssistant, data: ReadAttributeServiceData ): Promise => { return hass.callWS({ ...data, - type: "zha/entities/clusters/attributes/value", + type: "zha/devices/clusters/attributes/value", }); }; export const fetchCommandsForCluster = ( hass: HomeAssistant, - entityId: string, ieeeAddress: string, + endpointId: number, clusterId: number, clusterType: string ): Promise => hass.callWS({ - type: "zha/entities/clusters/commands", - entity_id: entityId, + type: "zha/devices/clusters/commands", ieee: ieeeAddress, + endpoint_id: endpointId, cluster_id: clusterId, cluster_type: clusterType, }); export const fetchClustersForZhaNode = ( hass: HomeAssistant, - entityId: string, ieeeAddress: string ): Promise => hass.callWS({ - type: "zha/entities/clusters", - entity_id: entityId, + type: "zha/devices/clusters", ieee: ieeeAddress, }); - -export const fetchEntitiesForZhaNode = ( - hass: HomeAssistant -): Promise => - hass.callWS({ - type: "zha/entities", - }); diff --git a/src/panels/config/zha/ha-config-zha.ts b/src/panels/config/zha/ha-config-zha.ts index 23ae151636..1ab743c6c6 100755 --- a/src/panels/config/zha/ha-config-zha.ts +++ b/src/panels/config/zha/ha-config-zha.ts @@ -14,11 +14,7 @@ import { Cluster } from "../../../data/zha"; import "../../../layouts/ha-app-layout"; import { haStyle } from "../../../resources/ha-style"; import { HomeAssistant } from "../../../types"; -import { - ZHAClusterSelectedParams, - ZHAEntitySelectedParams, - ZHANodeSelectedParams, -} from "./types"; +import { ZHAClusterSelectedParams, ZHANodeSelectedParams } from "./types"; import "./zha-cluster-attributes"; import "./zha-cluster-commands"; import "./zha-network"; @@ -29,14 +25,12 @@ export class HaConfigZha extends LitElement { public isWide?: boolean; private _selectedNode?: HassEntity; private _selectedCluster?: Cluster; - private _selectedEntity?: HassEntity; static get properties(): PropertyDeclarations { return { hass: {}, isWide: {}, _selectedCluster: {}, - _selectedEntity: {}, _selectedNode: {}, }; } @@ -64,7 +58,6 @@ export class HaConfigZha extends LitElement { .hass="${this.hass}" @zha-cluster-selected="${this._onClusterSelected}" @zha-node-selected="${this._onNodeSelected}" - @zha-entity-selected="${this._onEntitySelected}" > ${this._selectedCluster ? html` @@ -72,7 +65,6 @@ export class HaConfigZha extends LitElement { .isWide="${this.isWide}" .hass="${this.hass}" .selectedNode="${this._selectedNode}" - .selectedEntity="${this._selectedEntity}" .selectedCluster="${this._selectedCluster}" > @@ -80,7 +72,6 @@ export class HaConfigZha extends LitElement { .isWide="${this.isWide}" .hass="${this.hass}" .selectedNode="${this._selectedNode}" - .selectedEntity="${this._selectedEntity}" .selectedCluster="${this._selectedCluster}" > ` @@ -100,13 +91,6 @@ export class HaConfigZha extends LitElement { ): void { this._selectedNode = selectedNodeEvent.detail.node; this._selectedCluster = undefined; - this._selectedEntity = undefined; - } - - private _onEntitySelected( - selectedEntityEvent: HASSDomEvent - ): void { - this._selectedEntity = selectedEntityEvent.detail.entity; } static get styles(): CSSResult[] { diff --git a/src/panels/config/zha/types.ts b/src/panels/config/zha/types.ts index 23bc9f74d7..1f006964d7 100644 --- a/src/panels/config/zha/types.ts +++ b/src/panels/config/zha/types.ts @@ -1,4 +1,3 @@ -import { HassEntity } from "home-assistant-js-websocket"; import { ZHADeviceEntity, Cluster } from "../../../data/zha"; export interface PickerTarget extends EventTarget { @@ -17,7 +16,8 @@ export interface ChangeEvent { } export interface SetAttributeServiceData { - entity_id: string; + ieee: string; + endpoint_id: number; cluster_id: number; cluster_type: string; attribute: number; @@ -26,17 +26,14 @@ export interface SetAttributeServiceData { } export interface IssueCommandServiceData { - entity_id: string; + ieee: string; + endpoint_id: number; cluster_id: number; cluster_type: string; command: number; command_type: string; } -export interface ZHAEntitySelectedParams { - entity: HassEntity; -} - export interface ZHANodeSelectedParams { node: ZHADeviceEntity; } diff --git a/src/panels/config/zha/zha-cluster-attributes.ts b/src/panels/config/zha/zha-cluster-attributes.ts index d19354cdcd..165e336dbe 100644 --- a/src/panels/config/zha/zha-cluster-attributes.ts +++ b/src/panels/config/zha/zha-cluster-attributes.ts @@ -10,7 +10,6 @@ import { import "@polymer/paper-button/paper-button"; import "@polymer/paper-card/paper-card"; import "@polymer/paper-icon-button/paper-icon-button"; -import { HassEntity } from "home-assistant-js-websocket"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/ha-service-description"; import { @@ -19,7 +18,7 @@ import { fetchAttributesForCluster, ReadAttributeServiceData, readAttributeValue, - ZHADeviceEntity, + ZHADevice, } from "../../../data/zha"; import { haStyle } from "../../../resources/ha-style"; import { HomeAssistant } from "../../../types"; @@ -34,8 +33,7 @@ export class ZHAClusterAttributes extends LitElement { public hass?: HomeAssistant; public isWide?: boolean; public showHelp: boolean; - public selectedNode?: HassEntity; - public selectedEntity?: ZHADeviceEntity; + public selectedNode?: ZHADevice; public selectedCluster?: Cluster; private _attributes: Attribute[]; private _selectedAttributeIndex: number; @@ -57,7 +55,6 @@ export class ZHAClusterAttributes extends LitElement { isWide: {}, showHelp: {}, selectedNode: {}, - selectedEntity: {}, selectedCluster: {}, _attributes: {}, _selectedAttributeIndex: {}, @@ -172,49 +169,54 @@ export class ZHAClusterAttributes extends LitElement { } private async _fetchAttributesForCluster(): Promise { - if (this.selectedEntity && this.selectedCluster && this.hass) { + if (this.selectedNode && this.selectedCluster && this.hass) { this._attributes = await fetchAttributesForCluster( this.hass, - this.selectedEntity!.entity_id, - this.selectedEntity!.device_info!.identifiers[0][1], + this.selectedNode!.ieee, + this.selectedCluster!.endpoint_id, this.selectedCluster!.id, this.selectedCluster!.type ); + this._attributes.sort((a, b) => { + return a.name.localeCompare(b.name); + }); } } private _computeReadAttributeServiceData(): | ReadAttributeServiceData | undefined { - if (!this.selectedEntity || !this.selectedCluster || !this.selectedNode) { + if (!this.selectedCluster || !this.selectedNode) { return; } return { - entity_id: this.selectedEntity!.entity_id, + ieee: this.selectedNode!.ieee, + endpoint_id: this.selectedCluster!.endpoint_id, cluster_id: this.selectedCluster!.id, cluster_type: this.selectedCluster!.type, attribute: this._attributes[this._selectedAttributeIndex].id, manufacturer: this._manufacturerCodeOverride ? parseInt(this._manufacturerCodeOverride as string, 10) - : this.selectedNode!.attributes.manufacturer_code, + : this.selectedNode!.manufacturer_code, }; } private _computeSetAttributeServiceData(): | SetAttributeServiceData | undefined { - if (!this.selectedEntity || !this.selectedCluster || !this.selectedNode) { + if (!this.selectedCluster || !this.selectedNode) { return; } return { - entity_id: this.selectedEntity!.entity_id, + ieee: this.selectedNode!.ieee, + endpoint_id: this.selectedCluster!.endpoint_id, cluster_id: this.selectedCluster!.id, cluster_type: this.selectedCluster!.type, attribute: this._attributes[this._selectedAttributeIndex].id, value: this._attributeValue, manufacturer: this._manufacturerCodeOverride ? parseInt(this._manufacturerCodeOverride as string, 10) - : this.selectedNode!.attributes.manufacturer_code, + : this.selectedNode!.manufacturer_code, }; } @@ -306,8 +308,7 @@ export class ZHAClusterAttributes extends LitElement { [hidden] { display: none; } - - `, + `, ]; } } diff --git a/src/panels/config/zha/zha-cluster-commands.ts b/src/panels/config/zha/zha-cluster-commands.ts index 398a7ff3d6..14429982f9 100644 --- a/src/panels/config/zha/zha-cluster-commands.ts +++ b/src/panels/config/zha/zha-cluster-commands.ts @@ -8,14 +8,13 @@ import { css, } from "lit-element"; import "@polymer/paper-card/paper-card"; -import { HassEntity } from "home-assistant-js-websocket"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/ha-service-description"; import { Cluster, Command, fetchCommandsForCluster, - ZHADeviceEntity, + ZHADevice, } from "../../../data/zha"; import { haStyle } from "../../../resources/ha-style"; import { HomeAssistant } from "../../../types"; @@ -29,8 +28,7 @@ import { export class ZHAClusterCommands extends LitElement { public hass?: HomeAssistant; public isWide?: boolean; - public selectedNode?: HassEntity; - public selectedEntity?: ZHADeviceEntity; + public selectedNode?: ZHADevice; public selectedCluster?: Cluster; private _showHelp: boolean; private _commands: Command[]; @@ -50,7 +48,6 @@ export class ZHAClusterCommands extends LitElement { hass: {}, isWide: {}, selectedNode: {}, - selectedEntity: {}, selectedCluster: {}, _showHelp: {}, _commands: {}, @@ -146,25 +143,29 @@ export class ZHAClusterCommands extends LitElement { } private async _fetchCommandsForCluster(): Promise { - if (this.selectedEntity && this.selectedCluster && this.hass) { + if (this.selectedNode && this.selectedCluster && this.hass) { this._commands = await fetchCommandsForCluster( this.hass, - this.selectedEntity!.entity_id, - this.selectedEntity!.device_info!.identifiers[0][1], + this.selectedNode!.ieee, + this.selectedCluster!.endpoint_id, this.selectedCluster!.id, this.selectedCluster!.type ); + this._commands.sort((a, b) => { + return a.name.localeCompare(b.name); + }); } } private _computeIssueClusterCommandServiceData(): | IssueCommandServiceData | undefined { - if (!this.selectedEntity || !this.selectedCluster) { + if (!this.selectedNode || !this.selectedCluster) { return; } return { - entity_id: this.selectedEntity!.entity_id, + ieee: this.selectedNode!.ieee, + endpoint_id: this.selectedCluster!.endpoint_id, cluster_id: this.selectedCluster!.id, cluster_type: this.selectedCluster!.type, command: this._commands[this._selectedCommandIndex].id, @@ -257,8 +258,7 @@ export class ZHAClusterCommands extends LitElement { [hidden] { display: none; } - - `, + `, ]; } } diff --git a/src/panels/config/zha/zha-clusters.ts b/src/panels/config/zha/zha-clusters.ts index d580cc49c6..c45772c510 100644 --- a/src/panels/config/zha/zha-clusters.ts +++ b/src/panels/config/zha/zha-clusters.ts @@ -11,11 +11,7 @@ import "@polymer/paper-card/paper-card"; import { fireEvent } from "../../../common/dom/fire_event"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/ha-service-description"; -import { - Cluster, - fetchClustersForZhaNode, - ZHADeviceEntity, -} from "../../../data/zha"; +import { Cluster, fetchClustersForZhaNode, ZHADevice } from "../../../data/zha"; import { haStyle } from "../../../resources/ha-style"; import { HomeAssistant } from "../../../types"; import "../ha-config-section"; @@ -31,14 +27,16 @@ declare global { } const computeClusterKey = (cluster: Cluster): string => { - return `${cluster.name} (id: ${cluster.id}, type: ${cluster.type})`; + return `${cluster.name} (Endpoint id: ${cluster.endpoint_id}, Id: ${ + cluster.id + }, Type: ${cluster.type})`; }; export class ZHAClusters extends LitElement { public hass?: HomeAssistant; public isWide?: boolean; public showHelp: boolean; - public selectedEntity?: ZHADeviceEntity; + public selectedDevice?: ZHADevice; private _selectedClusterIndex: number; private _clusters: Cluster[]; @@ -54,14 +52,14 @@ export class ZHAClusters extends LitElement { hass: {}, isWide: {}, showHelp: {}, - selectedEntity: {}, + selectedDevice: {}, _selectedClusterIndex: {}, _clusters: {}, }; } protected updated(changedProperties: PropertyValues): void { - if (changedProperties.has("selectedEntity")) { + if (changedProperties.has("selectedDevice")) { this._clusters = []; this._selectedClusterIndex = -1; fireEvent(this, "zha-cluster-selected", { @@ -103,9 +101,11 @@ export class ZHAClusters extends LitElement { if (this.hass) { this._clusters = await fetchClustersForZhaNode( this.hass, - this.selectedEntity!.entity_id, - this.selectedEntity!.device_info!.identifiers[0][1] + this.selectedDevice!.ieee ); + this._clusters.sort((a, b) => { + return a.name.localeCompare(b.name); + }); } } diff --git a/src/panels/config/zha/zha-device-card.ts b/src/panels/config/zha/zha-device-card.ts new file mode 100644 index 0000000000..449f26d956 --- /dev/null +++ b/src/panels/config/zha/zha-device-card.ts @@ -0,0 +1,118 @@ +import { + html, + LitElement, + property, + TemplateResult, + CSSResult, + css, +} from "lit-element"; +import "@polymer/paper-item/paper-icon-item"; +import "@polymer/paper-item/paper-item-body"; +import "@polymer/paper-card/paper-card"; +import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; +import "@polymer/paper-item/paper-item"; +import "@polymer/paper-listbox/paper-listbox"; +import { fireEvent } from "../../../common/dom/fire_event"; +import { haStyle } from "../../../resources/ha-style"; +import { HomeAssistant } from "../../../types"; + +import "../../../components/entity/state-badge"; +import { ZHADevice } from "../../../data/zha"; + +class ZHADeviceCard extends LitElement { + @property() public hass?: HomeAssistant; + @property() public narrow?: boolean; + @property() public device?: ZHADevice; + + protected render(): TemplateResult | void { + return html` + +
+
+
IEEE:
+
${this.device!.ieee}
+
Quirk applied:
+
${this.device!.quirk_applied}
+
Quirk:
+
${this.device!.quirk_class}
+
+
+ +
+ ${this.device!.entities.map( + (entity) => html` + + + +
${entity.name}
+
${entity.entity_id}
+
+
+ ` + )} +
+
+ `; + } + + private _openMoreInfo(ev: MouseEvent): void { + fireEvent(this, "hass-more-info", { + entityId: (ev.currentTarget as any).entity.entity_id, + }); + } + + static get styles(): CSSResult[] { + return [ + haStyle, + css` + :host(:not([narrow])) .device-entities { + max-height: 225px; + overflow: auto; + } + paper-card { + flex: 1 0 100%; + padding-bottom: 10px; + min-width: 0; + } + .device { + width: 30%; + } + .label { + font-weight: bold; + } + .info { + color: var(--secondary-text-color); + font-weight: bold; + } + dl dt { + float: left; + width: 100px; + text-align: left; + } + dt dd { + margin-left: 10px; + text-align: left; + } + paper-icon-item { + cursor: pointer; + padding-top: 4px; + padding-bottom: 4px; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "zha-device-card": ZHADeviceCard; + } +} + +customElements.define("zha-device-card", ZHADeviceCard); diff --git a/src/panels/config/zha/zha-entities.ts b/src/panels/config/zha/zha-entities.ts deleted file mode 100644 index 9b6f373f07..0000000000 --- a/src/panels/config/zha/zha-entities.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { - html, - LitElement, - PropertyDeclarations, - PropertyValues, - TemplateResult, - CSSResult, - css, -} from "lit-element"; -import "@polymer/paper-button/paper-button"; -import "@polymer/paper-item/paper-item"; -import "@polymer/paper-listbox/paper-listbox"; -import { HassEntity } from "home-assistant-js-websocket"; -import { fireEvent } from "../../../common/dom/fire_event"; -import { fetchEntitiesForZhaNode } from "../../../data/zha"; -import { haStyle } from "../../../resources/ha-style"; -import { HomeAssistant } from "../../../types"; -import { ItemSelectedEvent } from "./types"; - -declare global { - // for fire event - interface HASSDomEvents { - "zha-entity-selected": { - entity?: HassEntity; - }; - } -} - -export class ZHAEntities extends LitElement { - public hass?: HomeAssistant; - public showHelp?: boolean; - public selectedNode?: HassEntity; - private _selectedEntityIndex: number; - private _entities: HassEntity[]; - - constructor() { - super(); - this._entities = []; - this._selectedEntityIndex = -1; - } - - static get properties(): PropertyDeclarations { - return { - hass: {}, - showHelp: {}, - selectedNode: {}, - _selectedEntityIndex: {}, - _entities: {}, - }; - } - - protected updated(changedProperties: PropertyValues): void { - if (changedProperties.has("selectedNode")) { - this._entities = []; - this._selectedEntityIndex = -1; - fireEvent(this, "zha-entity-selected", { - entity: undefined, - }); - this._fetchEntitiesForZhaNode(); - } - super.update(changedProperties); - } - - protected render(): TemplateResult | void { - return html` -
- - - ${this._entities.map( - (entry) => html` - ${entry.entity_id} - ` - )} - - -
- ${this.showHelp - ? html` -
- Select entity to view per-entity options -
- ` - : ""} - ${this._selectedEntityIndex !== -1 - ? html` -
- Entity Information -
- ` - : ""} - `; - } - - private async _fetchEntitiesForZhaNode(): Promise { - if (this.hass) { - const fetchedEntities = await fetchEntitiesForZhaNode(this.hass); - this._entities = fetchedEntities[this.selectedNode!.attributes.ieee]; - } - } - - private _selectedEntityChanged(event: ItemSelectedEvent): void { - this._selectedEntityIndex = event.target!.selected; - fireEvent(this, "zha-entity-selected", { - entity: this._entities[this._selectedEntityIndex], - }); - } - - private _showEntityInformation(): void { - fireEvent(this, "hass-more-info", { - entityId: this._entities[this._selectedEntityIndex].entity_id, - }); - } - - static get styles(): CSSResult[] { - return [ - haStyle, - css` - .flex { - -ms-flex: 1 1 0.000000001px; - -webkit-flex: 1; - flex: 1; - -webkit-flex-basis: 0.000000001px; - flex-basis: 0.000000001px; - } - - .node-picker { - display: -ms-flexbox; - display: -webkit-flex; - display: flex; - -ms-flex-direction: row; - -webkit-flex-direction: row; - flex-direction: row; - -ms-flex-align: center; - -webkit-align-items: center; - align-items: center; - padding-left: 28px; - padding-right: 28px; - padding-bottom: 10px; - } - .actions { - border-top: 1px solid #e8e8e8; - padding: 5px 16px; - position: relative; - } - .actions paper-button:not([disabled]) { - color: var(--primary-color); - font-weight: 500; - } - .helpText { - color: grey; - padding: 16px; - } - `, - ]; - } -} - -declare global { - interface HTMLElementTagNameMap { - "zha-entities": ZHAEntities; - } -} - -customElements.define("zha-entities", ZHAEntities); diff --git a/src/panels/config/zha/zha-network.ts b/src/panels/config/zha/zha-network.ts index bbd70a1629..55cb4a4da3 100644 --- a/src/panels/config/zha/zha-network.ts +++ b/src/panels/config/zha/zha-network.ts @@ -102,8 +102,7 @@ export class ZHANetwork extends LitElement { [hidden] { display: none; } - - `, + `, ]; } } diff --git a/src/panels/config/zha/zha-node.ts b/src/panels/config/zha/zha-node.ts index 2c2a680b10..1dd11c8c0a 100644 --- a/src/panels/config/zha/zha-node.ts +++ b/src/panels/config/zha/zha-node.ts @@ -4,6 +4,7 @@ import { PropertyDeclarations, TemplateResult, CSSResult, + PropertyValues, css, } from "lit-element"; import "@polymer/paper-button/paper-button"; @@ -11,29 +12,22 @@ import "@polymer/paper-card/paper-card"; import "@polymer/paper-icon-button/paper-icon-button"; import "@polymer/paper-item/paper-item"; import "@polymer/paper-listbox/paper-listbox"; -import { HassEntity } from "home-assistant-js-websocket"; -import { fireEvent, HASSDomEvent } from "../../../common/dom/fire_event"; -import computeStateName from "../../../common/entity/compute_state_name"; -import sortByName from "../../../common/entity/states_sort_by_name"; +import { fireEvent } from "../../../common/dom/fire_event"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/ha-service-description"; import { haStyle } from "../../../resources/ha-style"; import { HomeAssistant } from "../../../types"; import "../ha-config-section"; -import { - ItemSelectedEvent, - NodeServiceData, - ZHAEntitySelectedParams, -} from "./types"; +import { ItemSelectedEvent, NodeServiceData } from "./types"; import "./zha-clusters"; -import "./zha-entities"; -import { reconfigureNode } from "../../../data/zha"; +import "./zha-device-card"; +import { reconfigureNode, fetchDevices, ZHADevice } from "../../../data/zha"; declare global { // for fire event interface HASSDomEvents { "zha-node-selected": { - node?: HassEntity; + node?: ZHADevice; }; } } @@ -43,10 +37,9 @@ export class ZHANode extends LitElement { public isWide?: boolean; private _showHelp: boolean; private _selectedNodeIndex: number; - private _selectedNode?: HassEntity; - private _selectedEntity?: HassEntity; + private _selectedNode?: ZHADevice; private _serviceData?: {}; - private _nodes: HassEntity[]; + private _nodes: ZHADevice[]; constructor() { super(); @@ -62,13 +55,31 @@ export class ZHANode extends LitElement { _showHelp: {}, _selectedNodeIndex: {}, _selectedNode: {}, + _entities: {}, _serviceData: {}, - _selectedEntity: {}, + _nodes: {}, }; } + public firstUpdated(changedProperties: PropertyValues): void { + super.firstUpdated(changedProperties); + if (this._nodes.length === 0) { + this._fetchDevices(); + } + this.addEventListener("hass-service-called", (ev) => + this.serviceCalled(ev) + ); + } + + protected serviceCalled(ev): void { + // Check if this is for us + if (ev.detail.success && ev.detail.service === "remove") { + this._selectedNodeIndex = -1; + this._fetchDevices(); + } + } + protected render(): TemplateResult | void { - this._nodes = this._computeNodes(this.hass); return html`
@@ -94,12 +105,11 @@ export class ZHANode extends LitElement { ${this._nodes.map( (entry) => html` - ${this._computeSelectCaption(entry)} + ${entry.name} ` )} @@ -112,9 +122,18 @@ export class ZHANode extends LitElement {
` : ""} + ${this._selectedNodeIndex !== -1 + ? html` + + ` + : ""} ${this._selectedNodeIndex !== -1 ? this._renderNodeActions() : ""} - ${this._selectedNodeIndex !== -1 ? this._renderEntities() : ""} - ${this._selectedEntity ? this._renderClusters() : ""} + ${this._selectedNode ? this._renderClusters() : ""}
`; @@ -123,9 +142,6 @@ export class ZHANode extends LitElement { private _renderNodeActions(): TemplateResult { return html`
- Node Information Reconfigure Node @@ -158,22 +174,11 @@ export class ZHANode extends LitElement { `; } - private _renderEntities(): TemplateResult { - return html` - - `; - } - private _renderClusters(): TemplateResult { return html` `; @@ -186,50 +191,26 @@ export class ZHANode extends LitElement { private _selectedNodeChanged(event: ItemSelectedEvent): void { this._selectedNodeIndex = event!.target!.selected; this._selectedNode = this._nodes[this._selectedNodeIndex]; - this._selectedEntity = undefined; fireEvent(this, "zha-node-selected", { node: this._selectedNode }); this._serviceData = this._computeNodeServiceData(); } private async _onReconfigureNodeClick(): Promise { if (this.hass) { - await reconfigureNode(this.hass, this._selectedNode!.attributes.ieee); + await reconfigureNode(this.hass, this._selectedNode!.ieee); } } - private _showNodeInformation(): void { - fireEvent(this, "hass-more-info", { - entityId: this._selectedNode!.entity_id, - }); - } - private _computeNodeServiceData(): NodeServiceData { return { - ieee_address: this._selectedNode!.attributes.ieee, + ieee_address: this._selectedNode!.ieee, }; } - private _computeSelectCaption(stateObj: HassEntity): string { - return ( - computeStateName(stateObj) + " (Node:" + stateObj.attributes.ieee + ")" - ); - } - - private _computeNodes(hass?: HomeAssistant): HassEntity[] { - if (hass) { - return Object.keys(hass.states) - .map((key) => hass.states[key]) - .filter((ent) => ent.entity_id.match("zha[.]")) - .sort(sortByName); - } else { - return []; - } - } - - private _onEntitySelected( - entitySelectedEvent: HASSDomEvent - ): void { - this._selectedEntity = entitySelectedEvent.detail.entity; + private async _fetchDevices() { + this._nodes = (await fetchDevices(this.hass!)).sort((a, b) => { + return a.name.localeCompare(b.name); + }); } static get styles(): CSSResult[] { @@ -287,6 +268,17 @@ export class ZHANode extends LitElement { padding-bottom: 10px; } + .card { + box-sizing: border-box; + display: flex; + flex: 1 0 300px; + min-width: 0; + max-width: 600px; + padding-left: 28px; + padding-right: 28px; + padding-bottom: 10px; + } + ha-service-description { display: block; color: grey; From 6faea73c9fad9de9b95389079974ff13d41c267d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 12 Feb 2019 11:56:29 -0800 Subject: [PATCH 11/66] Update translations --- translations/ca.json | 4 ++-- translations/cs.json | 4 ++++ translations/de.json | 31 +++++++++++++++++++++++++------ translations/es-419.json | 25 +++++++++++++++++++++++-- translations/es.json | 6 +++++- 5 files changed, 59 insertions(+), 11 deletions(-) diff --git a/translations/ca.json b/translations/ca.json index a341c12cc5..ffb3b45dff 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -28,7 +28,7 @@ "disarmed": "Desactivada", "armed_home": "Activada, mode a casa", "armed_away": "Activada, mode fora", - "armed_night": "Activada, mode nit", + "armed_night": "Activada, mode nocturn", "pending": "Pendent", "arming": "Activant", "disarming": "Desactivant", @@ -871,7 +871,7 @@ "disarm": "Desactivar", "arm_home": "Activar, a casa", "arm_away": "Activar, fora", - "arm_night": "Activar, nit", + "arm_night": "Activar, nocturn", "armed_custom_bypass": "Bypass personalitzat" }, "automation": { diff --git a/translations/cs.json b/translations/cs.json index 3812fff1e2..435ccbdd82 100644 --- a/translations/cs.json +++ b/translations/cs.json @@ -945,6 +945,10 @@ "script": { "last_action": "Poslední akce" }, + "sun": { + "rising": "Vychází", + "setting": "Zapadá" + }, "updater": { "title": "Pokyny pro aktualizaci" } diff --git a/translations/de.json b/translations/de.json index caacb550f7..e4e371c465 100644 --- a/translations/de.json +++ b/translations/de.json @@ -301,7 +301,8 @@ "period": "Zeitraum" }, "logbook": { - "showing_entries": "Zeige Einträge für" + "showing_entries": "Zeige Einträge für", + "period": "Zeitraum" }, "mailbox": { "empty": "Du hast keine Nachrichten", @@ -435,8 +436,11 @@ "seconds": "Sekunden" }, "geo_location": { + "label": "Geolokalisierung", "source": "Quelle", - "enter": "Betrenten", + "zone": "Zone", + "event": "Ereignis:", + "enter": "Betreten", "leave": "Verlassen" } } @@ -572,7 +576,12 @@ "caption": "ZHA", "description": "Zigbee Home Automation Netzwerkmanagement" }, + "area_registry": { + "caption": "Gebietsregister", + "description": "Überblick über alle Bereiche in Deinem Haus." + }, "entity_registry": { + "caption": "Entitätsregister", "description": "Überblick aller bekannten Elemente." } }, @@ -744,7 +753,9 @@ "add_item": "Artikel hinzufügen" }, "empty_state": { - "title": "Willkommen zu Hause" + "title": "Willkommen zu Hause", + "no_devices": "Auf dieser Seite kannst du deine Geräte steuern, es sieht jedoch so aus, als hättest du noch keine eingerichtet. Gehe zur Integrationsseite, um damit zu beginnen.", + "go_to_integrations_page": "Gehe zur Integrationsseite." } }, "editor": { @@ -776,12 +787,16 @@ "para_sure": "Bist du dir sicher, dass du die Benutzeroberfläche selbst verwalten möchtest?", "cancel": "Abbrechen", "save": "Kontrolle übernehmen" + }, + "menu": { + "raw_editor": "Raw-Konfigurationseditor" } }, "menu": { "configure_ui": "Benutzeroberfläche konfigurieren", "unused_entities": "Ungenutzte Elemente", - "help": "Hilfe" + "help": "Hilfe", + "refresh": "Aktualisieren" } } }, @@ -958,7 +973,7 @@ }, "sun": { "elevation": "Höhe", - "rising": "Aufgehend", + "rising": "Aufgang", "setting": "Untergang" }, "updater": { @@ -1014,7 +1029,11 @@ "weblink": "Weblink", "zwave": "Z-Wave", "vacuum": "Staubsauger", - "zha": "ZHA" + "zha": "ZHA", + "hassio": "Hass.io", + "homeassistant": "Home Assistant", + "lovelace": "Lovelace", + "system_health": "Systemzustand" }, "attribute": { "weather": { diff --git a/translations/es-419.json b/translations/es-419.json index 2ee15f68b6..264bbc98d8 100644 --- a/translations/es-419.json +++ b/translations/es-419.json @@ -423,6 +423,17 @@ "event": "Evento:", "enter": "Entrar", "leave": "Salir" + }, + "webhook": { + "label": "Webhook" + }, + "time_pattern": { + "hours": "Horas", + "minutes": "Minutos", + "seconds": "Hass.io" + }, + "geo_location": { + "event": "Evento:" } } }, @@ -552,6 +563,9 @@ "device_unavailable": "dispositivo no disponible", "entity_unavailable": "entidad no disponible" } + }, + "zha": { + "caption": "ZHA" } }, "profile": { @@ -726,7 +740,8 @@ "edit_card": { "header": "Configuración de la tarjeta", "save": "Guardar", - "toggle_editor": "Cambiar editor" + "toggle_editor": "Cambiar editor", + "edit": "Editar" }, "migrate": { "header": "Configuración inválida", @@ -734,6 +749,9 @@ "para_migrate": "Home Assistant puede agregar ID a todas sus tarjetas y vistas automáticamente por usted presionando el botón 'Migrar configuración'.", "migrate": "Migrar configuración" } + }, + "menu": { + "help": "Ayuda" } } }, @@ -951,7 +969,10 @@ "updater": "Actualizador", "weblink": "Enlace web", "zwave": "", - "vacuum": "Aspiradora" + "vacuum": "Aspiradora", + "zha": "ZHA", + "lovelace": "Lovelace", + "system_health": "Estado del sistema" }, "attribute": { "weather": { diff --git a/translations/es.json b/translations/es.json index 4e28024f72..2f6eb013a7 100644 --- a/translations/es.json +++ b/translations/es.json @@ -574,7 +574,10 @@ }, "zha": { "caption": "ZHA", - "description": "Gestión de red de Zigbee Home Automation" + "description": "Gestión de red de Zigbee Home Automation", + "services": { + "reconfigure": "Reconfigura el dispositivo ZHA (curar dispositivo). Usa esto si tienes problemas con el dispositivo. Si el dispositivo en cuestión es un dispositivo alimentado por batería, asegurate de que está activo y aceptando comandos cuando uses este servicio." + } }, "area_registry": { "caption": "Registro de área", @@ -754,6 +757,7 @@ }, "empty_state": { "title": "Bienvenido a casa", + "no_devices": "Esta página te permite controlar tus dispositivos, aunque parece que aún no has configurado ninguno. Dirígete a la página de integraciones para empezar.", "go_to_integrations_page": "Ir a la página de integraciones." } }, From 421e5bb1697793aeccf96e7d2194d817de29d946 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 12 Feb 2019 11:56:37 -0800 Subject: [PATCH 12/66] Bumped version to 20190212.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 19c01b4d00..85ac515d8c 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="home-assistant-frontend", - version="20190203.0", + version="20190212.0", description="The Home Assistant frontend", url="https://github.com/home-assistant/home-assistant-polymer", author="The Home Assistant Authors", From ab6cd578e8b8b9dbecbdd4cf0ae513ed5896130d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 12 Feb 2019 13:24:00 -0800 Subject: [PATCH 13/66] Add lit-plugin to recommendations (#2735) --- .vscode/extensions.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index b89fc8e595..207b186d35 100755 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,8 +1,9 @@ { - "recommendations": [ - "dbaeumer.vscode-eslint", - "eg2.tslint", - "esbenp.prettier-vscode", - "bierner.lit-html" - ] + "recommendations": [ + "dbaeumer.vscode-eslint", + "eg2.tslint", + "esbenp.prettier-vscode", + "bierner.lit-html", + "runem.lit-plugin" + ] } From e1c2cf770a0053e7e9d578714b947e284e41bd3c Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 12 Feb 2019 22:41:36 -0800 Subject: [PATCH 14/66] Convert lit ts layout (#2742) * Convert layout to TS/Lit * Further cleanup * Apply suggestions from code review Co-Authored-By: balloob * Simplify error screen --- src/layouts/ha-init-page.ts | 26 +++--------- src/layouts/hass-error-screen.js | 56 -------------------------- src/layouts/hass-error-screen.ts | 58 +++++++++++++++++++++++++++ src/layouts/hass-loading-screen.js | 57 -------------------------- src/layouts/hass-loading-screen.ts | 56 ++++++++++++++++++++++++++ src/layouts/hass-subpage.js | 40 ------------------ src/layouts/hass-subpage.ts | 52 ++++++++++++++++++++++++ src/layouts/partial-panel-resolver.ts | 12 ++---- src/panels/config/ha-panel-config.js | 2 - src/resources/ha-style.ts | 1 + 10 files changed, 176 insertions(+), 184 deletions(-) delete mode 100644 src/layouts/hass-error-screen.js create mode 100644 src/layouts/hass-error-screen.ts delete mode 100644 src/layouts/hass-loading-screen.js create mode 100644 src/layouts/hass-loading-screen.ts delete mode 100644 src/layouts/hass-subpage.js create mode 100644 src/layouts/hass-subpage.ts diff --git a/src/layouts/ha-init-page.ts b/src/layouts/ha-init-page.ts index 737346c6f4..f935abe1d9 100644 --- a/src/layouts/ha-init-page.ts +++ b/src/layouts/ha-init-page.ts @@ -1,4 +1,5 @@ import "@polymer/paper-spinner/paper-spinner-lite"; +import "@polymer/paper-button/paper-button"; import { LitElement, @@ -8,9 +9,6 @@ import { css, } from "lit-element"; -/* - * @appliesMixin LocalizeMixin - */ class HaInitPage extends LitElement { public error?: boolean; @@ -37,15 +35,14 @@ class HaInitPage extends LitElement { `; } + private _retry() { + location.reload(); + } + static get styles(): CSSResult { return css` div { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - + height: 100%; display: flex; flex-direction: column; justify-content: center; @@ -60,17 +57,6 @@ class HaInitPage extends LitElement { } `; } - - protected updated(changedProps) { - super.updated(changedProps); - if (changedProps.has("error") && this.error) { - import(/* webpackChunkName: "paper-button" */ "@polymer/paper-button/paper-button"); - } - } - - private _retry() { - location.reload(); - } } customElements.define("ha-init-page", HaInitPage); diff --git a/src/layouts/hass-error-screen.js b/src/layouts/hass-error-screen.js deleted file mode 100644 index 9c326c0e90..0000000000 --- a/src/layouts/hass-error-screen.js +++ /dev/null @@ -1,56 +0,0 @@ -import "@polymer/app-layout/app-toolbar/app-toolbar"; -import "@polymer/iron-flex-layout/iron-flex-layout-classes"; -import "@polymer/paper-button/paper-button"; -import { html } from "@polymer/polymer/lib/utils/html-tag"; -import { PolymerElement } from "@polymer/polymer/polymer-element"; - -class HassErrorScreen extends PolymerElement { - static get template() { - return html` - - -
-
[[title]]
-
-

[[error]]

- go back -
-
- `; - } - - static get properties() { - return { - title: { - type: String, - value: "Home Assistant", - }, - - error: { - type: String, - value: "Oops! It looks like something went wrong.", - }, - }; - } - - backTapped() { - history.back(); - } -} - -customElements.define("hass-error-screen", HassErrorScreen); diff --git a/src/layouts/hass-error-screen.ts b/src/layouts/hass-error-screen.ts new file mode 100644 index 0000000000..db5138b38c --- /dev/null +++ b/src/layouts/hass-error-screen.ts @@ -0,0 +1,58 @@ +import { + LitElement, + CSSResultArray, + css, + TemplateResult, + html, + property, + customElement, +} from "lit-element"; +import "./hass-subpage"; + +@customElement("hass-error-screen") +class HassErrorScreen extends LitElement { + @property() + public error?: string; + + protected render(): TemplateResult | void { + return html` + +
+

${this.error}

+ + go back + +
+
+ `; + } + + private _backTapped(): void { + history.back(); + } + + static get styles(): CSSResultArray { + return [ + css` + .content { + height: calc(100% - 64px); + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + } + + paper-button { + font-weight: bold; + color: var(--primary-color); + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hass-error-screen": HassErrorScreen; + } +} diff --git a/src/layouts/hass-loading-screen.js b/src/layouts/hass-loading-screen.js deleted file mode 100644 index d97813833b..0000000000 --- a/src/layouts/hass-loading-screen.js +++ /dev/null @@ -1,57 +0,0 @@ -import "@polymer/app-layout/app-toolbar/app-toolbar"; -import "@polymer/iron-flex-layout/iron-flex-layout-classes"; -import "@polymer/paper-spinner/paper-spinner-lite"; -import { html } from "@polymer/polymer/lib/utils/html-tag"; -import { PolymerElement } from "@polymer/polymer/polymer-element"; - -import "../components/ha-menu-button"; - -class HassLoadingScreen extends PolymerElement { - static get template() { - return html` - - -
- - -
[[title]]
-
-
- -
-
- `; - } - - static get properties() { - return { - narrow: { - type: Boolean, - value: false, - }, - - showMenu: { - type: Boolean, - value: false, - }, - - title: { - type: String, - value: "", - }, - }; - } -} - -customElements.define("hass-loading-screen", HassLoadingScreen); diff --git a/src/layouts/hass-loading-screen.ts b/src/layouts/hass-loading-screen.ts new file mode 100644 index 0000000000..6c96a88026 --- /dev/null +++ b/src/layouts/hass-loading-screen.ts @@ -0,0 +1,56 @@ +import "@polymer/app-layout/app-toolbar/app-toolbar"; +import "@polymer/paper-spinner/paper-spinner-lite"; +import { + LitElement, + TemplateResult, + html, + property, + CSSResultArray, + css, + customElement, +} from "lit-element"; +import "../components/ha-menu-button"; +import { haStyle } from "../resources/ha-style"; + +@customElement("hass-loading-screen") +class HassLoadingScreen extends LitElement { + @property({ type: Boolean }) + public narrow?: boolean; + + @property({ type: Boolean }) + public showMenu?: boolean; + + protected render(): TemplateResult | void { + return html` + + + +
+ +
+ `; + } + + static get styles(): CSSResultArray { + return [ + haStyle, + css` + .content { + height: calc(100% - 64px); + display: flex; + align-items: center; + justify-content: center; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hass-loading-screen": HassLoadingScreen; + } +} diff --git a/src/layouts/hass-subpage.js b/src/layouts/hass-subpage.js deleted file mode 100644 index ef3ba4409e..0000000000 --- a/src/layouts/hass-subpage.js +++ /dev/null @@ -1,40 +0,0 @@ -import "@polymer/app-layout/app-header-layout/app-header-layout"; -import "@polymer/app-layout/app-header/app-header"; -import "@polymer/app-layout/app-toolbar/app-toolbar"; -import "@polymer/paper-icon-button/paper-icon-button"; -import { html } from "@polymer/polymer/lib/utils/html-tag"; -import { PolymerElement } from "@polymer/polymer/polymer-element"; - -class HassSubpage extends PolymerElement { - static get template() { - return html` - - - - - -
[[header]]
- -
-
- - -
- `; - } - - static get properties() { - return { - header: String, - }; - } - - _backTapped() { - history.back(); - } -} - -customElements.define("hass-subpage", HassSubpage); diff --git a/src/layouts/hass-subpage.ts b/src/layouts/hass-subpage.ts new file mode 100644 index 0000000000..25b4b5a794 --- /dev/null +++ b/src/layouts/hass-subpage.ts @@ -0,0 +1,52 @@ +import "@polymer/app-layout/app-header-layout/app-header-layout"; +import "@polymer/app-layout/app-header/app-header"; +import "@polymer/app-layout/app-toolbar/app-toolbar"; +import "@polymer/paper-icon-button/paper-icon-button"; +import { + LitElement, + property, + TemplateResult, + html, + customElement, + CSSResult, +} from "lit-element"; +import { haStyle } from "../resources/ha-style"; + +@customElement("hass-subpage") +class HassSubpage extends LitElement { + @property() + public header?: string; + + protected render(): TemplateResult | void { + return html` + + + + +
${this.header}
+ +
+
+ + +
+ `; + } + + private _backTapped(): void { + history.back(); + } + + static get styles(): CSSResult { + return haStyle; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hass-subpage": HassSubpage; + } +} diff --git a/src/layouts/partial-panel-resolver.ts b/src/layouts/partial-panel-resolver.ts index db43495ebb..3503c79a2c 100644 --- a/src/layouts/partial-panel-resolver.ts +++ b/src/layouts/partial-panel-resolver.ts @@ -1,6 +1,7 @@ import { LitElement, html, PropertyValues, property } from "lit-element"; import "./hass-loading-screen"; +import "./hass-error-screen"; import { HomeAssistant, Panel, PanelElement, Route } from "../types"; // Cache of panel loading promises. @@ -122,11 +123,10 @@ class PartialPanelResolver extends LitElement { if (this._error) { return html` + > `; } @@ -144,13 +144,6 @@ class PartialPanelResolver extends LitElement { `; } - protected firstUpdated(changedProps: PropertyValues) { - super.firstUpdated(changedProps); - // Load it before it's needed, because it will be shown if user is offline - // and a panel has to be loaded. - import(/* webpackChunkName: "hass-error-screen" */ "./hass-error-screen"); - } - protected updated(changedProps: PropertyValues) { super.updated(changedProps); if (!this.hass) { @@ -214,6 +207,7 @@ class PartialPanelResolver extends LitElement { this._cache[panel.component_name] = this._panelEl; } + this._error = false; this._updatePanel(); }, (err) => { diff --git a/src/panels/config/ha-panel-config.js b/src/panels/config/ha-panel-config.js index 8bfd4fdb3e..726e46ae85 100644 --- a/src/panels/config/ha-panel-config.js +++ b/src/panels/config/ha-panel-config.js @@ -3,8 +3,6 @@ import "@polymer/iron-media-query/iron-media-query"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; -import "../../layouts/hass-error-screen"; - import isComponentLoaded from "../../common/config/is_component_loaded"; import EventsMixin from "../../mixins/events-mixin"; import NavigateMixin from "../../mixins/navigate-mixin"; diff --git a/src/resources/ha-style.ts b/src/resources/ha-style.ts index 0c7e1f45ae..8d903f96cc 100644 --- a/src/resources/ha-style.ts +++ b/src/resources/ha-style.ts @@ -172,6 +172,7 @@ documentContainer.innerHTML = ` --google-blue-500: #4285f4; --google-green-500: #0f9d58; --google-yellow-500: #f4b400; + --paper-spinner-color: var(--primary-color); /* for paper-slider */ --paper-green-400: #66bb6a; From 1b8c567fd7ca575528d6f8be25872aee9b3b82ab Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 12 Feb 2019 23:08:29 -0800 Subject: [PATCH 15/66] Use mwc-button instead of paper-button (#2744) * Convert from paper-button to mwc-button * Fixes * Bye paper-button * Fixes * Final fixes * Fix rebase conversion --- demo/src/custom-cards/ha-demo-card.ts | 11 +- gallery/src/demos/demo-util-long-press.ts | 11 +- hassio/src/addon-view/hassio-addon-audio.js | 4 +- hassio/src/addon-view/hassio-addon-config.js | 6 +- hassio/src/addon-view/hassio-addon-info.js | 16 +-- hassio/src/addon-view/hassio-addon-logs.js | 4 +- hassio/src/addon-view/hassio-addon-network.js | 2 +- hassio/src/dashboard/hassio-hass-update.js | 4 +- hassio/src/snapshots/hassio-snapshot.js | 10 +- hassio/src/snapshots/hassio-snapshots.js | 6 +- hassio/src/system/hassio-host-info.js | 12 +- hassio/src/system/hassio-supervisor-info.js | 6 +- hassio/src/system/hassio-supervisor-log.js | 4 +- package.json | 3 +- src/auth/ha-auth-flow.js | 6 +- src/cards/ha-persistent_notification-card.js | 8 +- src/components/buttons/ha-progress-button.js | 20 ++- src/components/ha-vacuum-state.js | 10 +- src/dialogs/ha-store-auth-card.js | 8 +- .../controls/more-info-alarm_control_panel.js | 64 +++++----- .../controls/more-info-automation.js | 8 +- .../controls/more-info-configurator.js | 6 +- .../more-info/controls/more-info-lock.js | 10 +- src/dialogs/more-info/more-info-settings.js | 8 +- src/layouts/ha-init-page.ts | 8 +- src/layouts/hass-error-screen.ts | 8 +- src/onboarding/ha-onboarding.js | 6 +- .../dialog-area-registry-detail.ts | 18 +-- .../area_registry/ha-config-area-registry.ts | 4 +- .../config/automation/ha-automation-editor.ts | 2 +- src/panels/config/cloud/cloud-alexa-pref.ts | 2 +- src/panels/config/cloud/cloud-google-pref.ts | 2 +- .../cloud/cloud-webhook-manage-dialog.ts | 8 +- src/panels/config/cloud/cloud-webhooks.ts | 6 +- .../config/cloud/ha-config-cloud-account.js | 12 +- .../config/cloud/ha-config-cloud-login.js | 2 +- .../ha-config-entries-dashboard.js | 12 +- .../config/config-entries/ha-config-flow.js | 10 +- .../config/core/ha-config-section-core.js | 12 +- .../dialog-entity-registry-detail.ts | 18 +-- src/panels/config/ha-entity-config.js | 10 +- src/panels/config/js/condition/index.js | 6 +- src/panels/config/js/script/index.js | 6 +- src/panels/config/js/trigger/index.js | 6 +- .../config/person/dialog-person-detail.ts | 18 +-- src/panels/config/person/ha-config-person.ts | 4 +- src/panels/config/script/ha-script-editor.js | 2 +- src/panels/config/users/ha-dialog-add-user.js | 4 +- src/panels/config/users/ha-user-editor.js | 9 +- .../config/zha/zha-cluster-attributes.ts | 6 +- src/panels/config/zha/zha-network.ts | 2 +- src/panels/config/zha/zha-node.ts | 6 +- src/panels/config/zwave/ha-config-zwave.js | 8 +- src/panels/config/zwave/zwave-log.js | 6 +- src/panels/dev-event/ha-panel-dev-event.js | 6 +- src/panels/dev-info/error-log-card.ts | 6 +- src/panels/dev-info/ha-panel-dev-info.ts | 4 +- src/panels/dev-mqtt/ha-panel-dev-mqtt.js | 6 +- .../dev-service/ha-panel-dev-service.js | 9 +- src/panels/dev-state/ha-panel-dev-state.js | 6 +- .../lovelace/cards/hui-alarm-panel-card.ts | 20 ++- .../lovelace/cards/hui-empty-state-card.ts | 6 +- .../lovelace/cards/hui-entity-button-card.ts | 116 ++++++++---------- .../lovelace/components/hui-card-options.ts | 8 +- .../components/hui-theme-select-editor.ts | 2 +- .../hui-configurator-notification-item.js | 6 +- .../notifications/hui-notification-drawer.js | 2 +- .../hui-notification-item-template.js | 2 +- .../notifications/hui-notifications-button.js | 2 +- .../hui-persistent-notification-item.js | 6 +- .../editor/card-editor/hui-card-picker.ts | 17 ++- .../card-editor/hui-dialog-pick-card.ts | 2 +- .../editor/card-editor/hui-edit-card.ts | 16 +-- .../lovelace/editor/hui-dialog-save-config.ts | 15 +-- .../hui-dialog-edit-lovelace.ts | 12 +- .../editor/view-editor/hui-edit-view.ts | 12 +- .../entity-rows/hui-lock-entity-row.ts | 6 +- .../entity-rows/hui-scene-entity-row.ts | 6 +- .../entity-rows/hui-script-entity-row.ts | 6 +- src/panels/lovelace/ha-panel-lovelace.ts | 8 +- src/panels/lovelace/hui-editor.ts | 12 +- src/panels/lovelace/hui-root.ts | 20 +-- .../special-rows/hui-call-service-row.ts | 8 +- .../mailbox/ha-dialog-show-audio-message.js | 2 +- src/panels/mailbox/ha-panel-mailbox.js | 2 +- src/panels/profile/ha-change-password-card.js | 6 +- .../ha-long-lived-access-tokens-card.js | 6 +- .../profile/ha-mfa-module-setup-flow.js | 14 +-- src/panels/profile/ha-mfa-modules-card.js | 12 +- src/panels/profile/ha-panel-profile.js | 6 +- src/resources/ha-style.ts | 32 +++-- src/state-summary/state-card-configurator.js | 8 +- src/state-summary/state-card-lock.js | 12 +- src/state-summary/state-card-scene.js | 8 +- src/state-summary/state-card-script.js | 8 +- src/util/show-new-frontend-toast.js | 4 +- yarn.lock | 107 ++++++++++++++-- 97 files changed, 530 insertions(+), 514 deletions(-) diff --git a/demo/src/custom-cards/ha-demo-card.ts b/demo/src/custom-cards/ha-demo-card.ts index e997d86eae..85a8bd9ced 100644 --- a/demo/src/custom-cards/ha-demo-card.ts +++ b/demo/src/custom-cards/ha-demo-card.ts @@ -7,7 +7,7 @@ import { } from "lit-element"; import { until } from "lit-html/directives/until"; import "@polymer/paper-icon-button"; -import "@polymer/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-spinner/paper-spinner-lite"; import "../../../src/components/ha-card"; import { LovelaceCard, Lovelace } from "../../../src/panels/lovelace/types"; @@ -85,7 +85,7 @@ export class HADemoCard extends LitElement implements LovelaceCard {
@@ -146,12 +146,7 @@ export class HADemoCard extends LitElement implements LovelaceCard { } .actions { - padding-left: 5px; - } - - .actions paper-button { - color: var(--primary-color); - font-weight: 500; + padding-left: 8px; } `, ]; diff --git a/gallery/src/demos/demo-util-long-press.ts b/gallery/src/demos/demo-util-long-press.ts index d3cd8ddfb0..5f09e3598f 100644 --- a/gallery/src/demos/demo-util-long-press.ts +++ b/gallery/src/demos/demo-util-long-press.ts @@ -1,5 +1,5 @@ import { html, LitElement, TemplateResult } from "lit-element"; -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "../../../src/components/ha-card"; import { longPress } from "../../../src/panels/lovelace/common/directives/long-press-directive"; @@ -11,13 +11,13 @@ export class DemoUtilLongPress extends LitElement { ${[1, 2, 3].map( () => html` - (long) press me! - + @@ -60,11 +60,6 @@ export class DemoUtilLongPress extends LitElement { margin-bottom: 16px; } - paper-button { - font-weight: bold; - color: var(--primary-color); - } - textarea { height: 50px; } diff --git a/hassio/src/addon-view/hassio-addon-audio.js b/hassio/src/addon-view/hassio-addon-audio.js index b94fab20ef..d1a4011dda 100644 --- a/hassio/src/addon-view/hassio-addon-audio.js +++ b/hassio/src/addon-view/hassio-addon-audio.js @@ -1,6 +1,6 @@ import "web-animations-js/web-animations-next-lite.min"; -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-card/paper-card"; import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; import "@polymer/paper-item/paper-item"; @@ -65,7 +65,7 @@ class HassioAddonAudio extends EventsMixin(PolymerElement) {
- Save + Save
`; diff --git a/hassio/src/addon-view/hassio-addon-config.js b/hassio/src/addon-view/hassio-addon-config.js index cdcaf8060d..a4061b8899 100644 --- a/hassio/src/addon-view/hassio-addon-config.js +++ b/hassio/src/addon-view/hassio-addon-config.js @@ -1,5 +1,5 @@ import "@polymer/iron-autogrow-textarea/iron-autogrow-textarea"; -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-card/paper-card"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -50,8 +50,8 @@ class HassioAddonConfig extends PolymerElement { data="[[resetData]]" >Reset to defaults - SaveSave diff --git a/hassio/src/addon-view/hassio-addon-info.js b/hassio/src/addon-view/hassio-addon-info.js index d4977ecd98..792407116b 100644 --- a/hassio/src/addon-view/hassio-addon-info.js +++ b/hassio/src/addon-view/hassio-addon-info.js @@ -1,5 +1,5 @@ import "@polymer/iron-icon/iron-icon"; -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-card/paper-card"; import "@polymer/paper-toggle-button/paper-toggle-button"; import { html } from "@polymer/polymer/lib/utils/html-tag"; @@ -77,7 +77,7 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) { color: white; --paper-card-header-color: white; } - paper-card.warning paper-button { + paper-card.warning mwc-button { color: white !important; } .warning { @@ -169,7 +169,7 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) { >Update @@ -219,7 +219,7 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) { Protection mode on this addon is disabled! This gives the add-on full access to the entire system, which adds security risks, and could damage your system when used incorrectly. Only disable the protection mode if you know, need AND trust the source of this addon.
- Enable Protection mode + Enable Protection mode
@@ -250,7 +250,7 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) { @@ -337,8 +337,8 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) {
diff --git a/hassio/src/addon-view/hassio-addon-logs.js b/hassio/src/addon-view/hassio-addon-logs.js index d93be1750e..154630b01e 100644 --- a/hassio/src/addon-view/hassio-addon-logs.js +++ b/hassio/src/addon-view/hassio-addon-logs.js @@ -1,4 +1,4 @@ -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-card/paper-card"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -24,7 +24,7 @@ class HassioAddonLogs extends PolymerElement {
- Refresh + Refresh
`; diff --git a/hassio/src/addon-view/hassio-addon-network.js b/hassio/src/addon-view/hassio-addon-network.js index 7cfb15f5a0..569972c81f 100644 --- a/hassio/src/addon-view/hassio-addon-network.js +++ b/hassio/src/addon-view/hassio-addon-network.js @@ -60,7 +60,7 @@ class HassioAddonNetwork extends EventsMixin(PolymerElement) { data="[[resetData]]" >Reset to defaults - Save + Save
`; diff --git a/hassio/src/dashboard/hassio-hass-update.js b/hassio/src/dashboard/hassio-hass-update.js index 20c224cb3e..aff95e523a 100644 --- a/hassio/src/dashboard/hassio-hass-update.js +++ b/hassio/src/dashboard/hassio-hass-update.js @@ -1,4 +1,4 @@ -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-card/paper-card"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -56,7 +56,7 @@ class HassioHassUpdate extends PolymerElement { Release notesRelease notes diff --git a/hassio/src/snapshots/hassio-snapshot.js b/hassio/src/snapshots/hassio-snapshot.js index e36c4c1b5b..8ea0c0e4a6 100644 --- a/hassio/src/snapshots/hassio-snapshot.js +++ b/hassio/src/snapshots/hassio-snapshot.js @@ -1,5 +1,5 @@ import "@polymer/app-layout/app-toolbar/app-toolbar"; -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-checkbox/paper-checkbox"; import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable"; import "@polymer/paper-dialog/paper-dialog"; @@ -123,12 +123,12 @@ class HassioSnapshot extends PolymerElement { class="download" title="Download snapshot" > - Restore selectedRestore selected diff --git a/hassio/src/snapshots/hassio-snapshots.js b/hassio/src/snapshots/hassio-snapshots.js index 1318853856..6bacf798a1 100644 --- a/hassio/src/snapshots/hassio-snapshots.js +++ b/hassio/src/snapshots/hassio-snapshots.js @@ -1,4 +1,4 @@ -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-card/paper-card"; import "@polymer/paper-checkbox/paper-checkbox"; import "@polymer/paper-input/paper-input"; @@ -90,10 +90,10 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
- CreateCreate
diff --git a/hassio/src/system/hassio-host-info.js b/hassio/src/system/hassio-host-info.js index 0b650e3e48..ac19fcb519 100644 --- a/hassio/src/system/hassio-host-info.js +++ b/hassio/src/system/hassio-host-info.js @@ -1,4 +1,4 @@ -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-card/paper-card"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -39,7 +39,7 @@ class HassioHostInfo extends EventsMixin(PolymerElement) { color: var(--google-red-500); margin-top: 16px; } - paper-button.info { + mwc-button.info { max-width: calc(50% - 12px); } table.info { @@ -67,13 +67,13 @@ class HassioHostInfo extends EventsMixin(PolymerElement) { - + Hardware - + diff --git a/hassio/src/system/hassio-supervisor-log.js b/hassio/src/system/hassio-supervisor-log.js index 985cc2372c..e9b48c2e48 100644 --- a/hassio/src/system/hassio-supervisor-log.js +++ b/hassio/src/system/hassio-supervisor-log.js @@ -1,4 +1,4 @@ -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-card/paper-card"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -24,7 +24,7 @@ class HassioSupervisorLog extends PolymerElement {
- Refresh + Refresh
`; diff --git a/package.json b/package.json index 111db689f4..4577c34aed 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "author": "Paulus Schoutsen (http://paulusschoutsen.nl)", "license": "Apache-2.0", "dependencies": { + "@material/mwc-button": "^0.3.6", + "@material/mwc-ripple": "^0.3.6", "@mdi/svg": "^3.0.39", "@polymer/app-layout": "^3.0.1", "@polymer/app-localize-behavior": "^3.0.1", @@ -35,7 +37,6 @@ "@polymer/iron-pages": "^3.0.1", "@polymer/iron-resizable-behavior": "^3.0.1", "@polymer/neon-animation": "^3.0.1", - "@polymer/paper-button": "^3.0.1", "@polymer/paper-card": "^3.0.1", "@polymer/paper-checkbox": "^3.0.1", "@polymer/paper-dialog": "^3.0.1", diff --git a/src/auth/ha-auth-flow.js b/src/auth/ha-auth-flow.js index 2e964fa161..100b76beab 100644 --- a/src/auth/ha-auth-flow.js +++ b/src/auth/ha-auth-flow.js @@ -1,5 +1,5 @@ import { PolymerElement } from "@polymer/polymer/polymer-element"; -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import "../components/ha-form"; import { localizeLiteMixin } from "../mixins/localize-lite-mixin"; @@ -55,8 +55,8 @@ class HaAuthFlow extends localizeLiteMixin(PolymerElement) { >
- [[_computeSubmitCaption(_step.type)]][[_computeSubmitCaption(_step.type)]]
diff --git a/src/cards/ha-persistent_notification-card.js b/src/cards/ha-persistent_notification-card.js index af594cd851..bea39bbf97 100644 --- a/src/cards/ha-persistent_notification-card.js +++ b/src/cards/ha-persistent_notification-card.js @@ -1,4 +1,4 @@ -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -38,7 +38,7 @@ class HaPersistentNotificationCard extends LocalizeMixin(PolymerElement) { ha-markdown img { max-width: 100%; } - paper-button { + mwc-button { margin: 8px; font-weight: 500; } @@ -46,8 +46,8 @@ class HaPersistentNotificationCard extends LocalizeMixin(PolymerElement) { - [[localize('ui.card.persistent_notification.dismiss')]][[localize('ui.card.persistent_notification.dismiss')]] `; diff --git a/src/components/buttons/ha-progress-button.js b/src/components/buttons/ha-progress-button.js index f7b6faccec..9f14d21d18 100644 --- a/src/components/buttons/ha-progress-button.js +++ b/src/components/buttons/ha-progress-button.js @@ -1,4 +1,4 @@ -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-spinner/paper-spinner"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -12,26 +12,22 @@ class HaProgressButton extends PolymerElement { display: inline-block; } - paper-button { + mwc-button { transition: all 1s; } - .success paper-button { - color: white; + .success mwc-button { + --mdc-theme-primary: white; background-color: var(--google-green-500); transition: none; } - .error paper-button { - color: white; + .error mwc-button { + --mdc-theme-primary: white; background-color: var(--google-red-500); transition: none; } - paper-button[disabled] { - color: #c8c8c8; - } - .progress { @apply --layout; @apply --layout-center-center; @@ -43,13 +39,13 @@ class HaProgressButton extends PolymerElement { }
- - + diff --git a/src/components/ha-vacuum-state.js b/src/components/ha-vacuum-state.js index fd8c9d7db7..5dc82224dd 100644 --- a/src/components/ha-vacuum-state.js +++ b/src/components/ha-vacuum-state.js @@ -1,4 +1,4 @@ -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -38,21 +38,21 @@ class HaVacuumState extends LocalizeMixin(PolymerElement) { static get template() { return html` - [[_computeLabel(stateObj.state, _interceptable)]][[_computeLabel(stateObj.state, _interceptable)]] `; } diff --git a/src/dialogs/ha-store-auth-card.js b/src/dialogs/ha-store-auth-card.js index 2fb802650a..d63d805498 100644 --- a/src/dialogs/ha-store-auth-card.js +++ b/src/dialogs/ha-store-auth-card.js @@ -37,11 +37,11 @@ class HaStoreAuth extends LocalizeMixin(PolymerElement) {
[[localize('ui.auth_store.ask')]]
- [[localize('ui.auth_store.decline')]][[localize('ui.auth_store.decline')]] - [[localize('ui.auth_store.confirm')]][[localize('ui.auth_store.confirm')]]
diff --git a/src/dialogs/more-info/controls/more-info-alarm_control_panel.js b/src/dialogs/more-info/controls/more-info-alarm_control_panel.js index 5f1d186474..4628041974 100644 --- a/src/dialogs/more-info/controls/more-info-alarm_control_panel.js +++ b/src/dialogs/more-info/controls/more-info-alarm_control_panel.js @@ -1,5 +1,5 @@ import "@polymer/iron-flex-layout/iron-flex-layout-classes"; -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-input/paper-input"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -27,15 +27,15 @@ class MoreInfoAlarmControlPanel extends LocalizeMixin( display: flex; flex-direction: column; } - .pad paper-button { + .pad mwc-button { width: 80px; } - .actions paper-button { + .actions mwc-button { min-width: 160px; margin-bottom: 16px; color: var(--primary-color); } - paper-button.disarm { + mwc-button.disarm { color: var(--google-red-500); } @@ -51,87 +51,87 @@ class MoreInfoAlarmControlPanel extends LocalizeMixin( @@ -139,7 +139,7 @@ class MoreInfoAlarmControlPanel extends LocalizeMixin(
`; diff --git a/src/dialogs/more-info/controls/more-info-automation.js b/src/dialogs/more-info/controls/more-info-automation.js index d65471f87d..9b06dc218c 100644 --- a/src/dialogs/more-info/controls/more-info-automation.js +++ b/src/dialogs/more-info/controls/more-info-automation.js @@ -1,4 +1,4 @@ -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -10,7 +10,7 @@ class MoreInfoAutomation extends LocalizeMixin(PolymerElement) { static get template() { return html` @@ -69,7 +69,7 @@ class HaPanelDevMqtt extends PolymerElement { >
- Publish + Publish
diff --git a/src/panels/dev-service/ha-panel-dev-service.js b/src/panels/dev-service/ha-panel-dev-service.js index f249a5de69..6505f1dc02 100644 --- a/src/panels/dev-service/ha-panel-dev-service.js +++ b/src/panels/dev-service/ha-panel-dev-service.js @@ -1,7 +1,7 @@ import "@polymer/app-layout/app-header-layout/app-header-layout"; import "@polymer/app-layout/app-header/app-header"; import "@polymer/app-layout/app-toolbar/app-toolbar"; -import "@polymer/paper-button/paper-button"; +import "@material/mwc-button"; import "@polymer/paper-input/paper-textarea"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -131,11 +131,8 @@ class HaPanelDevService extends PolymerElement { autocomplete="off" spellcheck="false" > - Call ServiceCall Service