Merge pull request #2787 from home-assistant/dev

20190218.0
This commit is contained in:
Paulus Schoutsen 2019-02-18 13:16:19 -08:00 committed by GitHub
commit 197cf0f8cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 1001 additions and 820 deletions

View File

@ -1,7 +1,7 @@
{ {
"recommendations": [ "recommendations": [
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"eg2.tslint", "ms-vscode.vscode-typescript-tslint-plugin",
"esbenp.prettier-vscode", "esbenp.prettier-vscode",
"bierner.lit-html", "bierner.lit-html",
"runem.lit-plugin" "runem.lit-plugin"

View File

@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup( setup(
name="home-assistant-frontend", name="home-assistant-frontend",
version="20190216.0", version="20190218.0",
description="The Home Assistant frontend", description="The Home Assistant frontend",
url="https://github.com/home-assistant/home-assistant-polymer", url="https://github.com/home-assistant/home-assistant-polymer",
author="The Home Assistant Authors", author="The Home Assistant Authors",

View File

@ -40,7 +40,6 @@ class HaPersistentNotificationCard extends LocalizeMixin(PolymerElement) {
} }
mwc-button { mwc-button {
margin: 8px; margin: 8px;
font-weight: 500;
} }
</style> </style>

View File

@ -83,7 +83,7 @@ class HaSidebar extends LitElement {
${hass.user ${hass.user
? html` ? html`
<a href="/profile"> <a href="/profile">
<ha-user-badge user=${hass.user}></ha-user-badge> <ha-user-badge .user=${hass.user}></ha-user-badge>
</a> </a>
` `
: ""} : ""}

View File

@ -39,8 +39,6 @@ class HaVacuumState extends LocalizeMixin(PolymerElement) {
return html` return html`
<style> <style>
mwc-button { mwc-button {
color: var(--primary-color);
font-weight: 500;
top: 3px; top: 3px;
height: 37px; height: 37px;
margin-right: -0.57em; margin-right: -0.57em;

View File

@ -33,7 +33,6 @@ class MoreInfoAlarmControlPanel extends LocalizeMixin(
.actions mwc-button { .actions mwc-button {
min-width: 160px; min-width: 160px;
margin-bottom: 16px; margin-bottom: 16px;
color: var(--primary-color);
} }
mwc-button.disarm { mwc-button.disarm {
color: var(--google-red-500); color: var(--google-red-500);

View File

@ -10,10 +10,6 @@ class MoreInfoAutomation extends LocalizeMixin(PolymerElement) {
static get template() { static get template() {
return html` return html`
<style> <style>
mwc-button {
color: var(--primary-color);
font-weight: 500;
}
.flex { .flex {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;

View File

@ -129,10 +129,6 @@ export class CloudWebhookManageDialog extends LitElement {
button.link { button.link {
color: var(--primary-color); color: var(--primary-color);
} }
mwc-button {
color: var(--primary-color);
font-weight: 500;
}
`, `,
]; ];
} }

View File

@ -226,10 +226,6 @@ export class CloudWebhooks extends LitElement {
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
} }
mwc-button {
font-weight: 500;
color: var(--primary-color);
}
.footer { .footer {
padding: 16px; padding: 16px;
} }

View File

@ -66,10 +66,6 @@ class HaConfigCloudAccount extends EventsMixin(LocalizeMixin(PolymerElement)) {
text-transform: capitalize; text-transform: capitalize;
padding: 16px; padding: 16px;
} }
mwc-button {
color: var(--primary-color);
font-weight: 500;
}
</style> </style>
<hass-subpage header="Home Assistant Cloud"> <hass-subpage header="Home Assistant Cloud">
<div class="content"> <div class="content">

View File

@ -30,8 +30,6 @@ class HaConfigManagerDashboard extends LocalizeMixin(
return html` return html`
<style include="iron-flex ha-style"> <style include="iron-flex ha-style">
mwc-button { mwc-button {
color: var(--primary-color);
font-weight: 500;
top: 3px; top: 3px;
margin-right: -0.57em; margin-right: -0.57em;
} }

View File

@ -19,10 +19,7 @@ import {
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-label-badge"; import "../../../components/ha-label-badge";
import { import "../components/hui-warning";
createErrorCardConfig,
createErrorCardElement,
} from "./hui-error-card";
const ICONS = { const ICONS = {
armed_away: "hass:shield-lock", armed_away: "hass:shield-lock",
@ -107,11 +104,14 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
const stateObj = this.hass.states[this._config.entity]; const stateObj = this.hass.states[this._config.entity];
if (!stateObj) { if (!stateObj) {
const element = createErrorCardElement(
createErrorCardConfig("Entity not Found!", this._config)
);
return html` return html`
${element} <hui-warning
>${this.hass.localize(
"ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
@ -290,7 +290,6 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
} }
.actions mwc-button { .actions mwc-button {
min-width: calc(var(--base-unit) * 9); min-width: calc(var(--base-unit) * 9);
color: var(--primary-color);
margin: 0 4px; margin: 0 4px;
} }
mwc-button#disarm { mwc-button#disarm {

View File

@ -73,8 +73,6 @@ export class HuiEmptyStateCard extends LitElement implements LovelaceCard {
mwc-button { mwc-button {
margin-left: -8px; margin-left: -8px;
font-weight: 500;
color: var(--primary-color);
} }
`; `;
} }

View File

@ -12,6 +12,7 @@ import { styleMap } from "lit-html/directives/style-map";
import "@material/mwc-ripple"; import "@material/mwc-ripple";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../components/hui-warning";
import isValidEntityId from "../../../common/entity/valid_entity_id"; import isValidEntityId from "../../../common/entity/valid_entity_id";
import stateIcon from "../../../common/entity/state_icon"; import stateIcon from "../../../common/entity/state_icon";
@ -91,9 +92,13 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<div class="not-found"> <hui-warning
Entity not available: ${this._config.entity} >${this.hass.localize(
</div> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
@ -157,11 +162,6 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard {
ha-icon[data-state="unavailable"] { ha-icon[data-state="unavailable"] {
color: var(--state-icon-unavailable-color); color: var(--state-icon-unavailable-color);
} }
.not-found {
flex: 1;
background-color: yellow;
padding: 8px;
}
`; `;
} }

View File

@ -1,27 +1,27 @@
import { import {
html, html,
LitElement, LitElement,
PropertyDeclarations,
PropertyValues, PropertyValues,
TemplateResult, TemplateResult,
css,
CSSResult,
property,
} from "lit-element"; } from "lit-element";
import { styleMap } from "lit-html/directives/style-map"; import { styleMap } from "lit-html/directives/style-map";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../components/hui-warning";
import { LovelaceCardConfig } from "../../../data/lovelace"; import { LovelaceCardConfig } from "../../../data/lovelace";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { hasConfigOrEntityChanged } from "../common/has-changed"; import { hasConfigOrEntityChanged } from "../common/has-changed";
import { LovelaceCard, LovelaceCardEditor } from "../types";
import isValidEntityId from "../../../common/entity/valid_entity_id"; import isValidEntityId from "../../../common/entity/valid_entity_id";
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
import computeStateName from "../../../common/entity/compute_state_name"; import computeStateName from "../../../common/entity/compute_state_name";
import { LovelaceCard, LovelaceCardEditor } from "../types";
import {
createErrorCardConfig,
createErrorCardElement,
} from "./hui-error-card";
export interface SeverityConfig { export interface SeverityConfig {
green?: number; green?: number;
yellow?: number; yellow?: number;
@ -54,17 +54,10 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
return {}; return {};
} }
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: Config; @property() private _config?: Config;
private _updated?: boolean; private _updated?: boolean;
static get properties(): PropertyDeclarations {
return {
hass: {},
_config: {},
};
}
public getCardSize(): number { public getCardSize(): number {
return 2; return 2;
} }
@ -88,57 +81,59 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
if (!this._config || !this.hass) { if (!this._config || !this.hass) {
return html``; return html``;
} }
const stateObj = this.hass.states[this._config.entity]; const stateObj = this.hass.states[this._config.entity];
let state;
let error;
if (!stateObj) { if (!stateObj) {
error = "Entity not available: " + this._config.entity; return html`
} else { <hui-warning
state = Number(stateObj.state); >${this.hass.localize(
"ui.panel.lovelace.warning.entity_not_found",
if (isNaN(state)) { "entity",
error = "Entity is non-numeric: " + this._config.entity; this._config.entity
} )}</hui-warning
>
`;
} }
if (error) { const state = Number(stateObj.state);
if (isNaN(state)) {
return html` return html`
${createErrorCardElement(createErrorCardConfig(error, this._config))} <hui-warning
>${this.hass.localize(
"ui.panel.lovelace.warning.entity_non_numeric",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
return html` return html`
${this.renderStyle()}
<ha-card @click="${this._handleClick}"> <ha-card @click="${this._handleClick}">
${error <div class="container">
? html` <div class="gauge-a"></div>
<div class="not-found">${error}</div> <div class="gauge-b"></div>
` <div
: html` class="gauge-c"
<div class="container"> style="${styleMap({
<div class="gauge-a"></div> transform: `rotate(${this._translateTurn(state)}turn)`,
<div class="gauge-b"></div> "background-color": this._computeSeverity(state),
<div })}"
class="gauge-c" ></div>
style="${styleMap({ <div class="gauge-data">
transform: `rotate(${this._translateTurn(state)}turn)`, <div id="percent">
"background-color": this._computeSeverity(state), ${stateObj.state}
})}" ${this._config.unit ||
></div> stateObj.attributes.unit_of_measurement ||
<div class="gauge-data"> ""}
<div id="percent"> </div>
${stateObj.state} <div id="name">
${this._config.unit || ${this._config.name || computeStateName(stateObj)}
stateObj.attributes.unit_of_measurement || </div>
""} </div>
</div> </div>
<div id="name">
${this._config.name || computeStateName(stateObj)}
</div>
</div>
</div>
`}
</ha-card> </ha-card>
`; `;
} }
@ -225,90 +220,83 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
fireEvent(this, "hass-more-info", { entityId: this._config!.entity }); fireEvent(this, "hass-more-info", { entityId: this._config!.entity });
} }
private renderStyle(): TemplateResult { static get styles(): CSSResult {
return html` return css`
<style> ha-card {
ha-card { --base-unit: 50px;
--base-unit: 50px; height: calc(var(--base-unit) * 3);
height: calc(var(--base-unit) * 3); position: relative;
position: relative; cursor: pointer;
cursor: pointer; }
} .container {
.container { width: calc(var(--base-unit) * 4);
width: calc(var(--base-unit) * 4); height: calc(var(--base-unit) * 2);
height: calc(var(--base-unit) * 2); position: absolute;
position: absolute; top: calc(var(--base-unit) * 1.5);
top: calc(var(--base-unit) * 1.5); left: 50%;
left: 50%; overflow: hidden;
overflow: hidden; text-align: center;
text-align: center; transform: translate(-50%, -50%);
transform: translate(-50%, -50%); }
} .gauge-a {
.gauge-a { z-index: 1;
z-index: 1; position: absolute;
position: absolute; background-color: var(--primary-background-color);
background-color: var(--primary-background-color); width: calc(var(--base-unit) * 4);
width: calc(var(--base-unit) * 4); height: calc(var(--base-unit) * 2);
height: calc(var(--base-unit) * 2); top: 0%;
top: 0%; border-radius: calc(var(--base-unit) * 2.5) calc(var(--base-unit) * 2.5)
border-radius: calc(var(--base-unit) * 2.5) 0px 0px;
calc(var(--base-unit) * 2.5) 0px 0px; }
} .gauge-b {
.gauge-b { z-index: 3;
z-index: 3; position: absolute;
position: absolute; background-color: var(--paper-card-background-color);
background-color: var(--paper-card-background-color); width: calc(var(--base-unit) * 2.5);
width: calc(var(--base-unit) * 2.5); height: calc(var(--base-unit) * 1.25);
height: calc(var(--base-unit) * 1.25); top: calc(var(--base-unit) * 0.75);
top: calc(var(--base-unit) * 0.75); margin-left: calc(var(--base-unit) * 0.75);
margin-left: calc(var(--base-unit) * 0.75); margin-right: auto;
margin-right: auto; border-radius: calc(var(--base-unit) * 2.5) calc(var(--base-unit) * 2.5)
border-radius: calc(var(--base-unit) * 2.5) 0px 0px;
calc(var(--base-unit) * 2.5) 0px 0px; }
} .gauge-c {
.gauge-c { z-index: 2;
z-index: 2; position: absolute;
position: absolute; background-color: var(--label-badge-blue);
background-color: var(--label-badge-blue); width: calc(var(--base-unit) * 4);
width: calc(var(--base-unit) * 4); height: calc(var(--base-unit) * 2);
height: calc(var(--base-unit) * 2); top: calc(var(--base-unit) * 2);
top: calc(var(--base-unit) * 2); margin-left: auto;
margin-left: auto; margin-right: auto;
margin-right: auto; border-radius: 0px 0px calc(var(--base-unit) * 2)
border-radius: 0px 0px calc(var(--base-unit) * 2) calc(var(--base-unit) * 2);
calc(var(--base-unit) * 2); transform-origin: center top;
transform-origin: center top; }
} .init .gauge-c {
.init .gauge-c { transition: all 1.3s ease-in-out;
transition: all 1.3s ease-in-out; }
} .gauge-data {
.gauge-data { z-index: 4;
z-index: 4; color: var(--primary-text-color);
color: var(--primary-text-color); line-height: calc(var(--base-unit) * 0.3);
line-height: calc(var(--base-unit) * 0.3); position: absolute;
position: absolute; width: calc(var(--base-unit) * 4);
width: calc(var(--base-unit) * 4); height: calc(var(--base-unit) * 2.1);
height: calc(var(--base-unit) * 2.1); top: calc(var(--base-unit) * 1.2);
top: calc(var(--base-unit) * 1.2); margin-left: auto;
margin-left: auto; margin-right: auto;
margin-right: auto; }
} .init .gauge-data {
.init .gauge-data { transition: all 1s ease-out;
transition: all 1s ease-out; }
} .gauge-data #percent {
.gauge-data #percent { font-size: calc(var(--base-unit) * 0.55);
font-size: calc(var(--base-unit) * 0.55); }
} .gauge-data #name {
.gauge-data #name { padding-top: calc(var(--base-unit) * 0.15);
padding-top: calc(var(--base-unit) * 0.15); font-size: calc(var(--base-unit) * 0.3);
font-size: calc(var(--base-unit) * 0.3); }
}
.not-found {
flex: 1;
background-color: yellow;
padding: 8px;
}
</style>
`; `;
} }
} }

View File

@ -13,6 +13,7 @@ import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace";
import { longPress } from "../common/directives/long-press-directive"; import { longPress } from "../common/directives/long-press-directive";
import { EntityConfig } from "../entity-rows/types"; import { EntityConfig } from "../entity-rows/types";
import { processConfigEntities } from "../common/process-config-entities"; import { processConfigEntities } from "../common/process-config-entities";
import { handleClick } from "../common/handle-click";
import computeStateDisplay from "../../../common/entity/compute_state_display"; import computeStateDisplay from "../../../common/entity/compute_state_display";
import computeStateName from "../../../common/entity/compute_state_name"; import computeStateName from "../../../common/entity/compute_state_name";
@ -21,7 +22,7 @@ import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
import "../../../components/entity/state-badge"; import "../../../components/entity/state-badge";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon"; import "../../../components/ha-icon";
import { handleClick } from "../common/handle-click"; import "../components/hui-warning";
export interface ConfigEntity extends EntityConfig { export interface ConfigEntity extends EntityConfig {
tap_action?: ActionConfig; tap_action?: ActionConfig;
@ -176,10 +177,6 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
state-badge { state-badge {
margin: 8px 0; margin: 8px 0;
} }
.not-found {
background-color: yellow;
text-align: center;
}
</style> </style>
`; `;
} }
@ -189,10 +186,13 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<div class="entity not-found"> <hui-warning
<div class="name">${entityConf.entity}</div> >${this.hass!.localize(
Entity Not Available "ui.panel.lovelace.warning.entity_not_found",
</div> "entity",
entityConf.entity
)}</hui-warning
>
`; `;
} }

View File

@ -22,6 +22,7 @@ import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon"; import "../../../components/ha-icon";
import "../components/hui-warning";
const lightConfig = { const lightConfig = {
radius: 80, radius: 80,
@ -78,41 +79,45 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
const stateObj = this.hass.states[this._config!.entity] as LightEntity; const stateObj = this.hass.states[this._config!.entity] as LightEntity;
if (!stateObj) {
return html`
<hui-warning
>${this.hass.localize(
"ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`;
}
return html` return html`
${this.renderStyle()} ${this.renderStyle()}
<ha-card> <ha-card>
${!stateObj <paper-icon-button
? html` icon="hass:dots-vertical"
<div class="not-found"> class="more-info"
Entity not available: ${this._config.entity} @click="${this._handleMoreInfo}"
</div> ></paper-icon-button>
` <div id="light"></div>
: html` <div id="tooltip">
<paper-icon-button <div class="icon-state">
icon="hass:dots-vertical" <ha-icon
class="more-info" class="light-icon"
@click="${this._handleMoreInfo}" data-state="${stateObj.state}"
></paper-icon-button> .icon="${stateIcon(stateObj)}"
<div id="light"></div> style="${styleMap({
<div id="tooltip"> filter: this._computeBrightness(stateObj),
<div class="icon-state"> color: this._computeColor(stateObj),
<ha-icon })}"
class="light-icon" @click="${this._handleTap}"
data-state="${stateObj.state}" ></ha-icon>
.icon="${stateIcon(stateObj)}" <div class="brightness" @ha-click="${this._handleTap}"></div>
style="${styleMap({ <div class="name">
filter: this._computeBrightness(stateObj), ${this._config.name || computeStateName(stateObj)}
color: this._computeColor(stateObj), </div>
})}" </div>
@click="${this._handleTap}" </div>
></ha-icon>
<div class="brightness" @ha-click="${this._handleTap}"></div>
<div class="name">
${this._config.name || computeStateName(stateObj)}
</div>
</div>
</div>
`}
</ha-card> </ha-card>
`; `;
} }
@ -272,11 +277,6 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
.show_brightness { .show_brightness {
opacity: 1; opacity: 1;
} }
.not-found {
flex: 1;
background-color: yellow;
padding: 8px;
}
.more-info { .more-info {
position: absolute; position: absolute;
cursor: pointer; cursor: pointer;

View File

@ -8,6 +8,7 @@ import { classMap } from "lit-html/directives/class-map";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../components/hui-image"; import "../components/hui-image";
import "../components/hui-warning";
import computeDomain from "../../../common/entity/compute_domain"; import computeDomain from "../../../common/entity/compute_domain";
import computeStateDisplay from "../../../common/entity/compute_state_display"; import computeStateDisplay from "../../../common/entity/compute_state_display";
@ -19,10 +20,6 @@ import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace";
import { LovelaceCard } from "../types"; import { LovelaceCard } from "../types";
import { handleClick } from "../common/handle-click"; import { handleClick } from "../common/handle-click";
import { UNAVAILABLE } from "../../../data/entity"; import { UNAVAILABLE } from "../../../data/entity";
import {
createErrorCardElement,
createErrorCardConfig,
} from "./hui-error-card";
interface Config extends LovelaceCardConfig { interface Config extends LovelaceCardConfig {
entity: string; entity: string;
@ -76,12 +73,13 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
${createErrorCardElement( <hui-warning
createErrorCardConfig( >${this.hass.localize(
`Entity not found: ${this._config.entity}`, "ui.panel.lovelace.warning.entity_not_found",
this._config "entity",
) this._config.entity
)} )}</hui-warning
>
`; `;
} }

View File

@ -12,6 +12,7 @@ import { LovelaceCard, LovelaceCardEditor } from "../types";
import { LovelaceCardConfig } from "../../../data/lovelace"; import { LovelaceCardConfig } from "../../../data/lovelace";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { fetchRecent } from "../../../data/history";
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
import computeStateName from "../../../common/entity/compute_state_name"; import computeStateName from "../../../common/entity/compute_state_name";
@ -19,7 +20,7 @@ import stateIcon from "../../../common/entity/state_icon";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon"; import "../../../components/ha-icon";
import { fetchRecent } from "../../../data/history"; import "../components/hui-warning";
const midPoint = ( const midPoint = (
_Ax: number, _Ax: number,
@ -199,15 +200,27 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
const stateObj = this.hass.states[this._config.entity]; const stateObj = this.hass.states[this._config.entity];
if (!stateObj) {
return html`
<hui-warning
>${this.hass.localize(
"ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`;
}
let graph; let graph;
if (stateObj && this._config.graph === "line") { if (stateObj && this._config.graph === "line") {
if (!stateObj.attributes.unit_of_measurement) { if (!stateObj.attributes.unit_of_measurement) {
graph = html` return html`
<div class="not-found"> <hui-warning
Entity: ${this._config.entity} - Has no Unit of Measurement and >Entity: ${this._config.entity} - Has no Unit of Measurement and
therefore can not display a line graph. therefore can not display a line graph.</hui-warning
</div> >
`; `;
} else if (!this._history) { } else if (!this._history) {
graph = svg` graph = svg`
@ -233,34 +246,26 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
return html` return html`
${this.renderStyle()} ${this.renderStyle()}
<ha-card @click="${this._handleClick}"> <ha-card @click="${this._handleClick}">
${!stateObj <div class="flex">
? html` <div class="icon">
<div class="not-found"> <ha-icon
Entity not available: ${this._config.entity} .icon="${this._config.icon || stateIcon(stateObj)}"
</div> ></ha-icon>
` </div>
: html` <div class="header">
<div class="flex"> <span class="name"
<div class="icon"> >${this._config.name || computeStateName(stateObj)}</span
<ha-icon >
.icon="${this._config.icon || stateIcon(stateObj)}" </div>
></ha-icon> </div>
</div> <div class="flex info">
<div class="header"> <span id="value">${stateObj.state}</span>
<span class="name" <span id="measurement"
>${this._config.name || computeStateName(stateObj)}</span >${this._config.unit ||
> stateObj.attributes.unit_of_measurement}</span
</div> >
</div> </div>
<div class="flex info"> <div class="graph"><div>${graph}</div></div>
<span id="value">${stateObj.state}</span>
<span id="measurement"
>${this._config.unit ||
stateObj.attributes.unit_of_measurement}</span
>
</div>
<div class="graph"><div>${graph}</div></div>
`}
</ha-card> </ha-card>
`; `;
} }
@ -399,11 +404,6 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
align-self: flex-end; align-self: flex-end;
margin: auto 8px; margin: auto 8px;
} }
.not-found {
flex: 1;
background-color: yellow;
padding: 8px;
}
</style> </style>
`; `;
} }

View File

@ -10,6 +10,7 @@ import "@polymer/paper-icon-button/paper-icon-button";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon"; import "../../../components/ha-icon";
import "../components/hui-warning";
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element";
import computeStateName from "../../../common/entity/compute_state_name"; import computeStateName from "../../../common/entity/compute_state_name";
@ -102,16 +103,19 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
return html``; return html``;
} }
const stateObj = this.hass.states[this._config.entity] as ClimateEntity; const stateObj = this.hass.states[this._config.entity] as ClimateEntity;
if (!stateObj) { if (!stateObj) {
return html` return html`
${this.renderStyle()} <hui-warning
<ha-card> >${this.hass.localize(
<div class="not-found"> "ui.panel.lovelace.warning.entity_not_found",
Entity not available: ${this._config.entity} "entity",
</div> this._config.entity
</ha-card> )}</hui-warning
>
`; `;
} }
const mode = modeIcons[stateObj.attributes.operation_mode || ""] const mode = modeIcons[stateObj.attributes.operation_mode || ""]
? stateObj.attributes.operation_mode! ? stateObj.attributes.operation_mode!
: "unknown-mode"; : "unknown-mode";
@ -280,7 +284,10 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
); );
} else { } else {
sliderValue = stateObj.attributes.temperature; sliderValue = stateObj.attributes.temperature;
uiValue = "" + stateObj.attributes.temperature; uiValue =
stateObj.attributes.temperature !== null
? String(stateObj.attributes.temperature)
: "";
} }
return [sliderValue, uiValue]; return [sliderValue, uiValue];
@ -384,11 +391,6 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
--idle-color: #8a8a8a; --idle-color: #8a8a8a;
--unknown-color: #bac; --unknown-color: #bac;
} }
.not-found {
flex: 1;
background-color: yellow;
padding: 8px;
}
#root { #root {
position: relative; position: relative;
overflow: hidden; overflow: hidden;

View File

@ -1,7 +1,3 @@
import "../../../components/entity/state-badge";
import "../../../components/ha-relative-time";
import "../../../components/ha-icon";
import computeStateName from "../../../common/entity/compute_state_name"; import computeStateName from "../../../common/entity/compute_state_name";
import { import {
LitElement, LitElement,
@ -11,10 +7,16 @@ import {
PropertyValues, PropertyValues,
property, property,
} from "lit-element"; } from "lit-element";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntitiesCardEntityConfig } from "../cards/hui-entities-card"; import { EntitiesCardEntityConfig } from "../cards/hui-entities-card";
import { computeRTL } from "../../../common/util/compute_rtl"; import { computeRTL } from "../../../common/util/compute_rtl";
import "../../../components/entity/state-badge";
import "../../../components/ha-relative-time";
import "../../../components/ha-icon";
import "../components/hui-warning";
class HuiGenericEntityRow extends LitElement { class HuiGenericEntityRow extends LitElement {
@property() public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
@property() public config?: EntitiesCardEntityConfig; @property() public config?: EntitiesCardEntityConfig;
@ -30,7 +32,13 @@ class HuiGenericEntityRow extends LitElement {
if (!stateObj) { if (!stateObj) {
return html` return html`
<div class="not-found">Entity not available: [[config.entity]]</div> <hui-warning
>${this.hass.localize(
"ui.panel.lovelace.warning.entity_not_found",
"entity",
this.config.entity
)}</hui-warning
>
`; `;
} }
@ -107,11 +115,6 @@ class HuiGenericEntityRow extends LitElement {
display: block; display: block;
color: var(--secondary-text-color); color: var(--secondary-text-color);
} }
.not-found {
flex: 1;
background-color: yellow;
padding: 8px;
}
state-badge { state-badge {
flex: 0 0 40px; flex: 0 0 40px;
} }

View File

@ -167,15 +167,14 @@ class HuiImage extends LitElement {
if (!this.hass || !this.cameraImage) { if (!this.hass || !this.cameraImage) {
return; return;
} }
if (this._cameraImageSrc) {
URL.revokeObjectURL(this._cameraImageSrc);
this._cameraImageSrc = undefined;
}
try { try {
const { content_type: contentType, content } = await fetchThumbnail( const { content_type: contentType, content } = await fetchThumbnail(
this.hass, this.hass,
this.cameraImage this.cameraImage
); );
if (this._cameraImageSrc) {
URL.revokeObjectURL(this._cameraImageSrc);
}
this._cameraImageSrc = URL.createObjectURL( this._cameraImageSrc = URL.createObjectURL(
b64toBlob(content, contentType) b64toBlob(content, contentType)
); );

View File

@ -0,0 +1,34 @@
import {
html,
LitElement,
TemplateResult,
CSSResult,
css,
customElement,
} from "lit-element";
@customElement("hui-warning")
export class HuiWarning extends LitElement {
protected render(): TemplateResult | void {
return html`
<slot></slot>
`;
}
static get styles(): CSSResult {
return css`
:host {
display: block;
color: black;
background-color: #fce588;
padding: 8px;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-warning": HuiWarning;
}
}

View File

@ -1,68 +0,0 @@
import "@material/mwc-button";
import "@polymer/paper-icon-button/paper-icon-button";
import "@polymer/app-layout/app-toolbar/app-toolbar";
import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import EventsMixin from "../../../../mixins/events-mixin";
/*
* @appliesMixin EventsMixin
*/
export class HuiNotificationsButton extends EventsMixin(PolymerElement) {
static get template() {
return html`
<style>
:host {
position: relative;
}
.indicator {
position: absolute;
top: 10px;
right: 10px;
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--accent-color);
pointer-events: none;
}
.indicator[hidden] {
display: none;
}
</style>
<paper-icon-button
icon="hass:bell"
on-click="_clicked"
></paper-icon-button>
<span
class="indicator"
hidden$="[[!_hasNotifications(notifications)]]"
></span>
`;
}
static get properties() {
return {
open: {
type: Boolean,
notify: true,
},
notifications: {
type: Array,
value: [],
},
};
}
_clicked() {
this.open = true;
}
_hasNotifications(notifications) {
return notifications.length > 0;
}
}
customElements.define("hui-notifications-button", HuiNotificationsButton);

View File

@ -0,0 +1,80 @@
import {
html,
LitElement,
TemplateResult,
css,
CSSResult,
property,
} from "lit-element";
import "@polymer/paper-icon-button/paper-icon-button";
import { fireEvent } from "../../../../common/dom/fire_event";
declare global {
// tslint:disable-next-line
interface HASSDomEvents {
"opened-changed": { value: boolean };
}
}
class HuiNotificationsButton extends LitElement {
@property() public notifications?: string[];
@property() public opened?: boolean;
protected render(): TemplateResult | void {
return html`
<paper-icon-button
icon="hass:bell"
@click="${this._clicked}"
></paper-icon-button>
${this.notifications && this.notifications.length > 0
? html`
<span class="indicator">
<div>${this.notifications.length}</div>
</span>
`
: ""}
`;
}
static get styles(): CSSResult[] {
return [
css`
:host {
position: relative;
}
.indicator {
position: absolute;
top: 0px;
right: -3px;
width: 20px;
height: 20px;
border-radius: 50%;
background: var(--accent-color);
pointer-events: none;
z-index: 1;
}
.indicator > div {
right: 7px;
top: 3px;
position: absolute;
font-size: 0.55em;
}
`,
];
}
private _clicked() {
this.opened = true;
fireEvent(this, "opened-changed", { value: this.opened });
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-notifications-button": HuiNotificationsButton;
}
}
customElements.define("hui-notifications-button", HuiNotificationsButton);

View File

@ -1,21 +1,22 @@
import { html, LitElement, TemplateResult } from "lit-element"; import {
html,
LitElement,
TemplateResult,
property,
css,
CSSResult,
} from "lit-element";
import "../../../components/ha-climate-state"; import "../../../components/ha-climate-state";
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import "../components/hui-warning";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types"; import { EntityRow, EntityConfig } from "./types";
class HuiClimateEntityRow extends LitElement implements EntityRow { class HuiClimateEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: EntityConfig; @property() private _config?: EntityConfig;
static get properties() {
return {
hass: {},
_config: {},
};
}
public setConfig(config: EntityConfig): void { public setConfig(config: EntityConfig): void {
if (!config || !config.entity) { if (!config || !config.entity) {
@ -34,14 +35,17 @@ class HuiClimateEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
return html` return html`
${this.renderStyle()}
<hui-generic-entity-row .hass="${this.hass}" .config="${this._config}"> <hui-generic-entity-row .hass="${this.hass}" .config="${this._config}">
<ha-climate-state <ha-climate-state
.hass="${this.hass}" .hass="${this.hass}"
@ -51,13 +55,11 @@ class HuiClimateEntityRow extends LitElement implements EntityRow {
`; `;
} }
private renderStyle(): TemplateResult { static get styles(): CSSResult {
return html` return css`
<style> ha-climate-state {
ha-climate-state { text-align: right;
text-align: right; }
}
</style>
`; `;
} }
} }

View File

@ -1,29 +1,24 @@
import { import {
html, html,
LitElement, LitElement,
PropertyDeclarations,
TemplateResult, TemplateResult,
property,
css,
CSSResult,
} from "lit-element"; } from "lit-element";
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import "../../../components/ha-cover-controls"; import "../../../components/ha-cover-controls";
import "../../../components/ha-cover-tilt-controls"; import "../../../components/ha-cover-tilt-controls";
import "./hui-error-entity-row"; import "../components/hui-warning";
import { isTiltOnly } from "../../../util/cover-model"; import { isTiltOnly } from "../../../util/cover-model";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types"; import { EntityRow, EntityConfig } from "./types";
class HuiCoverEntityRow extends LitElement implements EntityRow { class HuiCoverEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: EntityConfig; @property() private _config?: EntityConfig;
static get properties(): PropertyDeclarations {
return {
hass: {},
_config: {},
};
}
public setConfig(config: EntityConfig): void { public setConfig(config: EntityConfig): void {
if (!config) { if (!config) {
@ -41,14 +36,17 @@ class HuiCoverEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
return html` return html`
${this.renderStyle()}
<hui-generic-entity-row .hass="${this.hass}" .config="${this._config}"> <hui-generic-entity-row .hass="${this.hass}" .config="${this._config}">
${isTiltOnly(stateObj) ${isTiltOnly(stateObj)
? html` ? html`
@ -67,14 +65,12 @@ class HuiCoverEntityRow extends LitElement implements EntityRow {
`; `;
} }
private renderStyle(): TemplateResult { static get styles(): CSSResult {
return html` return css`
<style> ha-cover-controls,
ha-cover-controls, ha-cover-tilt-controls {
ha-cover-tilt-controls { margin-right: -0.57em;
margin-right: -0.57em; }
}
</style>
`; `;
} }
} }

View File

@ -1,41 +0,0 @@
import { html, LitElement, TemplateResult } from "lit-element";
class HuiErrorEntityRow extends LitElement {
public entity?: string;
public error?: string;
static get properties() {
return {
error: {},
entity: {},
};
}
protected render(): TemplateResult | void {
return html`
${this.renderStyle()} ${this.error || "Entity not available"}:
${this.entity || ""}
`;
}
private renderStyle(): TemplateResult {
return html`
<style>
:host {
display: block;
color: black;
background-color: yellow;
padding: 8px;
}
</style>
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-error-entity-row": HuiErrorEntityRow;
}
}
customElements.define("hui-error-entity-row", HuiErrorEntityRow);

View File

@ -1,13 +1,8 @@
import { import { html, LitElement, TemplateResult, property } from "lit-element";
html,
LitElement,
PropertyDeclarations,
TemplateResult,
} from "lit-element";
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import "../../../components/entity/ha-entity-toggle"; import "../../../components/entity/ha-entity-toggle";
import "./hui-error-entity-row"; import "../components/hui-warning";
import computeStateDisplay from "../../../common/entity/compute_state_display"; import computeStateDisplay from "../../../common/entity/compute_state_display";
import { DOMAINS_TOGGLE } from "../../../common/const"; import { DOMAINS_TOGGLE } from "../../../common/const";
@ -15,15 +10,8 @@ import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types"; import { EntityRow, EntityConfig } from "./types";
class HuiGroupEntityRow extends LitElement implements EntityRow { class HuiGroupEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: EntityConfig; @property() private _config?: EntityConfig;
static get properties(): PropertyDeclarations {
return {
hass: {},
_config: {},
};
}
public setConfig(config: EntityConfig): void { public setConfig(config: EntityConfig): void {
if (!config) { if (!config) {
@ -41,9 +29,13 @@ class HuiGroupEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }

View File

@ -1,8 +1,10 @@
import { import {
html, html,
LitElement, LitElement,
PropertyDeclarations,
TemplateResult, TemplateResult,
property,
css,
CSSResult,
} from "lit-element"; } from "lit-element";
import { repeat } from "lit-html/directives/repeat"; import { repeat } from "lit-html/directives/repeat";
import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
@ -10,7 +12,7 @@ import "@polymer/paper-item/paper-item";
import "@polymer/paper-listbox/paper-listbox"; import "@polymer/paper-listbox/paper-listbox";
import "../../../components/entity/state-badge"; import "../../../components/entity/state-badge";
import "./hui-error-entity-row"; import "../components/hui-warning";
import computeStateName from "../../../common/entity/compute_state_name"; import computeStateName from "../../../common/entity/compute_state_name";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
@ -18,15 +20,8 @@ import { EntityRow, EntityConfig } from "./types";
import { setOption } from "../../../data/input-select"; import { setOption } from "../../../data/input-select";
class HuiInputSelectEntityRow extends LitElement implements EntityRow { class HuiInputSelectEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: EntityConfig; @property() private _config?: EntityConfig;
static get properties(): PropertyDeclarations {
return {
hass: {},
_config: {},
};
}
public setConfig(config: EntityConfig): void { public setConfig(config: EntityConfig): void {
if (!config || !config.entity) { if (!config || !config.entity) {
@ -45,14 +40,17 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
return html` return html`
${this.renderStyle()}
<state-badge .stateObj="${stateObj}"></state-badge> <state-badge .stateObj="${stateObj}"></state-badge>
<paper-dropdown-menu <paper-dropdown-menu
selected-item-label="${stateObj.state}" selected-item-label="${stateObj.state}"
@ -75,18 +73,16 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
`; `;
} }
private renderStyle(): TemplateResult { static get styles(): CSSResult {
return html` return css`
<style> :host {
:host { display: flex;
display: flex; align-items: center;
align-items: center; }
} paper-dropdown-menu {
paper-dropdown-menu { margin-left: 16px;
margin-left: 16px; flex: 1;
flex: 1; }
}
</style>
`; `;
} }

View File

@ -1,28 +1,16 @@
import { import { html, LitElement, TemplateResult, property } from "lit-element";
html,
LitElement,
PropertyDeclarations,
TemplateResult,
} from "lit-element";
import { PaperInputElement } from "@polymer/paper-input/paper-input"; import { PaperInputElement } from "@polymer/paper-input/paper-input";
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import "./hui-error-entity-row"; import "../components/hui-warning";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types"; import { EntityRow, EntityConfig } from "./types";
import { setValue } from "../../../data/input_text"; import { setValue } from "../../../data/input_text";
class HuiInputTextEntityRow extends LitElement implements EntityRow { class HuiInputTextEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: EntityConfig; @property() private _config?: EntityConfig;
static get properties(): PropertyDeclarations {
return {
hass: {},
_config: {},
};
}
public setConfig(config: EntityConfig): void { public setConfig(config: EntityConfig): void {
if (!config) { if (!config) {
@ -40,9 +28,13 @@ class HuiInputTextEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }

View File

@ -1,26 +1,21 @@
import { import {
html, html,
LitElement, LitElement,
PropertyDeclarations,
TemplateResult, TemplateResult,
property,
css,
CSSResult,
} from "lit-element"; } from "lit-element";
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import "./hui-error-entity-row"; import "../components/hui-warning";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types"; import { EntityRow, EntityConfig } from "./types";
class HuiLockEntityRow extends LitElement implements EntityRow { class HuiLockEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: EntityConfig; @property() private _config?: EntityConfig;
static get properties(): PropertyDeclarations {
return {
hass: {},
_config: {},
};
}
public setConfig(config: EntityConfig): void { public setConfig(config: EntityConfig): void {
if (!config) { if (!config) {
@ -38,14 +33,17 @@ class HuiLockEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
return html` return html`
${this.renderStyle()}
<hui-generic-entity-row .hass="${this.hass}" .config="${this._config}"> <hui-generic-entity-row .hass="${this.hass}" .config="${this._config}">
<mwc-button @click="${this._callService}"> <mwc-button @click="${this._callService}">
${stateObj.state === "locked" ${stateObj.state === "locked"
@ -56,15 +54,11 @@ class HuiLockEntityRow extends LitElement implements EntityRow {
`; `;
} }
protected renderStyle(): TemplateResult { static get styles(): CSSResult {
return html` return css`
<style> mwc-button {
mwc-button { margin-right: -0.57em;
color: var(--primary-color); }
font-weight: 500;
margin-right: -0.57em;
}
</style>
`; `;
} }

View File

@ -1,7 +1,15 @@
import { html, LitElement, TemplateResult } from "lit-element"; import {
html,
LitElement,
TemplateResult,
css,
CSSResult,
property,
} from "lit-element";
import "@polymer/paper-icon-button/paper-icon-button"; import "@polymer/paper-icon-button/paper-icon-button";
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import "../components/hui-warning";
import { EntityRow, EntityConfig } from "./types"; import { EntityRow, EntityConfig } from "./types";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
@ -15,15 +23,8 @@ import {
} from "../../../data/media-player"; } from "../../../data/media-player";
class HuiMediaPlayerEntityRow extends LitElement implements EntityRow { class HuiMediaPlayerEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: EntityConfig; @property() private _config?: EntityConfig;
static get properties() {
return {
hass: {},
_config: {},
};
}
public setConfig(config: EntityConfig): void { public setConfig(config: EntityConfig): void {
if (!config || !config.entity) { if (!config || !config.entity) {
@ -42,14 +43,17 @@ class HuiMediaPlayerEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
return html` return html`
${this.renderStyle()}
<hui-generic-entity-row <hui-generic-entity-row
.hass="${this.hass}" .hass="${this.hass}"
.config="${this._config}" .config="${this._config}"
@ -89,13 +93,11 @@ class HuiMediaPlayerEntityRow extends LitElement implements EntityRow {
`; `;
} }
private renderStyle(): TemplateResult { static get styles(): CSSResult {
return html` return css`
<style> .controls {
.controls { white-space: nowrap;
white-space: nowrap; }
}
</style>
`; `;
} }

View File

@ -1,27 +1,22 @@
import { import {
html, html,
LitElement, LitElement,
PropertyDeclarations,
TemplateResult, TemplateResult,
CSSResult,
css,
property,
} from "lit-element"; } from "lit-element";
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import "../../../components/entity/ha-entity-toggle"; import "../../../components/entity/ha-entity-toggle";
import "./hui-error-entity-row"; import "../components/hui-warning";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types"; import { EntityRow, EntityConfig } from "./types";
class HuiSceneEntityRow extends LitElement implements EntityRow { class HuiSceneEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: EntityConfig; @property() private _config?: EntityConfig;
static get properties(): PropertyDeclarations {
return {
hass: {},
_config: {},
};
}
public setConfig(config: EntityConfig): void { public setConfig(config: EntityConfig): void {
if (!config) { if (!config) {
@ -39,14 +34,17 @@ class HuiSceneEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
return html` return html`
${this.renderStyle()}
<hui-generic-entity-row .hass="${this.hass}" .config="${this._config}"> <hui-generic-entity-row .hass="${this.hass}" .config="${this._config}">
${stateObj.attributes.can_cancel ${stateObj.attributes.can_cancel
? html` ? html`
@ -64,15 +62,11 @@ class HuiSceneEntityRow extends LitElement implements EntityRow {
`; `;
} }
protected renderStyle(): TemplateResult { static get styles(): CSSResult {
return html` return css`
<style> mwc-button {
mwc-button { margin-right: -0.57em;
color: var(--primary-color); }
font-weight: 500;
margin-right: -0.57em;
}
</style>
`; `;
} }

View File

@ -1,27 +1,22 @@
import { import {
html, html,
LitElement, LitElement,
PropertyDeclarations,
TemplateResult, TemplateResult,
property,
CSSResult,
css,
} from "lit-element"; } from "lit-element";
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import "../../../components/entity/ha-entity-toggle"; import "../../../components/entity/ha-entity-toggle";
import "./hui-error-entity-row"; import "../components/hui-warning";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types"; import { EntityRow, EntityConfig } from "./types";
class HuiScriptEntityRow extends LitElement implements EntityRow { class HuiScriptEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: EntityConfig; @property() private _config?: EntityConfig;
static get properties(): PropertyDeclarations {
return {
hass: {},
_config: {},
};
}
public setConfig(config: EntityConfig): void { public setConfig(config: EntityConfig): void {
if (!config) { if (!config) {
@ -39,14 +34,17 @@ class HuiScriptEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
return html` return html`
${this.renderStyle()}
<hui-generic-entity-row .hass="${this.hass}" .config="${this._config}"> <hui-generic-entity-row .hass="${this.hass}" .config="${this._config}">
${stateObj.attributes.can_cancel ${stateObj.attributes.can_cancel
? html` ? html`
@ -64,15 +62,11 @@ class HuiScriptEntityRow extends LitElement implements EntityRow {
`; `;
} }
protected renderStyle(): TemplateResult { static get styles(): CSSResult {
return html` return css`
<style> mwc-button {
mwc-button { margin-right: -0.57em;
color: var(--primary-color); }
font-weight: 500;
margin-right: -0.57em;
}
</style>
`; `;
} }

View File

@ -1,13 +1,15 @@
import { import {
html, html,
LitElement, LitElement,
PropertyDeclarations,
TemplateResult, TemplateResult,
property,
CSSResult,
css,
} from "lit-element"; } from "lit-element";
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import "../components/hui-timestamp-display"; import "../components/hui-timestamp-display";
import "./hui-error-entity-row"; import "../components/hui-warning";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types"; import { EntityRow, EntityConfig } from "./types";
@ -19,15 +21,8 @@ interface SensorEntityConfig extends EntityConfig {
} }
class HuiSensorEntityRow extends LitElement implements EntityRow { class HuiSensorEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: SensorEntityConfig; @property() private _config?: SensorEntityConfig;
static get properties(): PropertyDeclarations {
return {
hass: {},
_config: {},
};
}
public setConfig(config: SensorEntityConfig): void { public setConfig(config: SensorEntityConfig): void {
if (!config) { if (!config) {
@ -45,14 +40,17 @@ class HuiSensorEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
return html` return html`
${this.renderStyle()}
<hui-generic-entity-row .hass="${this.hass}" .config="${this._config}"> <hui-generic-entity-row .hass="${this.hass}" .config="${this._config}">
<div> <div>
${stateObj.attributes.device_class === "timestamp" ${stateObj.attributes.device_class === "timestamp"
@ -73,13 +71,11 @@ class HuiSensorEntityRow extends LitElement implements EntityRow {
`; `;
} }
private renderStyle(): TemplateResult { static get styles(): CSSResult {
return html` return css`
<style> div {
div { text-align: right;
text-align: right; }
}
</style>
`; `;
} }
} }

View File

@ -1,27 +1,22 @@
import { import {
html, html,
LitElement, LitElement,
PropertyDeclarations,
TemplateResult, TemplateResult,
property,
CSSResult,
css,
} from "lit-element"; } from "lit-element";
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import "./hui-error-entity-row"; import "../components/hui-warning";
import computeStateDisplay from "../../../common/entity/compute_state_display"; import computeStateDisplay from "../../../common/entity/compute_state_display";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types"; import { EntityRow, EntityConfig } from "./types";
class HuiTextEntityRow extends LitElement implements EntityRow { class HuiTextEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
private _config?: EntityConfig; @property() private _config?: EntityConfig;
static get properties(): PropertyDeclarations {
return {
hass: {},
_config: {},
};
}
public setConfig(config: EntityConfig): void { public setConfig(config: EntityConfig): void {
if (!config) { if (!config) {
@ -39,14 +34,17 @@ class HuiTextEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }
return html` return html`
${this.renderStyle()}
<hui-generic-entity-row .hass="${this.hass}" .config="${this._config}"> <hui-generic-entity-row .hass="${this.hass}" .config="${this._config}">
<div> <div>
${computeStateDisplay( ${computeStateDisplay(
@ -59,13 +57,11 @@ class HuiTextEntityRow extends LitElement implements EntityRow {
`; `;
} }
private renderStyle(): TemplateResult { static get styles(): CSSResult {
return html` return css`
<style> div {
div { text-align: right;
text-align: right; }
}
</style>
`; `;
} }
} }

View File

@ -1,98 +0,0 @@
import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../components/hui-generic-entity-row";
import timerTimeRemaining from "../../../common/entity/timer_time_remaining";
import secondsToDuration from "../../../common/datetime/seconds_to_duration";
class HuiTimerEntityRow extends PolymerElement {
static get template() {
return html`
<hui-generic-entity-row hass="[[hass]]" config="[[_config]]">
${this.timerControlTemplate}
</hui-generic-entity-row>
`;
}
static get timerControlTemplate() {
return html`
<div>[[_computeDisplay(_stateObj, _timeRemaining)]]</div>
`;
}
static get properties() {
return {
hass: Object,
_config: Object,
_stateObj: {
type: Object,
computed: "_computeStateObj(hass.states, _config.entity)",
observer: "_stateObjChanged",
},
_timeRemaining: Number,
};
}
disconnectedCallback() {
super.disconnectedCallback();
this._clearInterval();
}
_stateObjChanged(stateObj) {
if (stateObj) {
this._startInterval(stateObj);
} else {
this._clearInterval();
}
}
_clearInterval() {
if (this._updateRemaining) {
clearInterval(this._updateRemaining);
this._updateRemaining = null;
}
}
_startInterval(stateObj) {
this._clearInterval();
this._calculateRemaining(stateObj);
if (stateObj.state === "active") {
this._updateRemaining = setInterval(
() => this._calculateRemaining(this._stateObj),
1000
);
}
}
_calculateRemaining(stateObj) {
this._timeRemaining = timerTimeRemaining(stateObj);
}
_computeDisplay(stateObj, time) {
if (!stateObj) return null;
if (stateObj.state === "idle" || time === 0) return stateObj.state;
let display = secondsToDuration(time);
if (stateObj.state === "paused") {
display += " (paused)";
}
return display;
}
_computeStateObj(states, entityId) {
return states && entityId in states ? states[entityId] : null;
}
setConfig(config) {
if (!config || !config.entity) {
throw new Error("Entity not configured.");
}
this._config = config;
}
}
customElements.define("hui-timer-entity-row", HuiTimerEntityRow);

View File

@ -0,0 +1,128 @@
import {
html,
LitElement,
TemplateResult,
property,
PropertyValues,
} from "lit-element";
import "../components/hui-generic-entity-row";
import "../components/hui-warning";
import timerTimeRemaining from "../../../common/entity/timer_time_remaining";
import secondsToDuration from "../../../common/datetime/seconds_to_duration";
import { HomeAssistant } from "../../../types";
import { EntityConfig } from "./types";
import { HassEntity } from "home-assistant-js-websocket";
class HuiTimerEntityRow extends LitElement {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;
@property() private _timeRemaining?: number;
private _interval?: number;
public setConfig(config: EntityConfig): void {
if (!config) {
throw new Error("Configuration error");
}
this._config = config;
}
public disconnectedCallback(): void {
super.disconnectedCallback();
this._clearInterval();
}
protected render(): TemplateResult | void {
if (!this._config || !this.hass) {
return html``;
}
const stateObj = this.hass.states[this._config.entity];
if (!stateObj) {
return html`
<hui-warning
>${this.hass.localize(
"ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`;
}
return html`
<hui-generic-entity-row .hass="${this.hass}" .config="${this._config}">
<div>${this._computeDisplay(stateObj)}</div>
</hui-generic-entity-row>
`;
}
protected updated(changedProps: PropertyValues) {
super.updated(changedProps);
if (changedProps.has("hass")) {
const stateObj = this.hass!.states[this._config!.entity];
const oldHass = changedProps.get("hass") as this["hass"];
const oldStateObj = oldHass
? oldHass.states[this._config!.entity]
: undefined;
if (oldStateObj !== stateObj) {
this._startInterval(stateObj);
} else if (!stateObj) {
this._clearInterval();
}
}
}
private _clearInterval(): void {
if (this._interval) {
window.clearInterval(this._interval);
this._interval = undefined;
}
}
private _startInterval(stateObj: HassEntity): void {
this._clearInterval();
this._calculateRemaining(stateObj);
if (stateObj.state === "active") {
this._interval = window.setInterval(
() => this._calculateRemaining(stateObj),
1000
);
}
}
private _calculateRemaining(stateObj: HassEntity): void {
this._timeRemaining = timerTimeRemaining(stateObj);
}
private _computeDisplay(stateObj: HassEntity): string | null {
if (!stateObj) {
return null;
}
if (stateObj.state === "idle" || this._timeRemaining === 0) {
return this.hass!.localize("state.timer." + stateObj.state);
}
let display = secondsToDuration(this._timeRemaining || 0);
if (stateObj.state === "paused") {
display += ` (${this.hass!.localize("state.timer.paused")})`;
}
return display;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-timer-entity-row": HuiTimerEntityRow;
}
}
customElements.define("hui-timer-entity-row", HuiTimerEntityRow);

View File

@ -7,7 +7,7 @@ import {
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import "../../../components/entity/ha-entity-toggle"; import "../../../components/entity/ha-entity-toggle";
import "./hui-error-entity-row"; import "../components/hui-warning";
import computeStateDisplay from "../../../common/entity/compute_state_display"; import computeStateDisplay from "../../../common/entity/compute_state_display";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
@ -40,9 +40,13 @@ class HuiToggleEntityRow extends LitElement implements EntityRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-error-entity-row <hui-warning
.entity="${this._config.entity}" >${this.hass.localize(
></hui-error-entity-row> "ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`; `;
} }

View File

@ -73,12 +73,6 @@ class LovelacePanel extends LitElement {
if (state === "error") { if (state === "error") {
return html` return html`
<style>
mwc-button {
color: var(--primary-color);
font-weight: 500;
}
</style>
<hass-error-screen <hass-error-screen
title="Lovelace" title="Lovelace"
.error="${this._errorMsg}" .error="${this._errorMsg}"

View File

@ -186,8 +186,8 @@ class HUIRoot extends LitElement {
<div main-title>${this.config.title || "Home Assistant"}</div> <div main-title>${this.config.title || "Home Assistant"}</div>
<hui-notifications-button <hui-notifications-button
.hass="${this.hass}" .hass="${this.hass}"
.open="${this._notificationsOpen}" .opened="${this._notificationsOpen}"
@open-changed="${this._handleNotificationsOpenChanged}" @opened-changed="${this._handleNotificationsOpenChanged}"
.notifications="${this._notifications}" .notifications="${this._notifications}"
></hui-notifications-button> ></hui-notifications-button>
<ha-start-voice-button <ha-start-voice-button

View File

@ -68,8 +68,6 @@ class HuiCallServiceRow extends LitElement implements EntityRow {
text-overflow: ellipsis; text-overflow: ellipsis;
} }
mwc-button { mwc-button {
color: var(--primary-color);
font-weight: 500;
margin-right: -0.57em; margin-right: -0.57em;
} }
</style> </style>

View File

@ -37,8 +37,6 @@ class HaMfaModulesCard extends EventsMixin(LocalizeMixin(PolymerElement)) {
margin: 16px auto; margin: 16px auto;
} }
mwc-button { mwc-button {
color: var(--primary-color);
font-weight: 500;
margin-right: -0.57em; margin-right: -0.57em;
} }
</style> </style>

View File

@ -16,8 +16,6 @@ class StateCardConfigurator extends LocalizeMixin(PolymerElement) {
<style include="iron-flex iron-flex-alignment"></style> <style include="iron-flex iron-flex-alignment"></style>
<style> <style>
mwc-button { mwc-button {
color: var(--primary-color);
font-weight: 500;
top: 3px; top: 3px;
height: 37px; height: 37px;
margin-right: -0.57em; margin-right: -0.57em;

View File

@ -16,8 +16,6 @@ class StateCardLock extends LocalizeMixin(PolymerElement) {
<style include="iron-flex iron-flex-alignment"></style> <style include="iron-flex iron-flex-alignment"></style>
<style> <style>
mwc-button { mwc-button {
color: var(--primary-color);
font-weight: 500;
top: 3px; top: 3px;
height: 37px; height: 37px;
margin-right: -0.57em; margin-right: -0.57em;

View File

@ -15,8 +15,6 @@ class StateCardScene extends LocalizeMixin(PolymerElement) {
<style include="iron-flex iron-flex-alignment"></style> <style include="iron-flex iron-flex-alignment"></style>
<style> <style>
mwc-button { mwc-button {
color: var(--primary-color);
font-weight: 500;
top: 3px; top: 3px;
height: 37px; height: 37px;
margin-right: -0.57em; margin-right: -0.57em;

View File

@ -17,8 +17,6 @@ class StateCardScript extends LocalizeMixin(PolymerElement) {
<style include="iron-flex iron-flex-alignment"></style> <style include="iron-flex iron-flex-alignment"></style>
<style> <style>
mwc-button { mwc-button {
color: var(--primary-color);
font-weight: 500;
top: 3px; top: 3px;
height: 37px; height: 37px;
margin-right: -0.57em; margin-right: -0.57em;

View File

@ -271,6 +271,11 @@
"off": "[%key:state::default::off%]", "off": "[%key:state::default::off%]",
"on": "[%key:state::default::on%]" "on": "[%key:state::default::on%]"
}, },
"timer": {
"active": "active",
"idle": "idle",
"paused": "paused"
},
"vacuum": { "vacuum": {
"cleaning": "Cleaning", "cleaning": "Cleaning",
"docked": "Docked", "docked": "Docked",
@ -899,6 +904,10 @@
"para_migrate": "Home Assistant can add ID's to all your cards and views automatically for you by pressing the 'Migrate config' button.", "para_migrate": "Home Assistant can add ID's to all your cards and views automatically for you by pressing the 'Migrate config' button.",
"migrate": "Migrate config" "migrate": "Migrate config"
} }
},
"warning": {
"entity_not_found": "Entity not available: {entity}",
"entity_non_numeric": "Entity is non-numeric: {entity}"
} }
}, },
"mailbox": { "mailbox": {

View File

@ -346,7 +346,10 @@
}, },
"customize": { "customize": {
"caption": "Anpassung", "caption": "Anpassung",
"description": "Elemente anpassen" "description": "Elemente anpassen",
"picker": {
"header": "Anpassung"
}
}, },
"automation": { "automation": {
"caption": "Automatisierung", "caption": "Automatisierung",
@ -569,20 +572,51 @@
"hub": "Verbunden über", "hub": "Verbunden über",
"firmware": "Firmware: {version}", "firmware": "Firmware: {version}",
"device_unavailable": "Gerät nicht verfügbar", "device_unavailable": "Gerät nicht verfügbar",
"entity_unavailable": "Entität nicht verfügbar" "entity_unavailable": "Entität nicht verfügbar",
"no_area": "Kein Bereich"
} }
}, },
"zha": { "zha": {
"caption": "ZHA", "caption": "ZHA",
"description": "Zigbee Home Automation Netzwerkmanagement" "description": "Zigbee Home Automation Netzwerkmanagement",
"services": {
"reconfigure": "Rekonfiguriere ZHA-Gerät (Gerät heilen). Benutze dies, wenn du Probleme mit dem Gerät hast. Wenn es sich bei dem betroffenden Gerät um ein batteriebetriebenes Gerät handelt, stelle sicher dass es wach ist und Kommandos akzeptiert wenn du diesen Dienst benutzt."
}
}, },
"area_registry": { "area_registry": {
"caption": "Gebietsregister", "caption": "Gebietsregister",
"description": "Überblick über alle Bereiche in Deinem Haus." "description": "Überblick über alle Bereiche in Deinem Haus.",
"no_areas": "Sieht aus, als hättest du noch keine Bereiche!",
"create_area": "BEREICH ERSTELLEN",
"editor": {
"default_name": "Neuer Bereich",
"delete": "LÖSCHEN",
"update": "AKTUALISIEREN",
"create": "ERSTELLEN"
}
}, },
"entity_registry": { "entity_registry": {
"caption": "Entitätsregister", "caption": "Entitätsregister",
"description": "Überblick aller bekannten Elemente." "description": "Überblick aller bekannten Elemente.",
"picker": {
"unavailable": "(nicht verfügbar)"
},
"editor": {
"unavailable": "Diese Entität ist derzeit nicht verfügbar.",
"default_name": "Neuer Bereich",
"delete": "LÖSCHEN",
"update": "UPDATE"
}
},
"person": {
"caption": "Personen",
"description": "Verwalte die Personen, die Home Assistant verfolgt.",
"detail": {
"name": "Name",
"device_tracker_intro": "Wähle die Geräte, die dieser Person gehören.",
"device_tracker_picked": "Verfolge Gerät",
"device_tracker_pick": "Wähle zu verfolgendes Gerät"
}
} }
}, },
"profile": { "profile": {
@ -727,6 +761,24 @@
} }
}, },
"command_line": { "command_line": {
"step": {
"init": {
"data": {
"username": "Benutzername",
"password": "Passwort"
}
},
"mfa": {
"data": {
"code": "Zwei-Faktor Authentifizierungscode"
},
"description": "Öffne das **{mfa_module_name}** auf deinem Gerät um den 2-Faktor Authentifizierungscode zu sehen und deine Identität zu bestätigen:"
}
},
"error": {
"invalid_auth": "Ungültiger Benutzername oder Passwort",
"invalid_code": "Ungültiger Authentifizierungscode"
},
"abort": { "abort": {
"login_expired": "Sitzung abgelaufen, bitte erneut anmelden." "login_expired": "Sitzung abgelaufen, bitte erneut anmelden."
} }
@ -771,7 +823,8 @@
"pick_card": "Karte auswählen, die hinzugefügt werden soll.", "pick_card": "Karte auswählen, die hinzugefügt werden soll.",
"add": "Karte hinzufügen", "add": "Karte hinzufügen",
"edit": "Bearbeiten", "edit": "Bearbeiten",
"delete": "Löschen" "delete": "Löschen",
"move": "Bewegen"
}, },
"migrate": { "migrate": {
"header": "Konfiguration inkompatibel", "header": "Konfiguration inkompatibel",

View File

@ -569,7 +569,8 @@
"hub": "Connecté via", "hub": "Connecté via",
"firmware": "Firmware: {version}", "firmware": "Firmware: {version}",
"device_unavailable": "appareil indisponible", "device_unavailable": "appareil indisponible",
"entity_unavailable": "entité indisponible" "entity_unavailable": "entité indisponible",
"no_area": "Pas de pièce"
} }
}, },
"zha": { "zha": {
@ -582,14 +583,23 @@
"area_registry": { "area_registry": {
"caption": "Registre des pièces", "caption": "Registre des pièces",
"description": "Vue d'ensemble de toutes les pièces de votre maison.", "description": "Vue d'ensemble de toutes les pièces de votre maison.",
"picker": {
"header": "Registre des pièces"
},
"no_areas": "Vous n'avez pas encore configuré de pièce !",
"create_area": "CRÉER UNE PIÈCE",
"editor": { "editor": {
"delete": "SUPPRIMER" "default_name": "Nouvelle pièce",
"delete": "SUPPRIMER",
"update": "METTRE À JOUR",
"create": "CRÉER"
} }
}, },
"entity_registry": { "entity_registry": {
"caption": "Registre des entités", "caption": "Registre des entités",
"description": "Vue d'ensemble de toutes les entités connues.", "description": "Vue d'ensemble de toutes les entités connues.",
"editor": { "editor": {
"default_name": "Nouvelle pièce",
"delete": "SUPPRIMER", "delete": "SUPPRIMER",
"update": "METTRE À JOUR" "update": "METTRE À JOUR"
} }

View File

@ -370,7 +370,7 @@
"alias": "שם", "alias": "שם",
"triggers": { "triggers": {
"header": "טריגרים", "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": "הוספת טריגר", "add": "הוספת טריגר",
"duplicate": "שכפל", "duplicate": "שכפל",
"delete": "מחק", "delete": "מחק",
@ -451,7 +451,7 @@
}, },
"conditions": { "conditions": {
"header": "תנאים", "header": "תנאים",
"introduction": "התנאים הם חלק אופציונלי של כלל אוטומציה, וניתן להשתמש בהם כדי למנוע פעולה כלשהי בעת הפעלתה. התנאים נראים דומים מאוד לטריגרים אך הם שונים מאוד. הטריגר יסתכל על האירועים המתרחשים במערכת בעוד תנאי רק מסתכל על איך המערכת נראית עכשיו. הטריגר יכול שמתג נדלק. תנאי יכול לראות רק אם מתג מופעל או כבוי. \n\n[למידע נוסף על תנאים](Https:\/\/home-assistant.io\/docs\/scripts\/conditions\/)", "introduction": "התנאים הם חלק אופציונלי של כלל אוטומציה, וניתן להשתמש בהם כדי למנוע פעולה כלשהי בעת הפעלתה. התנאים נראים דומים מאוד לטריגרים אך הם שונים מאוד. הטריגר יסתכל על האירועים המתרחשים במערכת בעוד תנאי רק מסתכל על איך המערכת נראית עכשיו. הטריגר יכול לדעת כשמתג נדלק. תנאי יכול לראות רק אם מתג מופעל או כבוי. \n\n[למידע נוסף על תנאים](Https:\/\/home-assistant.io\/docs\/scripts\/conditions\/)",
"add": "הוסף תנאי", "add": "הוסף תנאי",
"duplicate": "שכפל", "duplicate": "שכפל",
"delete": "מחק", "delete": "מחק",

View File

@ -346,7 +346,10 @@
}, },
"customize": { "customize": {
"caption": "Testreszabás", "caption": "Testreszabás",
"description": "Entitások testreszabása" "description": "Entitások testreszabása",
"picker": {
"header": "Testreszabás"
}
}, },
"automation": { "automation": {
"caption": "Automatizálás", "caption": "Automatizálás",
@ -436,6 +439,7 @@
"seconds": "Másodperc" "seconds": "Másodperc"
}, },
"geo_location": { "geo_location": {
"label": "Helylokáció",
"source": "Forrás", "source": "Forrás",
"zone": "Zóna", "zone": "Zóna",
"event": "Esemény:", "event": "Esemény:",
@ -568,20 +572,55 @@
"hub": "Kapcsolódva", "hub": "Kapcsolódva",
"firmware": "Firmware: {version}", "firmware": "Firmware: {version}",
"device_unavailable": "eszköz nem érhető el", "device_unavailable": "eszköz nem érhető el",
"entity_unavailable": "entitás nem érhető el" "entity_unavailable": "entitás nem érhető el",
"no_area": "Nincs Terület"
} }
}, },
"zha": { "zha": {
"caption": "ZHA", "caption": "ZHA",
"description": "Zigbee Home Automation hálózat menedzsment" "description": "Zigbee Home Automation hálózat menedzsment",
"services": {
"reconfigure": "A ZHA készülék újratelepítése (eszköz rendbehozatala). Ezt a funkciót használd, ha problémáid vannak a készülékkel. Ha a kérdéses eszköz akkumulátoros, győződj meg róla, hogy nincs alvó állapotban és fogadja a parancsokat, amikor ezt a szolgáltatást használod."
}
}, },
"area_registry": { "area_registry": {
"caption": "Terület Nyilvántartás", "caption": "Terület Nyilvántartás",
"description": "Az összes otthoni terület áttekintése" "description": "Az összes otthoni terület áttekintése",
"picker": {
"header": "Terület Nyilvántartás"
},
"no_areas": "Úgy tűnik nem hoztál létre még egy területet sem!",
"create_area": "TERÜLET LÉTREHOZÁSA",
"editor": {
"default_name": "Új Terület",
"delete": "TÖRLÉS",
"update": "FRISSÍTÉS",
"create": "LÉTREHOZÁS"
}
}, },
"entity_registry": { "entity_registry": {
"caption": "Entitás Nyilvántartás", "caption": "Entitás Nyilvántartás",
"description": "Az összes ismert entitás áttekintése" "description": "Az összes ismert entitás áttekintése",
"picker": {
"header": "Entitás Nyilvántartás",
"unavailable": "(nem elérhető)"
},
"editor": {
"unavailable": "Ez a entitás jelenleg nem elérhető.",
"default_name": "Új Terület",
"delete": "TÖRLÉS",
"update": "FRISSÍTÉS"
}
},
"person": {
"caption": "Személyek",
"description": "Kezeld azon személyeket, melyeket a Home Assistant követ.",
"detail": {
"name": "Név",
"device_tracker_intro": "Válaszd ki az eszközöket, melyek ehhez a felhasználóhoz tartoznak",
"device_tracker_picked": "Eszköz követése",
"device_tracker_pick": "Válassz egy követni kívánt eszközt"
}
} }
}, },
"profile": { "profile": {
@ -726,6 +765,23 @@
} }
}, },
"command_line": { "command_line": {
"step": {
"init": {
"data": {
"username": "Felhasználónév",
"password": "Jelszó"
}
},
"mfa": {
"data": {
"code": "Két faktoros hitelesítő kód"
}
}
},
"error": {
"invalid_auth": "Érvénytelen felhasználónév vagy jelszó",
"invalid_code": "Érvénytelen hitelesítő kód"
},
"abort": { "abort": {
"login_expired": "A munkamenet lejárt, kérlek, jelentkezz be újra." "login_expired": "A munkamenet lejárt, kérlek, jelentkezz be újra."
} }
@ -770,7 +826,8 @@
"pick_card": "Válaszd ki a kártyát amit hozzá szeretnél adni.", "pick_card": "Válaszd ki a kártyát amit hozzá szeretnél adni.",
"add": "Kártya hozzáadása", "add": "Kártya hozzáadása",
"edit": "Szerkesztés", "edit": "Szerkesztés",
"delete": "Törlés" "delete": "Törlés",
"move": "Mozgatás"
}, },
"migrate": { "migrate": {
"header": "Inkompatibilis Konfiguráció", "header": "Inkompatibilis Konfiguráció",

View File

@ -1003,7 +1003,7 @@
}, },
"relative_time": { "relative_time": {
"past": "{time} fa", "past": "{time} fa",
"future": "{time} fa", "future": "tra {time}",
"never": "Mai", "never": "Mai",
"duration": { "duration": {
"second": "{count} {count, plural,\none {secondo}\nother {secondi}\n}", "second": "{count} {count, plural,\none {secondo}\nother {secondi}\n}",
@ -1036,9 +1036,9 @@
"last_action": "Ultima azione" "last_action": "Ultima azione"
}, },
"sun": { "sun": {
"elevation": "Alba", "elevation": "Elevazione",
"rising": "Tramonto", "rising": "Alba",
"setting": "Impostazione" "setting": "Tramonto"
}, },
"updater": { "updater": {
"title": "Aggiorna istruzioni" "title": "Aggiorna istruzioni"

View File

@ -241,7 +241,7 @@
} }
}, },
"weather": { "weather": {
"clear-night": "맑은 밤", "clear-night": "맑음 (밤)",
"cloudy": "흐림", "cloudy": "흐림",
"fog": "안개", "fog": "안개",
"hail": "우박", "hail": "우박",

View File

@ -850,6 +850,9 @@
"para_sure": "Sécher fir d'Kontrolle iwwert de Benotzer Interface z'iwwerhuelen?", "para_sure": "Sécher fir d'Kontrolle iwwert de Benotzer Interface z'iwwerhuelen?",
"cancel": "Vergiess et", "cancel": "Vergiess et",
"save": "Kontroll iwwerhuelen" "save": "Kontroll iwwerhuelen"
},
"menu": {
"raw_editor": "Editeur fir déi reng Konfiguratioun"
} }
}, },
"menu": { "menu": {
@ -929,7 +932,8 @@
"arm_home": "Aktivéiert Doheem", "arm_home": "Aktivéiert Doheem",
"arm_away": "Aktivéiert Ënnerwee", "arm_away": "Aktivéiert Ënnerwee",
"arm_night": "Aktivéiert Nuecht", "arm_night": "Aktivéiert Nuecht",
"armed_custom_bypass": "Personaliséierte Bypass" "armed_custom_bypass": "Personaliséierte Bypass",
"arm_custom_bypass": "Personaliséierte Bypass"
}, },
"automation": { "automation": {
"last_triggered": "Läscht ausgeléist", "last_triggered": "Läscht ausgeléist",

View File

@ -433,6 +433,9 @@
"hours": "Stundas", "hours": "Stundas",
"minutes": "Minūtes", "minutes": "Minūtes",
"seconds": "Sekundes" "seconds": "Sekundes"
},
"geo_location": {
"label": "Ģeogrāfiskā atrašanās vieta"
} }
} }
}, },
@ -566,6 +569,9 @@
"zha": { "zha": {
"caption": "ZHA", "caption": "ZHA",
"description": "Zigbee Home Automation tīkla pārvaldība" "description": "Zigbee Home Automation tīkla pārvaldība"
},
"area_registry": {
"description": "Pārskats par visām vietām jūsu mājās."
} }
}, },
"profile": { "profile": {
@ -708,6 +714,26 @@
"abort": { "abort": {
"not_whitelisted": "Jūsu dators nav iekļauts baltajā sarakstā." "not_whitelisted": "Jūsu dators nav iekļauts baltajā sarakstā."
} }
},
"command_line": {
"step": {
"init": {
"data": {
"username": "Lietotājvārds",
"password": "Parole"
}
},
"mfa": {
"data": {
"code": "Divpakāpju Autorizācijas Kods"
},
"description": "Atveriet **{mfa_module_name}** Jūsu ierīcē, lai apskatītu savu divpakāpju autorizācijas kodu un aptiprinātu savu identitāti:"
}
},
"error": {
"invalid_auth": "Nepareizs lietotājvārds un parole",
"invalid_code": "Nepareizs autorizācijas kods"
}
} }
} }
} }
@ -841,7 +867,8 @@
"arm_home": "Pieslēgt mājas", "arm_home": "Pieslēgt mājas",
"arm_away": "Pieslēgt prombūtni", "arm_away": "Pieslēgt prombūtni",
"arm_night": "Pieslēgts uz nakti", "arm_night": "Pieslēgts uz nakti",
"armed_custom_bypass": "Pielāgots apvedceļš" "armed_custom_bypass": "Pielāgots apvedceļš",
"arm_custom_bypass": "Pielāgots apvedceļš"
}, },
"automation": { "automation": {
"last_triggered": "Pēdējais izsaukums", "last_triggered": "Pēdējais izsaukums",
@ -1001,7 +1028,10 @@
"weblink": "Weblink", "weblink": "Weblink",
"zwave": "Z-Wave", "zwave": "Z-Wave",
"vacuum": "Putekļsūcējs", "vacuum": "Putekļsūcējs",
"zha": "ZHA" "zha": "ZHA",
"hassio": "Hass.io",
"homeassistant": "Home Assistant",
"lovelace": "Lovelace"
}, },
"attribute": { "attribute": {
"weather": { "weather": {

View File

@ -588,6 +588,7 @@
"picker": { "picker": {
"header": "Områderegister" "header": "Områderegister"
}, },
"no_areas": "Det ser ikke ut som om du har noen områder ennå!",
"create_area": "OPPRETT OMRÅDE", "create_area": "OPPRETT OMRÅDE",
"editor": { "editor": {
"default_name": "Nytt område", "default_name": "Nytt område",
@ -612,9 +613,12 @@
}, },
"person": { "person": {
"caption": "Personer", "caption": "Personer",
"description": "Administrer personer som Home Assistant sporer.",
"detail": { "detail": {
"name": "Navn", "name": "Navn",
"device_tracker_intro": "Velg enhetene som tilhører denne personen." "device_tracker_intro": "Velg enhetene som tilhører denne personen.",
"device_tracker_picked": "Spor enhet",
"device_tracker_pick": "Velg en enhet å spore"
} }
} }
}, },
@ -769,7 +773,8 @@
} }
}, },
"error": { "error": {
"invalid_auth": "Ugyldig brukernavn eller passord" "invalid_auth": "Ugyldig brukernavn eller passord",
"invalid_code": "Ugyldig autentiseringskode"
}, },
"abort": { "abort": {
"login_expired": "Økten er utløpt, vennligst logg inn på nytt" "login_expired": "Økten er utløpt, vennligst logg inn på nytt"

View File

@ -581,11 +581,27 @@
}, },
"area_registry": { "area_registry": {
"caption": "Gebiedenregister", "caption": "Gebiedenregister",
"description": "Overzicht van alle gebieden in je huis." "description": "Overzicht van alle gebieden in je huis.",
"picker": {
"header": "Gebiedenregister"
}
}, },
"entity_registry": { "entity_registry": {
"caption": "Entiteiten register", "caption": "Entiteiten register",
"description": "Overzicht van alle gekende entiteiten" "description": "Overzicht van alle gekende entiteiten",
"picker": {
"header": "Entiteiten register"
},
"editor": {
"delete": "VERWIJDEREN"
}
},
"person": {
"caption": "Personen",
"description": "Beheer de personen die Home Assistant volgt.",
"detail": {
"name": "Naam"
}
} }
}, },
"profile": { "profile": {

View File

@ -370,7 +370,7 @@
"alias": "Название", "alias": "Название",
"triggers": { "triggers": {
"header": "Триггеры", "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": "Добавить триггер", "add": "Добавить триггер",
"duplicate": "Дублировать", "duplicate": "Дублировать",
"delete": "Удалить", "delete": "Удалить",
@ -590,7 +590,7 @@
"picker": { "picker": {
"header": "Управление помещениями" "header": "Управление помещениями"
}, },
"no_areas": "У Вас еще нет добавленных помещений.", "no_areas": "Похоже, что у Вас пока ещё нет добавленных помещений!",
"create_area": "ДОБАВИТЬ", "create_area": "ДОБАВИТЬ",
"editor": { "editor": {
"default_name": "Новое помещение", "default_name": "Новое помещение",

View File

@ -346,7 +346,11 @@
}, },
"customize": { "customize": {
"caption": "自定义", "caption": "自定义",
"description": "自定义实体" "description": "自定义实体",
"picker": {
"header": "自定义",
"introduction": "调整每个实体的属性。添加\/编辑的自定义设置将立即生效,删除的自定义设置将在实体更新时生效。"
}
}, },
"automation": { "automation": {
"caption": "自动化", "caption": "自动化",
@ -568,17 +572,50 @@
"hub": "链接于", "hub": "链接于",
"firmware": "固件:{version}", "firmware": "固件:{version}",
"device_unavailable": "设备不可用", "device_unavailable": "设备不可用",
"entity_unavailable": "实体不可用" "entity_unavailable": "实体不可用",
"no_area": "没有区域"
} }
}, },
"zha": { "zha": {
"description": "Zigbee 智能家居(ZHA) 网络管理" "description": "Zigbee 智能家居(ZHA) 网络管理"
}, },
"area_registry": { "area_registry": {
"description": "您家中所有区域的概览。" "description": "您家中所有区域的概览。",
"picker": {
"header": "注册区域"
},
"no_areas": "看来你还没有建立区域!",
"create_area": "创建区域",
"editor": {
"default_name": "新区域",
"delete": "删除",
"update": "更新",
"create": "创建"
}
}, },
"entity_registry": { "entity_registry": {
"description": "所有已知实体的概览。" "caption": "实体注册",
"description": "所有已知实体的概览。",
"picker": {
"header": "实体注册",
"unavailable": "(不可用)"
},
"editor": {
"unavailable": "该实体暂不可用。",
"default_name": "新区域",
"delete": "删除",
"update": "更新"
}
},
"person": {
"caption": "人",
"description": "管理Home Assistant跟踪的人员。",
"detail": {
"name": "名字",
"device_tracker_intro": "选择属于此人的设备。",
"device_tracker_picked": "跟踪设备",
"device_tracker_pick": "选择要跟踪的设备"
}
} }
}, },
"profile": { "profile": {
@ -674,7 +711,7 @@
"data": { "data": {
"code": "双重认证口令" "code": "双重认证口令"
}, },
"description": "在设备上打开 **{mfa_module_name}** 来查看双重认证口令以验证您的身份:" "description": "在设备上打开 **{mfa_module_name}** 查看双重认证口令并验证您的身份:"
} }
}, },
"error": { "error": {
@ -697,7 +734,7 @@
"data": { "data": {
"code": "双重认证口令" "code": "双重认证口令"
}, },
"description": "在设备上打开 **{mfa_module_name}** 来查看双重认证口令以验证您的身份:" "description": "在设备上打开 **{mfa_module_name}** 查看双重认证口令并验证您的身份:"
} }
}, },
"error": { "error": {
@ -723,6 +760,24 @@
} }
}, },
"command_line": { "command_line": {
"step": {
"init": {
"data": {
"username": "用户名",
"password": "密码"
}
},
"mfa": {
"data": {
"code": "二次认证口令"
},
"description": "在设备上打开 **{mfa_module_name}** 查看二次认证口令并验证您的身份:"
}
},
"error": {
"invalid_auth": "无效的用户名或密码",
"invalid_code": "无效的验证码"
},
"abort": { "abort": {
"login_expired": "会话已过期,请重新登录。" "login_expired": "会话已过期,请重新登录。"
} }
@ -767,7 +822,8 @@
"pick_card": "请选择要添加的卡片。", "pick_card": "请选择要添加的卡片。",
"add": "添加卡片", "add": "添加卡片",
"edit": "编辑", "edit": "编辑",
"delete": "删除" "delete": "删除",
"move": "移动"
}, },
"migrate": { "migrate": {
"header": "配置不兼容", "header": "配置不兼容",
@ -870,7 +926,8 @@
"arm_home": "在家警戒", "arm_home": "在家警戒",
"arm_away": "离家警戒", "arm_away": "离家警戒",
"arm_night": "夜间警戒", "arm_night": "夜间警戒",
"armed_custom_bypass": "自定义略过" "armed_custom_bypass": "自定义略过",
"arm_custom_bypass": "自定义略过条件"
}, },
"automation": { "automation": {
"last_triggered": "上次触发", "last_triggered": "上次触发",