Merge pull request #10162 from home-assistant/dev

This commit is contained in:
Bram Kragten 2021-10-06 10:18:40 +02:00 committed by GitHub
commit 736e117eca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 147 additions and 210 deletions

View File

@ -111,8 +111,7 @@
], ],
"unused-imports/no-unused-imports": "error", "unused-imports/no-unused-imports": "error",
"lit/attribute-value-entities": "off", "lit/attribute-value-entities": "off",
"lit/no-template-map": "off", "lit/no-template-map": "off"
"lit/no-template-arrow": "warn"
}, },
"plugins": ["disable", "unused-imports"], "plugins": ["disable", "unused-imports"],
"processor": "disable/disable" "processor": "disable/disable"

View File

@ -1,9 +1,6 @@
const gulp = require("gulp"); const gulp = require("gulp");
const fs = require("fs");
const path = require("path");
const env = require("../env"); const env = require("../env");
const paths = require("../paths");
require("./clean.js"); require("./clean.js");
require("./gen-icons-json.js"); require("./gen-icons-json.js");

View File

@ -4,9 +4,6 @@ const del = require("del");
const path = require("path"); const path = require("path");
const gulp = require("gulp"); const gulp = require("gulp");
const fs = require("fs"); const fs = require("fs");
const merge = require("gulp-merge-json");
const rename = require("gulp-rename");
const transform = require("gulp-json-transform");
const paths = require("../paths"); const paths = require("../paths");
const outDir = "build/locale-data"; const outDir = "build/locale-data";

View File

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

View File

@ -115,7 +115,7 @@ export const applyThemesOnElement = (
} }
const newTheme = const newTheme =
themeRules && cacheKey Object.keys(themeRules).length && cacheKey
? PROCESSED_THEMES[cacheKey] || processTheme(cacheKey, themeRules) ? PROCESSED_THEMES[cacheKey] || processTheme(cacheKey, themeRules)
: undefined; : undefined;

View File

@ -180,10 +180,10 @@ export function fuzzyScore(
wordLow wordLow
); );
let row = 1; let row: number;
let column = 1; let column = 1;
let patternPos = patternStart; let patternPos: number;
let wordPos = wordStart; let wordPos: number;
const hasStrongFirstMatch = [false]; const hasStrongFirstMatch = [false];

View File

@ -34,7 +34,7 @@ export class HaDeviceSelector extends LitElement {
.hass=${this.hass} .hass=${this.hass}
.value=${this.value} .value=${this.value}
.label=${this.label} .label=${this.label}
.deviceFilter=${(device) => this._filterDevices(device)} .deviceFilter=${this._filterDevices}
.includeDeviceClasses=${this.selector.device.entity?.device_class .includeDeviceClasses=${this.selector.device.entity?.device_class
? [this.selector.device.entity.device_class] ? [this.selector.device.entity.device_class]
: undefined} : undefined}
@ -46,7 +46,7 @@ export class HaDeviceSelector extends LitElement {
></ha-device-picker>`; ></ha-device-picker>`;
} }
private _filterDevices(device: DeviceRegistryEntry): boolean { private _filterDevices = (device: DeviceRegistryEntry): boolean => {
if ( if (
this.selector.device?.manufacturer && this.selector.device?.manufacturer &&
device.manufacturer !== this.selector.device.manufacturer device.manufacturer !== this.selector.device.manufacturer
@ -70,7 +70,7 @@ export class HaDeviceSelector extends LitElement {
} }
} }
return true; return true;
} };
private async _loadConfigEntries() { private async _loadConfigEntries() {
this._configEntries = (await getConfigEntries(this.hass)).filter( this._configEntries = (await getConfigEntries(this.hass)).filter(

View File

@ -27,7 +27,7 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
.hass=${this.hass} .hass=${this.hass}
.value=${this.value} .value=${this.value}
.label=${this.label} .label=${this.label}
.entityFilter=${(entity) => this._filterEntities(entity)} .entityFilter=${this._filterEntities}
.disabled=${this.disabled} .disabled=${this.disabled}
allow-custom-entity allow-custom-entity
></ha-entity-picker>`; ></ha-entity-picker>`;
@ -48,7 +48,7 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
]; ];
} }
private _filterEntities(entity: HassEntity): boolean { private _filterEntities = (entity: HassEntity): boolean => {
if (this.selector.entity?.domain) { if (this.selector.entity?.domain) {
if (computeStateDomain(entity) !== this.selector.entity.domain) { if (computeStateDomain(entity) !== this.selector.entity.domain) {
return false; return false;
@ -72,7 +72,7 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
} }
} }
return true; return true;
} };
} }
declare global { declare global {

View File

@ -69,10 +69,9 @@ export class HaTargetSelector extends SubscribeMixin(LitElement) {
return html`<ha-target-picker return html`<ha-target-picker
.hass=${this.hass} .hass=${this.hass}
.value=${this.value} .value=${this.value}
.deviceFilter=${(device) => this._filterDevices(device)} .deviceFilter=${this._filterDevices}
.entityRegFilter=${(entity: EntityRegistryEntry) => .entityRegFilter=${this._filterRegEntities}
this._filterRegEntities(entity)} .entityFilter=${this._filterEntities}
.entityFilter=${(entity: HassEntity) => this._filterEntities(entity)}
.includeDeviceClasses=${this.selector.target.entity?.device_class .includeDeviceClasses=${this.selector.target.entity?.device_class
? [this.selector.target.entity.device_class] ? [this.selector.target.entity.device_class]
: undefined} : undefined}
@ -83,7 +82,7 @@ export class HaTargetSelector extends SubscribeMixin(LitElement) {
></ha-target-picker>`; ></ha-target-picker>`;
} }
private _filterEntities(entity: HassEntity): boolean { private _filterEntities = (entity: HassEntity): boolean => {
if ( if (
this.selector.target.entity?.integration || this.selector.target.entity?.integration ||
this.selector.target.device?.integration this.selector.target.device?.integration
@ -98,18 +97,18 @@ export class HaTargetSelector extends SubscribeMixin(LitElement) {
} }
} }
return true; return true;
} };
private _filterRegEntities(entity: EntityRegistryEntry): boolean { private _filterRegEntities = (entity: EntityRegistryEntry): boolean => {
if (this.selector.target.entity?.integration) { if (this.selector.target.entity?.integration) {
if (entity.platform !== this.selector.target.entity.integration) { if (entity.platform !== this.selector.target.entity.integration) {
return false; return false;
} }
} }
return true; return true;
} };
private _filterDevices(device: DeviceRegistryEntry): boolean { private _filterDevices = (device: DeviceRegistryEntry): boolean => {
if ( if (
this.selector.target.device?.manufacturer && this.selector.target.device?.manufacturer &&
device.manufacturer !== this.selector.target.device.manufacturer device.manufacturer !== this.selector.target.device.manufacturer
@ -135,7 +134,7 @@ export class HaTargetSelector extends SubscribeMixin(LitElement) {
} }
} }
return true; return true;
} };
private async _loadConfigEntries() { private async _loadConfigEntries() {
this._configEntries = (await getConfigEntries(this.hass)).filter( this._configEntries = (await getConfigEntries(this.hass)).filter(

View File

@ -511,18 +511,16 @@ export class HaAutomationTracer extends LitElement {
className: isError ? "error" : undefined, className: isError ? "error" : undefined,
}; };
} }
// null means it was stopped by a condition
if (entry) { entries.push(html`
entries.push(html` <ha-timeline
<ha-timeline lastItem
lastItem .icon=${entry.icon}
.icon=${entry.icon} class=${ifDefined(entry.className)}
class=${ifDefined(entry.className)} >
> ${entry.description}
${entry.description} </ha-timeline>
</ha-timeline> `);
`);
}
return html`${entries}`; return html`${entries}`;
} }

View File

@ -123,7 +123,7 @@ export class QuickBar extends LitElement {
: this._entityItems; : this._entityItems;
if (items && this._filter && this._filter !== " ") { if (items && this._filter && this._filter !== " ") {
items = this._filterItems(items || [], this._filter); items = this._filterItems(items, this._filter);
} }
return html` return html`

View File

@ -113,7 +113,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
.hass=${this.hass} .hass=${this.hass}
.narrow=${this.narrow} .narrow=${this.narrow}
.route=${this.route} .route=${this.route}
.backCallback=${() => this._backTapped()} .backCallback=${this._backTapped}
.tabs=${configSections.automation} .tabs=${configSections.automation}
> >
<ha-button-menu <ha-button-menu
@ -435,7 +435,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
this._dirty = true; this._dirty = true;
} }
private _backTapped(): void { private _backTapped = (): void => {
if (this._dirty) { if (this._dirty) {
showConfirmationDialog(this, { showConfirmationDialog(this, {
text: this.hass!.localize( text: this.hass!.localize(
@ -448,7 +448,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
} else { } else {
history.back(); history.back();
} }
} };
private async _duplicate() { private async _duplicate() {
if (this._dirty) { if (this._dirty) {

View File

@ -135,7 +135,7 @@ class HaAutomationPicker extends LitElement {
template: (_info, automation: any) => html` template: (_info, automation: any) => html`
<mwc-button <mwc-button
.automation=${automation} .automation=${automation}
@click=${(ev) => this._runActions(ev)} @click=${this._runActions}
.disabled=${UNAVAILABLE_STATES.includes(automation.state)} .disabled=${UNAVAILABLE_STATES.includes(automation.state)}
> >
${this.hass.localize("ui.card.automation.trigger")} ${this.hass.localize("ui.card.automation.trigger")}
@ -313,10 +313,10 @@ class HaAutomationPicker extends LitElement {
}); });
} }
private _runActions(ev) { private _runActions = (ev) => {
const entityId = ev.currentTarget.automation.entity_id; const entityId = ev.currentTarget.automation.entity_id;
triggerAutomationActions(this.hass, entityId); triggerAutomationActions(this.hass, entityId);
} };
private _createNew() { private _createNew() {
if ( if (

View File

@ -90,7 +90,7 @@ export class HaAutomationTrace extends LitElement {
} }
const actionButtons = html` const actionButtons = html`
<mwc-icon-button label="Refresh" @click=${() => this._loadTraces()}> <mwc-icon-button label="Refresh" @click=${this._refreshTraces}>
<ha-svg-icon .path=${mdiRefresh}></ha-svg-icon> <ha-svg-icon .path=${mdiRefresh}></ha-svg-icon>
</mwc-icon-button> </mwc-icon-button>
<mwc-icon-button <mwc-icon-button
@ -111,7 +111,7 @@ export class HaAutomationTrace extends LitElement {
.tabs=${configSections.automation} .tabs=${configSections.automation}
> >
${this.narrow ${this.narrow
? html`<span slot="header"> ${title} </span> ? html`<span slot="header">${title}</span>
<div slot="toolbar-icon">${actionButtons}</div>` <div slot="toolbar-icon">${actionButtons}</div>`
: ""} : ""}
<div class="toolbar"> <div class="toolbar">
@ -335,6 +335,10 @@ export class HaAutomationTrace extends LitElement {
this._selected = ev.detail; this._selected = ev.detail;
} }
private _refreshTraces() {
this._loadTraces();
}
private async _loadTraces(runId?: string) { private async _loadTraces(runId?: string) {
this._traces = await loadTraces(this.hass, "automation", this.automationId); this._traces = await loadTraces(this.hass, "automation", this.automationId);
// Newest will be on top. // Newest will be on top.

View File

@ -78,7 +78,7 @@ class DialogThingtalk extends LitElement {
.hass=${this.hass} .hass=${this.hass}
.placeholders=${this._placeholders} .placeholders=${this._placeholders}
.opened=${this._opened} .opened=${this._opened}
.skip=${() => this._skip()} .skip=${this._skip}
@opened-changed=${this._openedChanged} @opened-changed=${this._openedChanged}
@placeholders-filled=${this._handlePlaceholders} @placeholders-filled=${this._handlePlaceholders}
> >
@ -229,10 +229,10 @@ class DialogThingtalk extends LitElement {
this.closeDialog(); this.closeDialog();
} }
private _skip() { private _skip = () => {
this._params!.callback(undefined); this._params!.callback(undefined);
this.closeDialog(); this.closeDialog();
} };
private _openedChanged(ev: PolymerChangedEvent<boolean>): void { private _openedChanged(ev: PolymerChangedEvent<boolean>): void {
if (!ev.detail.value) { if (!ev.detail.value) {

View File

@ -1,3 +1,4 @@
/* eslint-disable lit/no-template-arrow */
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
import { import {
css, css,

View File

@ -127,13 +127,13 @@ class HaBlueprintOverview extends LitElement {
title=${this.hass.localize( title=${this.hass.localize(
"ui.panel.config.blueprint.overview.use_blueprint" "ui.panel.config.blueprint.overview.use_blueprint"
)} )}
@click=${(ev) => this._createNew(ev)} @click=${this._createNew}
> >
<ha-svg-icon .path=${mdiRobot}></ha-svg-icon> <ha-svg-icon .path=${mdiRobot}></ha-svg-icon>
</mwc-icon-button>` </mwc-icon-button>`
: html`<mwc-button : html`<mwc-button
.blueprint=${blueprint} .blueprint=${blueprint}
@click=${(ev) => this._createNew(ev)} @click=${this._createNew}
> >
${this.hass.localize( ${this.hass.localize(
"ui.panel.config.blueprint.overview.use_blueprint" "ui.panel.config.blueprint.overview.use_blueprint"
@ -154,7 +154,7 @@ class HaBlueprintOverview extends LitElement {
? "ui.panel.config.blueprint.overview.share_blueprint" ? "ui.panel.config.blueprint.overview.share_blueprint"
: "ui.panel.config.blueprint.overview.share_blueprint_no_url" : "ui.panel.config.blueprint.overview.share_blueprint_no_url"
)} )}
@click=${(ev) => this._share(ev)} @click=${this._share}
><ha-svg-icon .path=${mdiShareVariant}></ha-svg-icon ><ha-svg-icon .path=${mdiShareVariant}></ha-svg-icon
></mwc-icon-button>`, ></mwc-icon-button>`,
}, },
@ -169,7 +169,7 @@ class HaBlueprintOverview extends LitElement {
.label=${this.hass.localize( .label=${this.hass.localize(
"ui.panel.config.blueprint.overview.delete_blueprint" "ui.panel.config.blueprint.overview.delete_blueprint"
)} )}
@click=${(ev) => this._delete(ev)} @click=${this._delete}
><ha-svg-icon .path=${mdiDelete}></ha-svg-icon ><ha-svg-icon .path=${mdiDelete}></ha-svg-icon
></mwc-icon-button>`, ></mwc-icon-button>`,
}, },
@ -275,12 +275,12 @@ class HaBlueprintOverview extends LitElement {
fireEvent(this, "reload-blueprints"); fireEvent(this, "reload-blueprints");
} }
private _createNew(ev) { private _createNew = (ev) => {
const blueprint = ev.currentTarget.blueprint as BlueprintMetaDataPath; const blueprint = ev.currentTarget.blueprint as BlueprintMetaDataPath;
createNewFunctions[blueprint.domain](blueprint); createNewFunctions[blueprint.domain](blueprint);
} };
private _share(ev) { private _share = (ev) => {
const blueprint = ev.currentTarget.blueprint; const blueprint = ev.currentTarget.blueprint;
const params = new URLSearchParams(); const params = new URLSearchParams();
params.append("redirect", "blueprint_import"); params.append("redirect", "blueprint_import");
@ -288,9 +288,9 @@ class HaBlueprintOverview extends LitElement {
window.open( window.open(
`https://my.home-assistant.io/create-link/?${params.toString()}` `https://my.home-assistant.io/create-link/?${params.toString()}`
); );
} };
private async _delete(ev) { private _delete = async (ev) => {
const blueprint = ev.currentTarget.blueprint; const blueprint = ev.currentTarget.blueprint;
if ( if (
!(await showConfirmationDialog(this, { !(await showConfirmationDialog(this, {
@ -306,7 +306,7 @@ class HaBlueprintOverview extends LitElement {
} }
await deleteBlueprint(this.hass, blueprint.domain, blueprint.path); await deleteBlueprint(this.hass, blueprint.domain, blueprint.path);
fireEvent(this, "reload-blueprints"); fireEvent(this, "reload-blueprints");
} };
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return haStyle; return haStyle;

View File

@ -99,16 +99,12 @@ export class CloudRemotePref extends LitElement {
)}</mwc-button )}</mwc-button
> >
</a> </a>
${remote_certificate <div class="spacer"></div>
? html` <mwc-button @click=${this._openCertInfo}>
<div class="spacer"></div> ${this.hass.localize(
<mwc-button @click=${this._openCertInfo}> "ui.panel.config.cloud.account.remote.certificate_info"
${this.hass.localize( )}
"ui.panel.config.cloud.account.remote.certificate_info" </mwc-button>
)}
</mwc-button>
`
: ""}
</div> </div>
</ha-card> </ha-card>
`; `;

View File

@ -36,7 +36,7 @@ export class DialogEnergyBatterySettings
this._params = params; this._params = params;
this._source = params.source this._source = params.source
? { ...params.source } ? { ...params.source }
: (this._source = emptyBatteryEnergyPreference()); : emptyBatteryEnergyPreference();
} }
public closeDialog(): void { public closeDialog(): void {

View File

@ -42,7 +42,7 @@ export class DialogEnergyGasSettings
this._params = params; this._params = params;
this._source = params.source this._source = params.source
? { ...params.source } ? { ...params.source }
: (this._source = emptyGasEnergyPreference()); : emptyGasEnergyPreference();
this._costs = this._source.entity_energy_price this._costs = this._source.entity_energy_price
? "entity" ? "entity"
: this._source.number_energy_price : this._source.number_energy_price

View File

@ -46,10 +46,9 @@ export class DialogEnergyGridFlowSettings
this._params = params; this._params = params;
this._source = params.source this._source = params.source
? { ...params.source } ? { ...params.source }
: (this._source = : params.direction === "from"
params.direction === "from" ? emptyFlowFromGridSourceEnergyPreference()
? emptyFlowFromGridSourceEnergyPreference() : emptyFlowToGridSourceEnergyPreference();
: emptyFlowToGridSourceEnergyPreference());
this._costs = this._source.entity_energy_price this._costs = this._source.entity_energy_price
? "entity" ? "entity"
: this._source.number_energy_price : this._source.number_energy_price

View File

@ -49,7 +49,7 @@ export class DialogEnergySolarSettings
this._fetchSolarForecastConfigEntries(); this._fetchSolarForecastConfigEntries();
this._source = params.source this._source = params.source
? { ...params.source } ? { ...params.source }
: (this._source = emptySolarEnergyPreference()); : emptySolarEnergyPreference();
this._forecast = this._source.config_entry_solar_forecast !== null; this._forecast = this._source.config_entry_solar_forecast !== null;
} }

View File

@ -173,7 +173,7 @@ export class ZHANetworkVisualizationPage extends LitElement {
.label=${this.hass.localize( .label=${this.hass.localize(
"ui.panel.config.zha.visualization.zoom_label" "ui.panel.config.zha.visualization.zoom_label"
)} )}
.deviceFilter=${(device) => this._filterDevices(device)} .deviceFilter=${this._filterDevices}
@value-changed=${this._onZoomToDevice} @value-changed=${this._onZoomToDevice}
></ha-device-picker> ></ha-device-picker>
<div class="controls"> <div class="controls">
@ -359,7 +359,7 @@ export class ZHANetworkVisualizationPage extends LitElement {
await refreshTopology(this.hass); await refreshTopology(this.hass);
} }
private _filterDevices(device: DeviceRegistryEntry): boolean { private _filterDevices = (device: DeviceRegistryEntry): boolean => {
if (!this.hass) { if (!this.hass) {
return false; return false;
} }
@ -371,7 +371,7 @@ export class ZHANetworkVisualizationPage extends LitElement {
} }
} }
return false; return false;
} };
private _handleCheckboxChange(ev: Event) { private _handleCheckboxChange(ev: Event) {
this._autoZoom = (ev.target as HaCheckbox).checked; this._autoZoom = (ev.target as HaCheckbox).checked;

View File

@ -493,7 +493,9 @@ class HaConfigZwave extends LocalizeMixin(EventsMixin(PolymerElement)) {
} }
computeEntities(selectedNode) { computeEntities(selectedNode) {
if (!this.nodes || selectedNode === -1) return -1; if (!this.nodes || selectedNode === -1) {
return -1;
}
const nodeid = this.nodes[this.selectedNode].attributes.node_id; const nodeid = this.nodes[this.selectedNode].attributes.node_id;
const hass = this.hass; const hass = this.hass;
return Object.keys(this.hass.states) return Object.keys(this.hass.states)
@ -512,7 +514,9 @@ class HaConfigZwave extends LocalizeMixin(EventsMixin(PolymerElement)) {
} }
selectedNodeChanged(selectedNode) { selectedNodeChanged(selectedNode) {
if (selectedNode === -1) return; if (selectedNode === -1) {
return;
}
this.selectedEntity = -1; this.selectedEntity = -1;
this.hass this.hass
@ -573,7 +577,9 @@ class HaConfigZwave extends LocalizeMixin(EventsMixin(PolymerElement)) {
} }
selectedEntityChanged(selectedEntity) { selectedEntityChanged(selectedEntity) {
if (selectedEntity === -1) return; if (selectedEntity === -1) {
return;
}
this.hass this.hass
.callApi( .callApi(
"GET", "GET",
@ -640,12 +646,16 @@ class HaConfigZwave extends LocalizeMixin(EventsMixin(PolymerElement)) {
} }
computeRefreshEntityServiceData(selectedEntity) { computeRefreshEntityServiceData(selectedEntity) {
if (selectedEntity === -1) return -1; if (selectedEntity === -1) {
return -1;
}
return { entity_id: this.entities[selectedEntity].entity_id }; return { entity_id: this.entities[selectedEntity].entity_id };
} }
computePollIntensityServiceData(entityPollingIntensity) { computePollIntensityServiceData(entityPollingIntensity) {
if (!this.selectedNode === -1 || this.selectedEntity === -1) return -1; if (this.selectedNode === -1 || this.selectedEntity === -1) {
return -1;
}
return { return {
node_id: this.nodes[this.selectedNode].attributes.node_id, node_id: this.nodes[this.selectedNode].attributes.node_id,
value_id: this.entities[this.selectedEntity].attributes.value_id, value_id: this.entities[this.selectedEntity].attributes.value_id,

View File

@ -300,12 +300,13 @@ class ZwaveGroups extends LocalizeMixin(PolymerElement) {
_computeAssocServiceData(selectedGroup, type) { _computeAssocServiceData(selectedGroup, type) {
if ( if (
!this.groups === -1 || !this.groups ||
selectedGroup === -1 || selectedGroup === -1 ||
this.selectedNode === -1 || this.selectedNode === -1 ||
this._selectedTargetNode === -1 this._selectedTargetNode === -1
) ) {
return -1; return -1;
}
return { return {
node_id: this.nodes[this.selectedNode].attributes.node_id, node_id: this.nodes[this.selectedNode].attributes.node_id,
association: type, association: type,

View File

@ -65,7 +65,7 @@ class DialogSystemLogDetail extends LitElement {
this._manifest && this._manifest &&
(this._manifest.is_built_in || (this._manifest.is_built_in ||
// Custom components with our offical docs should not link to our docs // Custom components with our offical docs should not link to our docs
!this._manifest.documentation.includes("www.home-assistant.io")); !this._manifest.documentation.includes("://www.home-assistant.io"));
return html` return html`
<ha-dialog open @closed=${this.closeDialog} hideActions .heading=${true}> <ha-dialog open @closed=${this.closeDialog} hideActions .heading=${true}>

View File

@ -77,7 +77,7 @@ class HaSceneDashboard extends LitElement {
title=${this.hass.localize( title=${this.hass.localize(
"ui.panel.config.scene.picker.activate_scene" "ui.panel.config.scene.picker.activate_scene"
)} )}
@click=${(ev: Event) => this._activateScene(ev)} @click=${this._activateScene}
> >
<ha-svg-icon .path=${mdiPlay}></ha-svg-icon> <ha-svg-icon .path=${mdiPlay}></ha-svg-icon>
</mwc-icon-button> </mwc-icon-button>
@ -213,7 +213,7 @@ class HaSceneDashboard extends LitElement {
fireEvent(this, "hass-more-info", { entityId }); fireEvent(this, "hass-more-info", { entityId });
} }
private async _activateScene(ev) { private _activateScene = async (ev) => {
ev.stopPropagation(); ev.stopPropagation();
const scene = ev.currentTarget.scene as SceneEntity; const scene = ev.currentTarget.scene as SceneEntity;
await activateScene(this.hass, scene.entity_id); await activateScene(this.hass, scene.entity_id);
@ -225,7 +225,7 @@ class HaSceneDashboard extends LitElement {
), ),
}); });
forwardHaptic("light"); forwardHaptic("light");
} };
private _showHelp() { private _showHelp() {
showAlertDialog(this, { showAlertDialog(this, {

View File

@ -201,7 +201,7 @@ export class HaSceneEditor extends SubscribeMixin(
.hass=${this.hass} .hass=${this.hass}
.narrow=${this.narrow} .narrow=${this.narrow}
.route=${this.route} .route=${this.route}
.backCallback=${() => this._backTapped()} .backCallback=${this._backTapped}
.tabs=${configSections.automation} .tabs=${configSections.automation}
> >
<ha-button-menu <ha-button-menu
@ -698,7 +698,7 @@ export class HaSceneEditor extends SubscribeMixin(
} }
} }
private _backTapped(): void { private _backTapped = (): void => {
if (this._dirty) { if (this._dirty) {
showConfirmationDialog(this, { showConfirmationDialog(this, {
text: this.hass!.localize( text: this.hass!.localize(
@ -711,7 +711,7 @@ export class HaSceneEditor extends SubscribeMixin(
} else { } else {
this._goBack(); this._goBack();
} }
} };
private _goBack(): void { private _goBack(): void {
applyScene(this.hass, this._storedStates); applyScene(this.hass, this._storedStates);

View File

@ -87,7 +87,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
.hass=${this.hass} .hass=${this.hass}
.narrow=${this.narrow} .narrow=${this.narrow}
.route=${this.route} .route=${this.route}
.backCallback=${() => this._backTapped()} .backCallback=${this._backTapped}
.tabs=${configSections.automation} .tabs=${configSections.automation}
> >
<ha-button-menu <ha-button-menu
@ -578,7 +578,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
this._dirty = true; this._dirty = true;
} }
private _backTapped(): void { private _backTapped = (): void => {
if (this._dirty) { if (this._dirty) {
showConfirmationDialog(this, { showConfirmationDialog(this, {
text: this.hass!.localize( text: this.hass!.localize(
@ -591,7 +591,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
} else { } else {
history.back(); history.back();
} }
} };
private async _duplicate() { private async _duplicate() {
if (this._dirty) { if (this._dirty) {

View File

@ -79,7 +79,7 @@ class HaScriptPicker extends LitElement {
title=${this.hass.localize( title=${this.hass.localize(
"ui.panel.config.script.picker.run_script" "ui.panel.config.script.picker.run_script"
)} )}
@click=${(ev: Event) => this._runScript(ev)} @click=${this._runScript}
> >
<ha-svg-icon .path=${mdiPlay}></ha-svg-icon> <ha-svg-icon .path=${mdiPlay}></ha-svg-icon>
</mwc-icon-button> </mwc-icon-button>
@ -234,7 +234,7 @@ class HaScriptPicker extends LitElement {
this._filterValue = undefined; this._filterValue = undefined;
} }
private async _runScript(ev) { private _runScript = async (ev) => {
ev.stopPropagation(); ev.stopPropagation();
const script = ev.currentTarget.script as HassEntity; const script = ev.currentTarget.script as HassEntity;
await triggerScript(this.hass, script.entity_id); await triggerScript(this.hass, script.entity_id);
@ -245,7 +245,7 @@ class HaScriptPicker extends LitElement {
computeStateName(script) computeStateName(script)
), ),
}); });
} };
private _showInfo(ev) { private _showInfo(ev) {
ev.stopPropagation(); ev.stopPropagation();

View File

@ -88,7 +88,7 @@ export class HaScriptTrace extends LitElement {
} }
const actionButtons = html` const actionButtons = html`
<mwc-icon-button label="Refresh" @click=${() => this._loadTraces()}> <mwc-icon-button label="Refresh" @click=${this._refreshTraces}>
<ha-svg-icon .path=${mdiRefresh}></ha-svg-icon> <ha-svg-icon .path=${mdiRefresh}></ha-svg-icon>
</mwc-icon-button> </mwc-icon-button>
<mwc-icon-button <mwc-icon-button
@ -321,6 +321,10 @@ export class HaScriptTrace extends LitElement {
this._selected = ev.detail; this._selected = ev.detail;
} }
private _refreshTraces() {
this._loadTraces();
}
private async _loadTraces(runId?: string) { private async _loadTraces(runId?: string) {
this._traces = await loadTraces( this._traces = await loadTraces(
this.hass, this.hass,

View File

@ -107,8 +107,7 @@ export class HaConfigTags extends SubscribeMixin(LitElement) {
type: "icon-button", type: "icon-button",
template: (_write, tag: any) => html` <mwc-icon-button template: (_write, tag: any) => html` <mwc-icon-button
.tag=${tag} .tag=${tag}
@click=${(ev: Event) => @click=${this._handleWriteClick}
this._openWrite((ev.currentTarget as any).tag)}
title=${this.hass.localize("ui.panel.config.tag.write")} title=${this.hass.localize("ui.panel.config.tag.write")}
> >
<ha-svg-icon .path=${mdiContentDuplicate}></ha-svg-icon> <ha-svg-icon .path=${mdiContentDuplicate}></ha-svg-icon>
@ -120,8 +119,7 @@ export class HaConfigTags extends SubscribeMixin(LitElement) {
type: "icon-button", type: "icon-button",
template: (_automation, tag: any) => html` <mwc-icon-button template: (_automation, tag: any) => html` <mwc-icon-button
.tag=${tag} .tag=${tag}
@click=${(ev: Event) => @click=${this._handleAutomationClick}
this._createAutomation((ev.currentTarget as any).tag)}
title=${this.hass.localize("ui.panel.config.tag.create_automation")} title=${this.hass.localize("ui.panel.config.tag.create_automation")}
> >
<ha-svg-icon .path=${mdiRobot}></ha-svg-icon> <ha-svg-icon .path=${mdiRobot}></ha-svg-icon>
@ -132,8 +130,7 @@ export class HaConfigTags extends SubscribeMixin(LitElement) {
type: "icon-button", type: "icon-button",
template: (_settings, tag: any) => html` <mwc-icon-button template: (_settings, tag: any) => html` <mwc-icon-button
.tag=${tag} .tag=${tag}
@click=${(ev: Event) => @click=${this._handleEditClick}
this._openDialog((ev.currentTarget as any).tag)}
title=${this.hass.localize("ui.panel.config.tag.edit")} title=${this.hass.localize("ui.panel.config.tag.edit")}
> >
<ha-svg-icon .path=${mdiCog}></ha-svg-icon> <ha-svg-icon .path=${mdiCog}></ha-svg-icon>
@ -209,6 +206,25 @@ export class HaConfigTags extends SubscribeMixin(LitElement) {
`; `;
} }
private _handleWriteClick = (ev: Event) =>
this._openWrite((ev.currentTarget as any).tag);
private _handleAutomationClick = (ev: Event) => {
const tag = (ev.currentTarget as any).tag;
const data = {
alias: this.hass.localize(
"ui.panel.config.tag.automation_title",
"name",
tag.name || tag.id
),
trigger: [{ platform: "tag", tag_id: tag.id } as TagTrigger],
};
showAutomationEditor(data);
};
private _handleEditClick = (ev: Event) =>
this._openDialog((ev.currentTarget as any).tag);
private _showHelp() { private _showHelp() {
showAlertDialog(this, { showAlertDialog(this, {
title: this.hass.localize("ui.panel.config.tag.caption"), title: this.hass.localize("ui.panel.config.tag.caption"),
@ -251,18 +267,6 @@ export class HaConfigTags extends SubscribeMixin(LitElement) {
}); });
} }
private _createAutomation(tag: Tag) {
const data = {
alias: this.hass.localize(
"ui.panel.config.tag.automation_title",
"name",
tag.name || tag.id
),
trigger: [{ platform: "tag", tag_id: tag.id } as TagTrigger],
};
showAutomationEditor(data);
}
private _addTag() { private _addTag() {
this._openDialog(); this._openDialog();
} }

View File

@ -41,7 +41,6 @@ class HaPanelDevStatistics extends LitElement {
this._validateStatistics(); this._validateStatistics();
} }
/* eslint-disable lit/no-template-arrow */
private _columns = memoizeOne( private _columns = memoizeOne(
(localize): DataTableColumnContainer => ({ (localize): DataTableColumnContainer => ({
state: { state: {
@ -82,16 +81,13 @@ class HaPanelDevStatistics extends LitElement {
issue.data issue.data
) || issue.type ) || issue.type
) )
: ""}`, : "No issues"}`,
}, },
fix: { fix: {
title: "", title: "",
template: (_, data: any) => template: (_, data: any) =>
html`${data.issues html`${data.issues
? html`<mwc-button ? html`<mwc-button @click=${this._fixIssue} .data=${data.issues}>
@click=${(ev) => this._fixIssue(ev)}
.data=${data.issues}
>
Fix issue Fix issue
</mwc-button>` </mwc-button>`
: ""}`, : ""}`,
@ -99,7 +95,6 @@ class HaPanelDevStatistics extends LitElement {
}, },
}) })
); );
/* eslint-enable lit/no-template-arrow */
protected render() { protected render() {
return html` return html`
@ -150,7 +145,7 @@ class HaPanelDevStatistics extends LitElement {
}); });
} }
private _fixIssue(ev) { private _fixIssue = (ev) => {
const issues = (ev.currentTarget.data as StatisticsValidationResult[]).sort( const issues = (ev.currentTarget.data as StatisticsValidationResult[]).sort(
(itemA, itemB) => (itemA, itemB) =>
(FIX_ISSUES_ORDER[itemA.type] ?? 99) - (FIX_ISSUES_ORDER[itemA.type] ?? 99) -
@ -236,7 +231,7 @@ class HaPanelDevStatistics extends LitElement {
text: "Fixing this issue is not supported yet.", text: "Fixing this issue is not supported yet.",
}); });
} }
} };
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return [ return [

View File

@ -164,21 +164,6 @@ export class HuiEnergyDevicesGraphCard
) )
); );
const statisticsData = Object.values(this._data!);
let endTime: Date;
endTime = new Date(
Math.max(
...statisticsData.map((stats) =>
stats.length ? new Date(stats[stats.length - 1].start).getTime() : 0
)
)
);
if (!endTime || endTime > new Date()) {
endTime = new Date();
}
const data: Array<ChartDataset<"bar", ParsedDataType<"bar">>["data"]> = []; const data: Array<ChartDataset<"bar", ParsedDataType<"bar">>["data"]> = [];
const borderColor: string[] = []; const borderColor: string[] = [];
const backgroundColor: string[] = []; const backgroundColor: string[] = [];

View File

@ -220,21 +220,7 @@ export class HuiEnergyGasGraphCard
this._unit = getEnergyGasUnit(this.hass, energyData.prefs) || "m³"; this._unit = getEnergyGasUnit(this.hass, energyData.prefs) || "m³";
const statisticsData = Object.values(energyData.stats);
const datasets: ChartDataset<"bar">[] = []; const datasets: ChartDataset<"bar">[] = [];
let endTime: Date;
endTime = new Date(
Math.max(
...statisticsData.map((stats) =>
stats.length ? new Date(stats[stats.length - 1].start).getTime() : 0
)
)
);
if (!endTime || endTime > new Date()) {
endTime = new Date();
}
const computedStyles = getComputedStyle(this); const computedStyles = getComputedStyle(this);
const gasColor = computedStyles const gasColor = computedStyles

View File

@ -226,21 +226,7 @@ export class HuiEnergySolarGraphCard
} }
} }
const statisticsData = Object.values(energyData.stats);
const datasets: ChartDataset<"bar">[] = []; const datasets: ChartDataset<"bar">[] = [];
let endTime: Date;
endTime = new Date(
Math.max(
...statisticsData.map((stats) =>
stats.length ? new Date(stats[stats.length - 1].start).getTime() : 0
)
)
);
if (!endTime || endTime > new Date()) {
endTime = new Date();
}
const computedStyles = getComputedStyle(this); const computedStyles = getComputedStyle(this);
const solarColor = computedStyles const solarColor = computedStyles

View File

@ -88,7 +88,7 @@ export class HuiEnergyUsageGraphCard
)} )}
chart-type="bar" chart-type="bar"
></ha-chart-base> ></ha-chart-base>
${!this._chartData.datasets.length ${!this._chartData.datasets.some((dataset) => dataset.data.length)
? html`<div class="no-data"> ? html`<div class="no-data">
${isToday(this._start) ${isToday(this._start)
? "There is no data to show. It can take up to 2 hours for new data to arrive after you configure your energy dashboard." ? "There is no data to show. It can take up to 2 hours for new data to arrive after you configure your energy dashboard."
@ -228,6 +228,8 @@ export class HuiEnergyUsageGraphCard
); );
private async _getStatistics(energyData: EnergyData): Promise<void> { private async _getStatistics(energyData: EnergyData): Promise<void> {
const datasets: ChartDataset<"bar">[] = [];
const statistics: { const statistics: {
to_grid?: string[]; to_grid?: string[];
from_grid?: string[]; from_grid?: string[];
@ -283,33 +285,9 @@ export class HuiEnergyUsageGraphCard
energyData.start energyData.start
); );
const statisticsData = Object.values(energyData.stats);
const datasets: ChartDataset<"bar">[] = [];
let endTime: Date;
this._start = energyData.start; this._start = energyData.start;
this._end = energyData.end || endOfToday(); this._end = energyData.end || endOfToday();
if (statisticsData.length === 0) {
this._chartData = {
datasets,
};
return;
}
endTime = new Date(
Math.max(
...statisticsData.map((stats) =>
stats.length ? new Date(stats[stats.length - 1].start).getTime() : 0
)
)
);
if (endTime > new Date()) {
endTime = new Date();
}
const combinedData: { const combinedData: {
to_grid?: { [statId: string]: { [start: string]: number } }; to_grid?: { [statId: string]: { [start: string]: number } };
to_battery?: { [statId: string]: { [start: string]: number } }; to_battery?: { [statId: string]: { [start: string]: number } };

View File

@ -104,12 +104,7 @@ class HuiTimestampDisplay extends LitElement {
this._relative = this._relative =
this._format === "relative" this._format === "relative"
? relativeTime(this.ts, this.hass!.locale) ? relativeTime(this.ts, this.hass!.locale)
: (this._relative = relativeTime( : relativeTime(new Date(), this.hass!.locale, this.ts, false);
new Date(),
this.hass!.locale,
this.ts,
false
));
} }
} }
} }

View File

@ -90,8 +90,7 @@ export class HuiCreateDialogCard
</ha-header-bar> </ha-header-bar>
<mwc-tab-bar <mwc-tab-bar
.activeIndex=${this._currTabIndex} .activeIndex=${this._currTabIndex}
@MDCTabBar:activated=${(ev: CustomEvent) => @MDCTabBar:activated=${this._handleTabChanged}
this._handleTabChanged(ev)}
> >
<mwc-tab <mwc-tab
.label=${this.hass!.localize( .label=${this.hass!.localize(

View File

@ -218,7 +218,7 @@ class HaPanelMy extends LitElement {
protected render() { protected render() {
if (this._error) { if (this._error) {
let error = "Unknown error"; let error: string;
switch (this._error) { switch (this._error) {
case "not_supported": case "not_supported":
error = error =

View File

@ -1091,10 +1091,14 @@
"title": "Unexpected unit of measurement", "title": "Unexpected unit of measurement",
"description": "The following entities do not have the expected units of measurement 'kWh', 'm³' or 'ft³':" "description": "The following entities do not have the expected units of measurement 'kWh', 'm³' or 'ft³':"
}, },
"entity_unexpected_unit_price": { "entity_unexpected_unit_energy_price": {
"title": "Unexpected unit of measurement", "title": "Unexpected unit of measurement",
"description": "The following entities do not have the expected units of measurement ''{currency}/kWh'' or ''{currency}/Wh'':" "description": "The following entities do not have the expected units of measurement ''{currency}/kWh'' or ''{currency}/Wh'':"
}, },
"entity_unexpected_unit_gas_price": {
"title": "Unexpected unit of measurement",
"description": "The following entities do not have the expected units of measurement ''{currency}/kWh'', ''{currency}/Wh'', ''{currency}/m³'' or ''{currency}/ft³'':"
},
"entity_unexpected_state_class": { "entity_unexpected_state_class": {
"title": "Unexpected state class", "title": "Unexpected state class",
"description": "The following entities do not have the expected state class:" "description": "The following entities do not have the expected state class:"

View File

@ -124,7 +124,7 @@ hassAttributeUtil.LOGIC_STATE_ATTRIBUTES = {
}, },
state_class: { state_class: {
type: "array", type: "array",
options: { sensor: ["measurement"] }, options: { sensor: ["measurement", "total", "total_increasing"] },
description: "State class", description: "State class",
domains: ["sensor"], domains: ["sensor"],
}, },