From 2f36304f069eb971550763690f621eb99611d16d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 24 Apr 2019 12:51:41 -0700 Subject: [PATCH 01/10] Move picking new integration into dialog (#3110) --- src/data/config_entries.ts | 12 +++ src/dialogs/config-flow/dialog-config-flow.ts | 102 +++++++++++++----- .../config-flow/show-dialog-config-flow.ts | 3 - src/dialogs/config-flow/step-flow-form.ts | 2 + .../config-flow/step-flow-pick-handler.ts | 67 ++++++++++++ .../ha-config-entries-dashboard.js | 63 +++++++---- 6 files changed, 199 insertions(+), 50 deletions(-) create mode 100644 src/dialogs/config-flow/step-flow-pick-handler.ts diff --git a/src/data/config_entries.ts b/src/data/config_entries.ts index 48618bdc80..3741fea239 100644 --- a/src/data/config_entries.ts +++ b/src/data/config_entries.ts @@ -6,6 +6,12 @@ export interface FieldSchema { optional: boolean; } +export interface ConfigFlowProgress { + flow_id: string; + handler: string; + context: { [key: string]: any }; +} + export interface ConfigFlowStepForm { type: "form"; flow_id: string; @@ -62,3 +68,9 @@ export const handleConfigFlowStep = ( export const deleteConfigFlow = (hass: HomeAssistant, flowId: string) => hass.callApi("DELETE", `config/config_entries/flow/${flowId}`); + +export const getConfigFlowsInProgress = (hass: HomeAssistant) => + hass.callApi("GET", "config/config_entries/flow"); + +export const getConfigFlowHandlers = (hass: HomeAssistant) => + hass.callApi("GET", "config/config_entries/flow_handlers"); diff --git a/src/dialogs/config-flow/dialog-config-flow.ts b/src/dialogs/config-flow/dialog-config-flow.ts index 37c1b1b7d6..3b495419d8 100644 --- a/src/dialogs/config-flow/dialog-config-flow.ts +++ b/src/dialogs/config-flow/dialog-config-flow.ts @@ -23,13 +23,14 @@ import { HaPaperDialog } from "../../components/dialog/ha-paper-dialog"; import { haStyleDialog } from "../../resources/styles"; import { fetchConfigFlow, - createConfigFlow, ConfigFlowStep, deleteConfigFlow, + getConfigFlowHandlers, } from "../../data/config_entries"; import { PolymerChangedEvent } from "../../polymer-types"; import { HaConfigFlowParams } from "./show-dialog-config-flow"; +import "./step-flow-pick-handler"; import "./step-flow-loading"; import "./step-flow-form"; import "./step-flow-abort"; @@ -39,6 +40,7 @@ import { fetchDeviceRegistry, } from "../../data/device_registry"; import { AreaRegistryEntry, fetchAreaRegistry } from "../../data/area_registry"; +import { HomeAssistant } from "../../types"; let instance = 0; @@ -47,12 +49,15 @@ declare global { interface HASSDomEvents { "flow-update": { step?: ConfigFlowStep; + stepPromise?: Promise; }; } } @customElement("dialog-config-flow") class ConfigFlowDialog extends LitElement { + public hass!: HomeAssistant; + @property() private _params?: HaConfigFlowParams; @@ -62,7 +67,11 @@ class ConfigFlowDialog extends LitElement { private _instance = instance; @property() - private _step?: ConfigFlowStep; + private _step: + | ConfigFlowStep + | undefined + // Null means we need to pick a config flow + | null; @property() private _devices?: DeviceRegistryEntry[]; @@ -70,25 +79,35 @@ class ConfigFlowDialog extends LitElement { @property() private _areas?: AreaRegistryEntry[]; + @property() + private _handlers?: string[]; + public async showDialog(params: HaConfigFlowParams): Promise { this._params = params; - this._loading = true; this._instance = instance++; - const fetchStep = params.continueFlowId - ? fetchConfigFlow(params.hass, params.continueFlowId) - : params.newFlowForHandler - ? createConfigFlow(params.hass, params.newFlowForHandler) - : undefined; + // Create a new config flow. Show picker + if (!params.continueFlowId) { + this._step = null; - if (!fetchStep) { - throw new Error(`Pass in either continueFlowId or newFlorForHandler`); + // We only load the handlers once + if (this._handlers === undefined) { + this._loading = true; + this.updateComplete.then(() => this._scheduleCenterDialog()); + try { + this._handlers = await getConfigFlowHandlers(this.hass); + } finally { + this._loading = false; + } + } + await this.updateComplete; + this._scheduleCenterDialog(); + return; } + this._loading = true; const curInstance = this._instance; - - await this.updateComplete; - const step = await fetchStep; + const step = await fetchConfigFlow(this.hass, params.continueFlowId); // Happens if second showDialog called if (curInstance !== this._instance) { @@ -99,7 +118,7 @@ class ConfigFlowDialog extends LitElement { this._loading = false; // When the flow changes, center the dialog. // Don't do it on each step or else the dialog keeps bouncing. - setTimeout(() => this._dialog.center(), 0); + this._scheduleCenterDialog(); } protected render(): TemplateResult | void { @@ -113,7 +132,7 @@ class ConfigFlowDialog extends LitElement { opened @opened-changed=${this._openedChanged} > - ${this._loading + ${this._loading || (this._step === null && this._handlers === undefined) ? html` ` @@ -121,18 +140,26 @@ class ConfigFlowDialog extends LitElement { ? // When we are going to next step, we render 1 round of empty // to reset the element. "" + : this._step === null + ? // Show handler picker + html` + + ` : this._step.type === "form" ? html` ` : this._step.type === "abort" ? html` ` : this._devices === undefined || this._areas === undefined @@ -143,7 +170,7 @@ class ConfigFlowDialog extends LitElement { : html` @@ -155,7 +182,8 @@ class ConfigFlowDialog extends LitElement { protected firstUpdated(changedProps: PropertyValues) { super.firstUpdated(changedProps); this.addEventListener("flow-update", (ev) => { - this._processStep((ev as any).detail.step); + const { step, stepPromise } = (ev as any).detail; + this._processStep(step || stepPromise); }); } @@ -170,6 +198,10 @@ class ConfigFlowDialog extends LitElement { } } + private _scheduleCenterDialog() { + setTimeout(() => this._dialog.center(), 0); + } + private get _dialog(): HaPaperDialog { return this.shadowRoot!.querySelector("ha-paper-dialog")!; } @@ -177,17 +209,29 @@ class ConfigFlowDialog extends LitElement { private async _fetchDevices(configEntryId) { // Wait 5 seconds to give integrations time to find devices await new Promise((resolve) => setTimeout(resolve, 5000)); - const devices = await fetchDeviceRegistry(this._params!.hass); + const devices = await fetchDeviceRegistry(this.hass); this._devices = devices.filter((device) => device.config_entries.includes(configEntryId) ); } private async _fetchAreas() { - this._areas = await fetchAreaRegistry(this._params!.hass); + this._areas = await fetchAreaRegistry(this.hass); } - private async _processStep(step: ConfigFlowStep): Promise { + private async _processStep( + step: ConfigFlowStep | undefined | Promise + ): Promise { + if (step instanceof Promise) { + this._loading = true; + try { + this._step = await step; + } finally { + this._loading = false; + } + return; + } + if (step === undefined) { this._flowDone(); return; @@ -206,8 +250,8 @@ class ConfigFlowDialog extends LitElement { ); // If we created this flow, delete it now. - if (this._step && !flowFinished && this._params.newFlowForHandler) { - deleteConfigFlow(this._params.hass, this._step.flow_id); + if (this._step && !flowFinished && !this._params.continueFlowId) { + deleteConfigFlow(this.hass, this._step.flow_id); } this._params.dialogClosedCallback({ @@ -221,8 +265,14 @@ class ConfigFlowDialog extends LitElement { private _openedChanged(ev: PolymerChangedEvent): void { // Closed dialog by clicking on the overlay - if (this._step && !ev.detail.value) { - this._flowDone(); + if (!ev.detail.value) { + if (this._step) { + this._flowDone(); + } else if (this._step === null) { + // Flow aborted during picking flow + this._step = undefined; + this._params = undefined; + } } } diff --git a/src/dialogs/config-flow/show-dialog-config-flow.ts b/src/dialogs/config-flow/show-dialog-config-flow.ts index 35f86f8c3e..a38db25f36 100644 --- a/src/dialogs/config-flow/show-dialog-config-flow.ts +++ b/src/dialogs/config-flow/show-dialog-config-flow.ts @@ -1,10 +1,7 @@ -import { HomeAssistant } from "../../types"; import { fireEvent } from "../../common/dom/fire_event"; export interface HaConfigFlowParams { - hass: HomeAssistant; continueFlowId?: string; - newFlowForHandler?: string; dialogClosedCallback: (params: { flowFinished: boolean }) => void; } diff --git a/src/dialogs/config-flow/step-flow-form.ts b/src/dialogs/config-flow/step-flow-form.ts index 0a2df43164..3f5b93825b 100644 --- a/src/dialogs/config-flow/step-flow-form.ts +++ b/src/dialogs/config-flow/step-flow-form.ts @@ -167,6 +167,8 @@ class StepFlowForm extends LitElement { toSendData ); + // make sure we're still showing the same step as when we + // fired off request. if (!this.step || flowId !== this.step.flow_id) { return; } diff --git a/src/dialogs/config-flow/step-flow-pick-handler.ts b/src/dialogs/config-flow/step-flow-pick-handler.ts new file mode 100644 index 0000000000..ef64b0798a --- /dev/null +++ b/src/dialogs/config-flow/step-flow-pick-handler.ts @@ -0,0 +1,67 @@ +import { + LitElement, + TemplateResult, + html, + css, + customElement, + CSSResult, +} from "lit-element"; +import "@polymer/paper-spinner/paper-spinner-lite"; +import "@polymer/paper-item/paper-item"; +import "@polymer/paper-item/paper-item-body"; +import { HomeAssistant } from "../../types"; +import { createConfigFlow } from "../../data/config_entries"; +import { fireEvent } from "../../common/dom/fire_event"; +import "../../components/ha-icon-next"; + +@customElement("step-flow-pick-handler") +class StepFlowPickHandler extends LitElement { + public hass!: HomeAssistant; + public handlers!: string[]; + + protected render(): TemplateResult | void { + return html` +

${this.hass.localize("ui.panel.config.integrations.new")}

+
+ ${this.handlers.map( + (handler) => + html` + + + ${this.hass.localize(`component.${handler}.config.title`)} + + + + ` + )} +
+ `; + } + + private async _handlerPicked(ev) { + fireEvent(this, "flow-update", { + stepPromise: createConfigFlow(this.hass, ev.currentTarget.handler), + }); + } + + static get styles(): CSSResult { + return css` + h2 { + padding-left: 16px; + } + div { + overflow: auto; + max-height: 600px; + } + paper-item { + cursor: pointer; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "step-flow-pick-handler": StepFlowPickHandler; + } +} diff --git a/src/panels/config/integrations/ha-config-entries-dashboard.js b/src/panels/config/integrations/ha-config-entries-dashboard.js index c2720962df..e7582b6c91 100644 --- a/src/panels/config/integrations/ha-config-entries-dashboard.js +++ b/src/panels/config/integrations/ha-config-entries-dashboard.js @@ -1,6 +1,7 @@ import "@polymer/iron-flex-layout/iron-flex-layout-classes"; import "@polymer/paper-tooltip/paper-tooltip"; import "@material/mwc-button"; +import "@polymer/paper-fab/paper-fab"; import "@polymer/paper-card/paper-card"; import "@polymer/iron-icon/iron-icon"; import "@polymer/paper-item/paper-item"; @@ -13,6 +14,7 @@ import "../../../layouts/hass-subpage"; import "../../../resources/ha-style"; import "../../../components/ha-icon-next"; +import { computeRTL } from "../../../common/util/compute_rtl"; import "../ha-config-section"; import EventsMixin from "../../../mixins/events-mixin"; import LocalizeMixin from "../../../mixins/localize-mixin"; @@ -50,6 +52,28 @@ class HaConfigManagerDashboard extends LocalizeMixin( color: var(--primary-text-color); text-decoration: none; } + paper-fab { + position: fixed; + bottom: 16px; + right: 16px; + z-index: 1; + } + + paper-fab[is-wide] { + bottom: 24px; + right: 24px; + } + + paper-fab[rtl] { + right: auto; + left: 16px; + } + + paper-fab[rtl][is-wide] { + bottom: 24px; + right: auto; + left: 24px; + } - - [[localize('ui.panel.config.integrations.new')]] - - - - + `; } @@ -162,6 +176,12 @@ class HaConfigManagerDashboard extends LocalizeMixin( progress: Array, handlers: Array, + + rtl: { + type: Boolean, + reflectToAttribute: true, + computed: "_computeRTL(hass)", + }, }; } @@ -170,17 +190,14 @@ class HaConfigManagerDashboard extends LocalizeMixin( loadConfigFlowDialog(); } - _createFlow(ev) { + _createFlow() { showConfigFlowDialog(this, { - hass: this.hass, - newFlowForHandler: ev.model.item, dialogClosedCallback: () => this.fire("hass-reload-entries"), }); } _continueFlow(ev) { showConfigFlowDialog(this, { - hass: this.hass, continueFlowId: ev.model.item.flow_id, dialogClosedCallback: () => this.fire("hass-reload-entries"), }); @@ -230,6 +247,10 @@ class HaConfigManagerDashboard extends LocalizeMixin( _handleMoreInfo(ev) { this.fire("hass-more-info", { entityId: ev.model.item.entity_id }); } + + _computeRTL(hass) { + return computeRTL(hass); + } } customElements.define("ha-config-entries-dashboard", HaConfigManagerDashboard); From cd6250c495c931bf303256664b607af3459713d9 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 24 Apr 2019 21:05:38 -0700 Subject: [PATCH 02/10] Don't proxy external accessible covers (#3120) --- src/cards/ha-media_player-card.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/cards/ha-media_player-card.js b/src/cards/ha-media_player-card.js index e24f08cb68..6a08bb01c9 100644 --- a/src/cards/ha-media_player-card.js +++ b/src/cards/ha-media_player-card.js @@ -279,6 +279,14 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) { } // We have a new picture url + // If entity picture is non-relative, we use that url directly. + if (picture.substr(0, 1) !== "/") { + this._coverShowing = true; + this._coverLoadError = false; + this.$.cover.style.backgroundImage = `url(${picture})`; + return; + } + try { const { content_type: contentType, From 981dd5df633a8d11390fde2420bc43580f4db062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Fri, 26 Apr 2019 06:47:46 +0200 Subject: [PATCH 03/10] Basic input-datetime entity row (#3121) * Basic input-datetime entity row * Address review comments * Fix imports --- src/components/ha-date-input.ts | 126 +++++++++++++++++ src/components/paper-time-input.js | 2 +- src/data/input_datetime.ts | 11 ++ .../lovelace/common/create-row-element.ts | 2 + .../hui-input-datetime-entity-row.ts | 128 ++++++++++++++++++ 5 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 src/components/ha-date-input.ts create mode 100644 src/data/input_datetime.ts create mode 100644 src/panels/lovelace/entity-rows/hui-input-datetime-entity-row.ts diff --git a/src/components/ha-date-input.ts b/src/components/ha-date-input.ts new file mode 100644 index 0000000000..4157d70af9 --- /dev/null +++ b/src/components/ha-date-input.ts @@ -0,0 +1,126 @@ +import { + html, + css, + LitElement, + TemplateResult, + property, + customElement, +} from "lit-element"; + +import "@polymer/paper-input/paper-input"; +// tslint:disable-next-line:no-duplicate-imports +import { PaperInputElement } from "@polymer/paper-input/paper-input"; + +@customElement("ha-date-input") +export class HaDateInput extends LitElement { + @property() public year?: string; + @property() public month?: string; + @property() public day?: string; + @property({ type: Boolean }) public disabled = false; + + static get styles() { + return css` + :host { + display: block; + font-family: var(--paper-font-common-base_-_font-family); + -webkit-font-smoothing: var( + --paper-font-common-base_-_-webkit-font-smoothing + ); + } + + paper-input { + width: 30px; + text-align: center; + --paper-input-container-input_-_-moz-appearance: textfield; + --paper-input-container-input-webkit-spinner_-_-webkit-appearance: none; + --paper-input-container-input-webkit-spinner_-_margin: 0; + --paper-input-container-input-webkit-spinner_-_display: none; + } + + paper-input#year { + width: 50px; + } + + .date-input-wrap { + display: flex; + flex-direction: row; + } + `; + } + + protected render(): TemplateResult { + return html` +
+ + - + + + - + + + +
+ `; + } + + private _formatYear() { + const yearElement = this.shadowRoot!.getElementById( + "year" + ) as PaperInputElement; + this.year = yearElement.value!; + } + + private _formatMonth() { + const monthElement = this.shadowRoot!.getElementById( + "month" + ) as PaperInputElement; + this.month = ("0" + monthElement.value!).slice(-2); + } + + private _formatDay() { + const dayElement = this.shadowRoot!.getElementById( + "day" + ) as PaperInputElement; + this.day = ("0" + dayElement.value!).slice(-2); + } + + get value() { + return `${this.year}-${this.month}-${this.day}`; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-date-input": HaDateInput; + } +} diff --git a/src/components/paper-time-input.js b/src/components/paper-time-input.js index 59c819858a..3fec74281a 100644 --- a/src/components/paper-time-input.js +++ b/src/components/paper-time-input.js @@ -23,7 +23,7 @@ import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; -class PaperTimeInput extends PolymerElement { +export class PaperTimeInput extends PolymerElement { static get template() { return html` - - ${this.stateBadgeTemplate} - - - - - - `; - } - - static get stateBadgeTemplate() { - return html` - - `; - } - - static get properties() { - return { - hass: Object, - stateObj: Object, - inDialog: { - type: Boolean, - value: false, - }, - selectedOption: { - type: String, - observer: "selectedOptionChanged", - }, - }; - } - - _computeStateName(stateObj) { - return computeStateName(stateObj); - } - - computeSelected(stateObj) { - return stateObj.attributes.options.indexOf(stateObj.state); - } - - selectedOptionChanged(option) { - // Selected Option will transition to '' before transitioning to new value - if (option === "" || option === this.stateObj.state) { - return; - } - this.hass.callService("input_select", "select_option", { - option: option, - entity_id: this.stateObj.entity_id, - }); - } - - stopPropagation(ev) { - ev.stopPropagation(); - } -} -customElements.define("state-card-input_select", StateCardInputSelect); diff --git a/src/state-summary/state-card-input_select.ts b/src/state-summary/state-card-input_select.ts new file mode 100644 index 0000000000..19befdfb29 --- /dev/null +++ b/src/state-summary/state-card-input_select.ts @@ -0,0 +1,96 @@ +import { + LitElement, + customElement, + TemplateResult, + html, + CSSResult, + css, + property, + PropertyValues, +} from "lit-element"; +import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light"; +import "@polymer/paper-item/paper-item"; +// tslint:disable-next-line: no-duplicate-imports +import { PaperItemElement } from "@polymer/paper-item/paper-item"; +import "@polymer/paper-listbox/paper-listbox"; + +import "../components/entity/state-badge"; + +import computeStateName from "../common/entity/compute_state_name"; +import { HomeAssistant, InputSelectEntity } from "../types"; +import { setInputSelectOption } from "../data/input-select"; +import { PolymerIronSelectEvent } from "../polymer-types"; +import { stopPropagation } from "../common/dom/stop_propagation"; + +@customElement("state-card-input_select") +class StateCardInputSelect extends LitElement { + @property() public hass!: HomeAssistant; + @property() public stateObj!: InputSelectEntity; + + protected render(): TemplateResult | void { + return html` + + + + ${this.stateObj.attributes.options.map( + (option) => html` + ${option} + ` + )} + + + `; + } + + protected updated(changedProps: PropertyValues) { + super.updated(changedProps); + // Update selected after rendering the items or else it won't work in Firefox + this.shadowRoot!.querySelector( + "paper-listbox" + )!.selected = this.stateObj.attributes.options.indexOf(this.stateObj.state); + } + + private async _selectedOptionChanged( + ev: PolymerIronSelectEvent + ) { + const option = ev.detail.item.innerText; + if (option === this.stateObj.state) { + return; + } + await setInputSelectOption(this.hass, this.stateObj.entity_id, option); + } + + static get styles(): CSSResult { + return css` + :host { + display: block; + } + + state-badge { + float: left; + margin-top: 10px; + } + + paper-dropdown-menu-light { + display: block; + margin-left: 53px; + } + + paper-item { + cursor: pointer; + min-width: 200px; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "state-card-input_select": StateCardInputSelect; + } +} diff --git a/src/types.ts b/src/types.ts index e312a1f6b9..9a5a731a3b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -219,6 +219,12 @@ export type CameraEntity = HassEntityBase & { }; }; +export type InputSelectEntity = HassEntityBase & { + attributes: HassEntityAttributeBase & { + options: string[]; + }; +}; + export interface Route { prefix: string; path: string; From 2624c1544b915df99d940f8d2da43aeed3dde209 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 27 Apr 2019 22:02:47 -0700 Subject: [PATCH 08/10] Disable the show in sidebar toggle when HA < 0.92 (#3124) * Hide the show in sidebar toggle on 0.92 * Update hassio/src/addon-view/hassio-addon-info.js Co-Authored-By: balloob --- hassio/src/addon-view/hassio-addon-info.js | 78 +++++++++++++++------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/hassio/src/addon-view/hassio-addon-info.js b/hassio/src/addon-view/hassio-addon-info.js index 4ec0a959a9..6e9e8c9636 100644 --- a/hassio/src/addon-view/hassio-addon-info.js +++ b/hassio/src/addon-view/hassio-addon-info.js @@ -1,6 +1,7 @@ import "@polymer/iron-icon/iron-icon"; import "@material/mwc-button"; import "@polymer/paper-card/paper-card"; +import "@polymer/paper-tooltip/paper-tooltip"; import "@polymer/paper-toggle-button/paper-toggle-button"; import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; @@ -109,10 +110,18 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) { margin: 16px 0; display: block; } + .state { + display: flex; + margin: 8px 0; + } .state div { width: 180px; display: inline-block; } + .state iron-icon { + width: 16px; + color: var(--secondary-text-color); + } paper-toggle-button { display: inline; } @@ -156,6 +165,9 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) { margin-right: 4px; --iron-icon-height: 45px; } + .protection-enable mwc-button { + --mdc-theme-primary: white; + } + +
@@ -226,22 +250,7 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) { -
-

Add-on Security Rating

-
- Hass.io provides a security rating to each of the add-ons, which indicates the risks involved when using this add-on. The more access an add-on requires on your system, the lower the score, thus raising the possible security risks. -
+
-
Protection mode
+
+ Protection mode + + + Grant the add-on elevated system access. + +
-
@@ -580,5 +599,14 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) { this.fire("hass-api-called", eventData); }); } + + _computeCannotIngressSidebar(hass, addon) { + return !addon.ingress || !this._computeHA92plus(hass); + } + + _computeHA92plus(hass) { + const [major, minor] = hass.config.version.split(".", 2); + return Number(major) > 0 || (major === "0" && Number(minor) >= 92); + } } customElements.define("hassio-addon-info", HassioAddonInfo); From 57abd4ae0765abadb0f4e7ef5c5a61bd898d513a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 27 Apr 2019 22:08:15 -0700 Subject: [PATCH 09/10] Update translations --- translations/cy.json | 3 +++ translations/el.json | 2 +- translations/hu.json | 3 ++- translations/is.json | 37 ++++++++++++++++++++++++++++++++++++- 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/translations/cy.json b/translations/cy.json index 984277a1bf..7416302b9d 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -629,6 +629,9 @@ "password": "Cyfrinair", "create": "Creu" } + }, + "cloud": { + "description_features": "Rheolaeth oddi cartref, integreiddio gyda Alexa a Google Assistant." } }, "lovelace": { diff --git a/translations/el.json b/translations/el.json index 704c616fea..e47d0690c1 100644 --- a/translations/el.json +++ b/translations/el.json @@ -178,7 +178,7 @@ "stopped": "Σταμάτησε", "locked": "Κλειδωμένο", "unlocked": "Ξεκλείδωτο", - "ok": "Ένταξη", + "ok": "Εντάξει", "problem": "Πρόβλημα" }, "input_boolean": { diff --git a/translations/hu.json b/translations/hu.json index 5e4e7e068c..343e2b24cb 100644 --- a/translations/hu.json +++ b/translations/hu.json @@ -581,7 +581,8 @@ "cloud": { "caption": "Home Assistant Felhő", "description_login": "Bejelentkezve mint {email}", - "description_not_login": "Nincs bejelentkezve" + "description_not_login": "Nincs bejelentkezve", + "description_features": "Távoli vezérlés, Alexa és Google Assistant integráció" }, "integrations": { "caption": "Integrációk", diff --git a/translations/is.json b/translations/is.json index 245aff2d7b..9b10258be2 100644 --- a/translations/is.json +++ b/translations/is.json @@ -101,13 +101,24 @@ "gas": "Gas", "manual": "Handvirkt" }, + "cover": { + "open": "Opin", + "opening": "Opna", + "closed": "Lokað", + "closing": "Loka" + }, "device_tracker": { "home": "Heima", "not_home": "Fjarverandi" }, "group": { + "off": "Óvirkur", + "on": "Virkur", "home": "Heima", "not_home": "Fjarverandi", + "open": "Opin", + "opening": "Opna", + "closed": "Lokuð", "closing": "Loka", "stopped": "Stöðvað", "locked": "Læst", @@ -172,6 +183,7 @@ "rainy": "Rigning", "snowy": "Snjókoma", "snowy-rainy": "Slydda", + "sunny": "Sólskin", "windy": "Vindasamt", "windy-variant": "Vindasamt" }, @@ -229,12 +241,16 @@ }, "config": { "header": "Stilla af Home Assistant", + "introduction": "Hér er mögulegt að stilla af íhluti og Home Assistang. Því miður er ekki hægt að breyta öllu í gegnum viðmótið ennþá, en við erum að vinna í því.", "core": { "caption": "Almennt", "description": "Staðfesta að stillingarskráin þín sé rétt og stjórnun á miðlara", "section": { "core": { + "header": "Stillingar og stjórnun þjóns", + "introduction": "Að breyta stillingum getur verið þreytandi ferli og við vitum það. Þetta svæði mun reyna að létta þér lífið hvað það varðar.", "validation": { + "heading": "Staðfesta stillingar", "check_config": "Athuga stillingar", "valid": "Stillingar í lagi!", "invalid": "Stillingar ógildar" @@ -243,7 +259,8 @@ "heading": "Endurhleðsla stillinga", "core": "Endurhlaða inn kjarna", "group": "Endurhlaða inn hópum", - "automation": "Endurhlaða inn sjálfvirkni" + "automation": "Endurhlaða inn sjálfvirkni", + "script": "Endurhlaða inn skriftum" }, "server_management": { "heading": "Stjórnun miðlara", @@ -256,6 +273,7 @@ }, "customize": { "caption": "Séraðlögun", + "description": "Séraðlögun fyrir einingarnar þínar", "picker": { "header": "Séraðlögun" } @@ -265,6 +283,7 @@ "description": "Stofna og breyta sjálfvirkni", "picker": { "pick_automation": "Veldu sjálfvirkni sem á að breyta", + "no_automations": "Við fundum ekki neinar sjálfvirkni-skilgreiningar sem hægt er að breyta", "add_automation": "Bæta við sjálfvirkni", "learn_more": "Læra meira um sjálfvirkni" }, @@ -300,6 +319,10 @@ "mqtt": { "label": "MQTT" }, + "numeric_state": { + "above": "Yfir", + "below": "Undir" + }, "sun": { "label": "Sól", "event": "Viðburður:", @@ -348,6 +371,10 @@ "label": "Staða", "state": "Staða" }, + "numeric_state": { + "above": "Yfir", + "below": "Undir" + }, "sun": { "label": "Sól", "before": "Fyrir:", @@ -656,6 +683,7 @@ } }, "page-onboarding": { + "intro": "Ertu tilbúinn að vekja heimilið þitt, endurheimta friðhelgi þína og gerast þáttakandi í samfélagi grúskara á heimsvísu?", "user": { "intro": "Hefjumst handa með því að byrja á að stona notanda aðgang.", "required_field": "Skilyrt", @@ -896,6 +924,7 @@ "confirm": "Vista innskráningu" }, "notification_drawer": { + "click_to_configure": "Smelltu á hnappinn til að stilla {entity}", "empty": "Engar tilkynningar", "title": "Tilkynningar" } @@ -904,11 +933,16 @@ "automation": "Sjálfvirkni", "calendar": "Dagatal", "camera": "Myndavél", + "climate": "Loftslag", "configurator": "Stillingarálfur", "conversation": "Samtal", "cover": "Gluggatjöld", "fan": "Vifta", "group": "Hópur", + "input_datetime": "Innsláttar dagsetning\/tími", + "input_select": "Innsláttarval", + "input_number": "Innsláttarnúmer", + "input_text": "Innsláttartexti", "light": "Ljós", "lock": "Lás", "mailbox": "Pósthólf", @@ -917,6 +951,7 @@ "plant": "Planta", "proximity": "Nálægð", "scene": "Sena", + "script": "Skrifta", "sensor": "Skynjari", "sun": "Sól", "switch": "Rofi", From 1e85880d7b38816dbdb80b816d8fa3cf2dfb40a8 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 27 Apr 2019 22:08:20 -0700 Subject: [PATCH 10/10] Bumped version to 20190427.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index bbb3e0c5cd..0e754b6250 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="home-assistant-frontend", - version="20190424.0", + version="20190427.0", description="The Home Assistant frontend", url="https://github.com/home-assistant/home-assistant-polymer", author="The Home Assistant Authors",