mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
20240402.2 (#20348)
This commit is contained in:
commit
29eb73176a
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "home-assistant-frontend"
|
name = "home-assistant-frontend"
|
||||||
version = "20240402.1"
|
version = "20240402.2"
|
||||||
license = {text = "Apache-2.0"}
|
license = {text = "Apache-2.0"}
|
||||||
description = "The Home Assistant frontend"
|
description = "The Home Assistant frontend"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { SelectedDetail } from "@material/mwc-list";
|
import { SelectedDetail } from "@material/mwc-list";
|
||||||
import "@material/mwc-menu/mwc-menu-surface";
|
import "@material/mwc-menu/mwc-menu-surface";
|
||||||
|
import { mdiFilterVariantRemove } from "@mdi/js";
|
||||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { findRelated, RelatedResult } from "../data/search";
|
|
||||||
import type { HomeAssistant } from "../types";
|
|
||||||
import { haStyleScrollbar } from "../resources/styles";
|
|
||||||
import { Blueprints, fetchBlueprints } from "../data/blueprint";
|
import { Blueprints, fetchBlueprints } from "../data/blueprint";
|
||||||
|
import { findRelated, RelatedResult } from "../data/search";
|
||||||
|
import { haStyleScrollbar } from "../resources/styles";
|
||||||
|
import type { HomeAssistant } from "../types";
|
||||||
|
|
||||||
@customElement("ha-filter-blueprints")
|
@customElement("ha-filter-blueprints")
|
||||||
export class HaFilterBlueprints extends LitElement {
|
export class HaFilterBlueprints extends LitElement {
|
||||||
@ -35,7 +36,11 @@ export class HaFilterBlueprints extends LitElement {
|
|||||||
<div slot="header" class="header">
|
<div slot="header" class="header">
|
||||||
${this.hass.localize("ui.panel.config.blueprint.caption")}
|
${this.hass.localize("ui.panel.config.blueprint.caption")}
|
||||||
${this.value?.length
|
${this.value?.length
|
||||||
? html`<div class="badge">${this.value?.length}</div>`
|
? html`<div class="badge">${this.value?.length}</div>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiFilterVariantRemove}
|
||||||
|
@click=${this._clearFilter}
|
||||||
|
></ha-icon-button>`
|
||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${this._blueprints && this._shouldRender
|
${this._blueprints && this._shouldRender
|
||||||
@ -128,6 +133,15 @@ export class HaFilterBlueprints extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _clearFilter(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.value = undefined;
|
||||||
|
fireEvent(this, "data-table-filter-changed", {
|
||||||
|
value: undefined,
|
||||||
|
items: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyleScrollbar,
|
haStyleScrollbar,
|
||||||
@ -147,6 +161,10 @@ export class HaFilterBlueprints extends LitElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.header ha-icon-button {
|
||||||
|
margin-inline-start: auto;
|
||||||
|
margin-inline-end: 8px;
|
||||||
|
}
|
||||||
.badge {
|
.badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
@ -2,6 +2,7 @@ import { ActionDetail, SelectedDetail } from "@material/mwc-list";
|
|||||||
import {
|
import {
|
||||||
mdiDelete,
|
mdiDelete,
|
||||||
mdiDotsVertical,
|
mdiDotsVertical,
|
||||||
|
mdiFilterVariantRemove,
|
||||||
mdiPencil,
|
mdiPencil,
|
||||||
mdiPlus,
|
mdiPlus,
|
||||||
mdiTag,
|
mdiTag,
|
||||||
@ -68,7 +69,11 @@ export class HaFilterCategories extends SubscribeMixin(LitElement) {
|
|||||||
<div slot="header" class="header">
|
<div slot="header" class="header">
|
||||||
${this.hass.localize("ui.panel.config.category.caption")}
|
${this.hass.localize("ui.panel.config.category.caption")}
|
||||||
${this.value?.length
|
${this.value?.length
|
||||||
? html`<div class="badge">${this.value?.length}</div>`
|
? html`<div class="badge">${this.value?.length}</div>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiFilterVariantRemove}
|
||||||
|
@click=${this._clearFilter}
|
||||||
|
></ha-icon-button>`
|
||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${this._shouldRender
|
${this._shouldRender
|
||||||
@ -254,6 +259,15 @@ export class HaFilterCategories extends SubscribeMixin(LitElement) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _clearFilter(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.value = undefined;
|
||||||
|
fireEvent(this, "data-table-filter-changed", {
|
||||||
|
value: undefined,
|
||||||
|
items: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyleScrollbar,
|
haStyleScrollbar,
|
||||||
@ -274,6 +288,10 @@ export class HaFilterCategories extends SubscribeMixin(LitElement) {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.header ha-icon-button {
|
||||||
|
margin-inline-start: auto;
|
||||||
|
margin-inline-end: 8px;
|
||||||
|
}
|
||||||
.badge {
|
.badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { mdiFilterVariantRemove } from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
@ -13,10 +14,11 @@ import { stringCompare } from "../common/string/compare";
|
|||||||
import { computeDeviceName } from "../data/device_registry";
|
import { computeDeviceName } from "../data/device_registry";
|
||||||
import { findRelated, RelatedResult } from "../data/search";
|
import { findRelated, RelatedResult } from "../data/search";
|
||||||
import { haStyleScrollbar } from "../resources/styles";
|
import { haStyleScrollbar } from "../resources/styles";
|
||||||
import type { HomeAssistant } from "../types";
|
|
||||||
import "./ha-expansion-panel";
|
|
||||||
import "./ha-check-list-item";
|
|
||||||
import { loadVirtualizer } from "../resources/virtualizer";
|
import { loadVirtualizer } from "../resources/virtualizer";
|
||||||
|
import type { HomeAssistant } from "../types";
|
||||||
|
import "./ha-check-list-item";
|
||||||
|
import "./ha-expansion-panel";
|
||||||
|
import "./search-input-outlined";
|
||||||
|
|
||||||
@customElement("ha-filter-devices")
|
@customElement("ha-filter-devices")
|
||||||
export class HaFilterDevices extends LitElement {
|
export class HaFilterDevices extends LitElement {
|
||||||
@ -32,6 +34,8 @@ export class HaFilterDevices extends LitElement {
|
|||||||
|
|
||||||
@state() private _shouldRender = false;
|
@state() private _shouldRender = false;
|
||||||
|
|
||||||
|
@state() private _filter?: string;
|
||||||
|
|
||||||
public willUpdate(properties: PropertyValues) {
|
public willUpdate(properties: PropertyValues) {
|
||||||
super.willUpdate(properties);
|
super.willUpdate(properties);
|
||||||
|
|
||||||
@ -51,19 +55,33 @@ export class HaFilterDevices extends LitElement {
|
|||||||
<div slot="header" class="header">
|
<div slot="header" class="header">
|
||||||
${this.hass.localize("ui.panel.config.devices.caption")}
|
${this.hass.localize("ui.panel.config.devices.caption")}
|
||||||
${this.value?.length
|
${this.value?.length
|
||||||
? html`<div class="badge">${this.value?.length}</div>`
|
? html`<div class="badge">${this.value?.length}</div>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiFilterVariantRemove}
|
||||||
|
@click=${this._clearFilter}
|
||||||
|
></ha-icon-button>`
|
||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${this._shouldRender
|
${this._shouldRender
|
||||||
? html`<mwc-list class="ha-scrollbar">
|
? html`<search-input-outlined
|
||||||
<lit-virtualizer
|
.hass=${this.hass}
|
||||||
.items=${this._devices(this.hass.devices, this.value)}
|
.filter=${this._filter}
|
||||||
.keyFunction=${this._keyFunction}
|
@value-changed=${this._handleSearchChange}
|
||||||
.renderItem=${this._renderItem}
|
|
||||||
@click=${this._handleItemClick}
|
|
||||||
>
|
>
|
||||||
</lit-virtualizer>
|
</search-input-outlined>
|
||||||
</mwc-list>`
|
<mwc-list class="ha-scrollbar">
|
||||||
|
<lit-virtualizer
|
||||||
|
.items=${this._devices(
|
||||||
|
this.hass.devices,
|
||||||
|
this._filter || "",
|
||||||
|
this.value
|
||||||
|
)}
|
||||||
|
.keyFunction=${this._keyFunction}
|
||||||
|
.renderItem=${this._renderItem}
|
||||||
|
@click=${this._handleItemClick}
|
||||||
|
>
|
||||||
|
</lit-virtualizer>
|
||||||
|
</mwc-list>`
|
||||||
: nothing}
|
: nothing}
|
||||||
</ha-expansion-panel>
|
</ha-expansion-panel>
|
||||||
`;
|
`;
|
||||||
@ -72,12 +90,14 @@ export class HaFilterDevices extends LitElement {
|
|||||||
private _keyFunction = (device) => device?.id;
|
private _keyFunction = (device) => device?.id;
|
||||||
|
|
||||||
private _renderItem = (device) =>
|
private _renderItem = (device) =>
|
||||||
html`<ha-check-list-item
|
!device
|
||||||
.value=${device.id}
|
? nothing
|
||||||
.selected=${this.value?.includes(device.id)}
|
: html`<ha-check-list-item
|
||||||
>
|
.value=${device.id}
|
||||||
${computeDeviceName(device, this.hass)}
|
.selected=${this.value?.includes(device.id)}
|
||||||
</ha-check-list-item>`;
|
>
|
||||||
|
${computeDeviceName(device, this.hass)}
|
||||||
|
</ha-check-list-item>`;
|
||||||
|
|
||||||
private _handleItemClick(ev) {
|
private _handleItemClick(ev) {
|
||||||
const listItem = ev.target.closest("ha-check-list-item");
|
const listItem = ev.target.closest("ha-check-list-item");
|
||||||
@ -99,7 +119,7 @@ export class HaFilterDevices extends LitElement {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!this.expanded) return;
|
if (!this.expanded) return;
|
||||||
this.renderRoot.querySelector("mwc-list")!.style.height =
|
this.renderRoot.querySelector("mwc-list")!.style.height =
|
||||||
`${this.clientHeight - 49}px`;
|
`${this.clientHeight - 49 - 32}px`; // 32px is the height of the search input
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,16 +132,28 @@ export class HaFilterDevices extends LitElement {
|
|||||||
this.expanded = ev.detail.expanded;
|
this.expanded = ev.detail.expanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _devices = memoizeOne((devices: HomeAssistant["devices"], _value) => {
|
private _handleSearchChange(ev: CustomEvent) {
|
||||||
const values = Object.values(devices);
|
this._filter = ev.detail.value.toLowerCase();
|
||||||
return values.sort((a, b) =>
|
}
|
||||||
stringCompare(
|
|
||||||
a.name_by_user || a.name || "",
|
private _devices = memoizeOne(
|
||||||
b.name_by_user || b.name || "",
|
(devices: HomeAssistant["devices"], filter: string, _value) => {
|
||||||
this.hass.locale.language
|
const values = Object.values(devices);
|
||||||
)
|
return values
|
||||||
);
|
.filter(
|
||||||
});
|
(device) =>
|
||||||
|
!filter ||
|
||||||
|
computeDeviceName(device, this.hass).toLowerCase().includes(filter)
|
||||||
|
)
|
||||||
|
.sort((a, b) =>
|
||||||
|
stringCompare(
|
||||||
|
computeDeviceName(a, this.hass),
|
||||||
|
computeDeviceName(b, this.hass),
|
||||||
|
this.hass.locale.language
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
private async _findRelated() {
|
private async _findRelated() {
|
||||||
const relatedPromises: Promise<RelatedResult>[] = [];
|
const relatedPromises: Promise<RelatedResult>[] = [];
|
||||||
@ -158,6 +190,15 @@ export class HaFilterDevices extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _clearFilter(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.value = undefined;
|
||||||
|
fireEvent(this, "data-table-filter-changed", {
|
||||||
|
value: undefined,
|
||||||
|
items: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyleScrollbar,
|
haStyleScrollbar,
|
||||||
@ -178,6 +219,10 @@ export class HaFilterDevices extends LitElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.header ha-icon-button {
|
||||||
|
margin-inline-start: auto;
|
||||||
|
margin-inline-end: 8px;
|
||||||
|
}
|
||||||
.badge {
|
.badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
@ -197,6 +242,10 @@ export class HaFilterDevices extends LitElement {
|
|||||||
ha-check-list-item {
|
ha-check-list-item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
search-input-outlined {
|
||||||
|
display: block;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { mdiFilterVariantRemove } from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
@ -14,10 +15,11 @@ import { computeStateName } from "../common/entity/compute_state_name";
|
|||||||
import { stringCompare } from "../common/string/compare";
|
import { stringCompare } from "../common/string/compare";
|
||||||
import { findRelated, RelatedResult } from "../data/search";
|
import { findRelated, RelatedResult } from "../data/search";
|
||||||
import { haStyleScrollbar } from "../resources/styles";
|
import { haStyleScrollbar } from "../resources/styles";
|
||||||
import type { HomeAssistant } from "../types";
|
|
||||||
import "./ha-state-icon";
|
|
||||||
import "./ha-check-list-item";
|
|
||||||
import { loadVirtualizer } from "../resources/virtualizer";
|
import { loadVirtualizer } from "../resources/virtualizer";
|
||||||
|
import type { HomeAssistant } from "../types";
|
||||||
|
import "./ha-check-list-item";
|
||||||
|
import "./ha-state-icon";
|
||||||
|
import "./search-input-outlined";
|
||||||
|
|
||||||
@customElement("ha-filter-entities")
|
@customElement("ha-filter-entities")
|
||||||
export class HaFilterEntities extends LitElement {
|
export class HaFilterEntities extends LitElement {
|
||||||
@ -33,6 +35,8 @@ export class HaFilterEntities extends LitElement {
|
|||||||
|
|
||||||
@state() private _shouldRender = false;
|
@state() private _shouldRender = false;
|
||||||
|
|
||||||
|
@state() private _filter?: string;
|
||||||
|
|
||||||
public willUpdate(properties: PropertyValues) {
|
public willUpdate(properties: PropertyValues) {
|
||||||
super.willUpdate(properties);
|
super.willUpdate(properties);
|
||||||
|
|
||||||
@ -52,16 +56,27 @@ export class HaFilterEntities extends LitElement {
|
|||||||
<div slot="header" class="header">
|
<div slot="header" class="header">
|
||||||
${this.hass.localize("ui.panel.config.entities.caption")}
|
${this.hass.localize("ui.panel.config.entities.caption")}
|
||||||
${this.value?.length
|
${this.value?.length
|
||||||
? html`<div class="badge">${this.value?.length}</div>`
|
? html`<div class="badge">${this.value?.length}</div>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiFilterVariantRemove}
|
||||||
|
@click=${this._clearFilter}
|
||||||
|
></ha-icon-button>`
|
||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${this._shouldRender
|
${this._shouldRender
|
||||||
? html`
|
? html`
|
||||||
|
<search-input-outlined
|
||||||
|
.hass=${this.hass}
|
||||||
|
.filter=${this._filter}
|
||||||
|
@value-changed=${this._handleSearchChange}
|
||||||
|
>
|
||||||
|
</search-input-outlined>
|
||||||
<mwc-list class="ha-scrollbar">
|
<mwc-list class="ha-scrollbar">
|
||||||
<lit-virtualizer
|
<lit-virtualizer
|
||||||
.items=${this._entities(
|
.items=${this._entities(
|
||||||
this.hass.states,
|
this.hass.states,
|
||||||
this.type,
|
this.type,
|
||||||
|
this._filter || "",
|
||||||
this.value
|
this.value
|
||||||
)}
|
)}
|
||||||
.keyFunction=${this._keyFunction}
|
.keyFunction=${this._keyFunction}
|
||||||
@ -81,7 +96,7 @@ export class HaFilterEntities extends LitElement {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!this.expanded) return;
|
if (!this.expanded) return;
|
||||||
this.renderRoot.querySelector("mwc-list")!.style.height =
|
this.renderRoot.querySelector("mwc-list")!.style.height =
|
||||||
`${this.clientHeight - 49}px`;
|
`${this.clientHeight - 49 - 32}px`; // 32px is the height of the search input
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,18 +104,20 @@ export class HaFilterEntities extends LitElement {
|
|||||||
private _keyFunction = (entity) => entity?.entity_id;
|
private _keyFunction = (entity) => entity?.entity_id;
|
||||||
|
|
||||||
private _renderItem = (entity) =>
|
private _renderItem = (entity) =>
|
||||||
html`<ha-check-list-item
|
!entity
|
||||||
.value=${entity.entity_id}
|
? nothing
|
||||||
.selected=${this.value?.includes(entity.entity_id)}
|
: html`<ha-check-list-item
|
||||||
graphic="icon"
|
.value=${entity.entity_id}
|
||||||
>
|
.selected=${this.value?.includes(entity.entity_id)}
|
||||||
<ha-state-icon
|
graphic="icon"
|
||||||
slot="graphic"
|
>
|
||||||
.hass=${this.hass}
|
<ha-state-icon
|
||||||
.stateObj=${entity}
|
slot="graphic"
|
||||||
></ha-state-icon>
|
.hass=${this.hass}
|
||||||
${computeStateName(entity)}
|
.stateObj=${entity}
|
||||||
</ha-check-list-item>`;
|
></ha-state-icon>
|
||||||
|
${computeStateName(entity)}
|
||||||
|
</ha-check-list-item>`;
|
||||||
|
|
||||||
private _handleItemClick(ev) {
|
private _handleItemClick(ev) {
|
||||||
const listItem = ev.target.closest("ha-check-list-item");
|
const listItem = ev.target.closest("ha-check-list-item");
|
||||||
@ -125,12 +142,27 @@ export class HaFilterEntities extends LitElement {
|
|||||||
this.expanded = ev.detail.expanded;
|
this.expanded = ev.detail.expanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _handleSearchChange(ev: CustomEvent) {
|
||||||
|
this._filter = ev.detail.value.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
private _entities = memoizeOne(
|
private _entities = memoizeOne(
|
||||||
(states: HomeAssistant["states"], type: this["type"], _value) => {
|
(
|
||||||
|
states: HomeAssistant["states"],
|
||||||
|
type: this["type"],
|
||||||
|
filter: string,
|
||||||
|
_value
|
||||||
|
) => {
|
||||||
const values = Object.values(states);
|
const values = Object.values(states);
|
||||||
return values
|
return values
|
||||||
.filter(
|
.filter(
|
||||||
(entityState) => !type || computeStateDomain(entityState) !== type
|
(entityState) =>
|
||||||
|
(!type || computeStateDomain(entityState) !== type) &&
|
||||||
|
(!filter ||
|
||||||
|
entityState.entity_id.toLowerCase().includes(filter) ||
|
||||||
|
entityState.attributes.friendly_name
|
||||||
|
?.toLowerCase()
|
||||||
|
.includes(filter))
|
||||||
)
|
)
|
||||||
.sort((a, b) =>
|
.sort((a, b) =>
|
||||||
stringCompare(
|
stringCompare(
|
||||||
@ -177,6 +209,15 @@ export class HaFilterEntities extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _clearFilter(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.value = undefined;
|
||||||
|
fireEvent(this, "data-table-filter-changed", {
|
||||||
|
value: undefined,
|
||||||
|
items: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyleScrollbar,
|
haStyleScrollbar,
|
||||||
@ -196,6 +237,10 @@ export class HaFilterEntities extends LitElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.header ha-icon-button {
|
||||||
|
margin-inline-start: auto;
|
||||||
|
margin-inline-end: 8px;
|
||||||
|
}
|
||||||
.badge {
|
.badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
@ -216,6 +261,10 @@ export class HaFilterEntities extends LitElement {
|
|||||||
--mdc-list-item-graphic-margin: 16px;
|
--mdc-list-item-graphic-margin: 16px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
search-input-outlined {
|
||||||
|
display: block;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import "@material/mwc-menu/mwc-menu-surface";
|
import "@material/mwc-menu/mwc-menu-surface";
|
||||||
import { mdiTextureBox } from "@mdi/js";
|
import { mdiFilterVariantRemove, mdiTextureBox } from "@mdi/js";
|
||||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
@ -53,9 +53,13 @@ export class HaFilterFloorAreas extends SubscribeMixin(LitElement) {
|
|||||||
${this.hass.localize("ui.panel.config.areas.caption")}
|
${this.hass.localize("ui.panel.config.areas.caption")}
|
||||||
${this.value?.areas?.length || this.value?.floors?.length
|
${this.value?.areas?.length || this.value?.floors?.length
|
||||||
? html`<div class="badge">
|
? html`<div class="badge">
|
||||||
${(this.value?.areas?.length || 0) +
|
${(this.value?.areas?.length || 0) +
|
||||||
(this.value?.floors?.length || 0)}
|
(this.value?.floors?.length || 0)}
|
||||||
</div>`
|
</div>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiFilterVariantRemove}
|
||||||
|
@click=${this._clearFilter}
|
||||||
|
></ha-icon-button>`
|
||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${this._shouldRender
|
${this._shouldRender
|
||||||
@ -238,6 +242,15 @@ export class HaFilterFloorAreas extends SubscribeMixin(LitElement) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _clearFilter(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.value = undefined;
|
||||||
|
fireEvent(this, "data-table-filter-changed", {
|
||||||
|
value: undefined,
|
||||||
|
items: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyleScrollbar,
|
haStyleScrollbar,
|
||||||
@ -257,6 +270,10 @@ export class HaFilterFloorAreas extends SubscribeMixin(LitElement) {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.header ha-icon-button {
|
||||||
|
margin-inline-start: auto;
|
||||||
|
margin-inline-end: 8px;
|
||||||
|
}
|
||||||
.badge {
|
.badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { SelectedDetail } from "@material/mwc-list";
|
import { SelectedDetail } from "@material/mwc-list";
|
||||||
|
import { mdiFilterVariantRemove } from "@mdi/js";
|
||||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { repeat } from "lit/directives/repeat";
|
import { repeat } from "lit/directives/repeat";
|
||||||
@ -38,7 +39,11 @@ export class HaFilterIntegrations extends LitElement {
|
|||||||
<div slot="header" class="header">
|
<div slot="header" class="header">
|
||||||
${this.hass.localize("ui.panel.config.integrations.caption")}
|
${this.hass.localize("ui.panel.config.integrations.caption")}
|
||||||
${this.value?.length
|
${this.value?.length
|
||||||
? html`<div class="badge">${this.value?.length}</div>`
|
? html`<div class="badge">${this.value?.length}</div>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiFilterVariantRemove}
|
||||||
|
@click=${this._clearFilter}
|
||||||
|
></ha-icon-button>`
|
||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${this._manifests && this._shouldRender
|
${this._manifests && this._shouldRender
|
||||||
@ -142,6 +147,15 @@ export class HaFilterIntegrations extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _clearFilter(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.value = undefined;
|
||||||
|
fireEvent(this, "data-table-filter-changed", {
|
||||||
|
value: undefined,
|
||||||
|
items: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyleScrollbar,
|
haStyleScrollbar,
|
||||||
@ -161,6 +175,10 @@ export class HaFilterIntegrations extends LitElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.header ha-icon-button {
|
||||||
|
margin-inline-start: auto;
|
||||||
|
margin-inline-end: 8px;
|
||||||
|
}
|
||||||
.badge {
|
.badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
import { SelectedDetail } from "@material/mwc-list";
|
import { SelectedDetail } from "@material/mwc-list";
|
||||||
import "@material/mwc-menu/mwc-menu-surface";
|
import "@material/mwc-menu/mwc-menu-surface";
|
||||||
import { mdiPlus } from "@mdi/js";
|
import { mdiCog, mdiFilterVariantRemove } from "@mdi/js";
|
||||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
|
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { repeat } from "lit/directives/repeat";
|
import { repeat } from "lit/directives/repeat";
|
||||||
import { computeCssColor } from "../common/color/compute-color";
|
import { computeCssColor } from "../common/color/compute-color";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
import { navigate } from "../common/navigate";
|
||||||
import {
|
import {
|
||||||
LabelRegistryEntry,
|
LabelRegistryEntry,
|
||||||
createLabelRegistryEntry,
|
|
||||||
subscribeLabelRegistry,
|
subscribeLabelRegistry,
|
||||||
} from "../data/label_registry";
|
} from "../data/label_registry";
|
||||||
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
||||||
import { showLabelDetailDialog } from "../panels/config/labels/show-dialog-label-detail";
|
|
||||||
import { haStyleScrollbar } from "../resources/styles";
|
import { haStyleScrollbar } from "../resources/styles";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import "./ha-check-list-item";
|
import "./ha-check-list-item";
|
||||||
@ -54,7 +53,11 @@ export class HaFilterLabels extends SubscribeMixin(LitElement) {
|
|||||||
<div slot="header" class="header">
|
<div slot="header" class="header">
|
||||||
${this.hass.localize("ui.panel.config.labels.caption")}
|
${this.hass.localize("ui.panel.config.labels.caption")}
|
||||||
${this.value?.length
|
${this.value?.length
|
||||||
? html`<div class="badge">${this.value?.length}</div>`
|
? html`<div class="badge">${this.value?.length}</div>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiFilterVariantRemove}
|
||||||
|
@click=${this._clearFilter}
|
||||||
|
></ha-icon-button>`
|
||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${this._shouldRender
|
${this._shouldRender
|
||||||
@ -95,11 +98,11 @@ export class HaFilterLabels extends SubscribeMixin(LitElement) {
|
|||||||
${this.expanded
|
${this.expanded
|
||||||
? html`<ha-list-item
|
? html`<ha-list-item
|
||||||
graphic="icon"
|
graphic="icon"
|
||||||
@click=${this._addLabel}
|
@click=${this._manageLabels}
|
||||||
class="add"
|
class="add"
|
||||||
>
|
>
|
||||||
<ha-svg-icon slot="graphic" .path=${mdiPlus}></ha-svg-icon>
|
<ha-svg-icon slot="graphic" .path=${mdiCog}></ha-svg-icon>
|
||||||
${this.hass.localize("ui.panel.config.labels.add_label")}
|
${this.hass.localize("ui.panel.config.labels.manage_labels")}
|
||||||
</ha-list-item>`
|
</ha-list-item>`
|
||||||
: nothing}
|
: nothing}
|
||||||
`;
|
`;
|
||||||
@ -115,10 +118,8 @@ export class HaFilterLabels extends SubscribeMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _addLabel() {
|
private _manageLabels() {
|
||||||
showLabelDetailDialog(this, {
|
navigate("/config/labels");
|
||||||
createEntry: (values) => createLabelRegistryEntry(this.hass, values),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _expandedWillChange(ev) {
|
private _expandedWillChange(ev) {
|
||||||
@ -153,6 +154,15 @@ export class HaFilterLabels extends SubscribeMixin(LitElement) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _clearFilter(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.value = undefined;
|
||||||
|
fireEvent(this, "data-table-filter-changed", {
|
||||||
|
value: undefined,
|
||||||
|
items: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyleScrollbar,
|
haStyleScrollbar,
|
||||||
@ -173,6 +183,10 @@ export class HaFilterLabels extends SubscribeMixin(LitElement) {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.header ha-icon-button {
|
||||||
|
margin-inline-start: auto;
|
||||||
|
margin-inline-end: 8px;
|
||||||
|
}
|
||||||
.badge {
|
.badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { SelectedDetail } from "@material/mwc-list";
|
import { SelectedDetail } from "@material/mwc-list";
|
||||||
|
import { mdiFilterVariantRemove } from "@mdi/js";
|
||||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { haStyleScrollbar } from "../resources/styles";
|
import { haStyleScrollbar } from "../resources/styles";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import "./ha-expansion-panel";
|
|
||||||
import "./ha-check-list-item";
|
import "./ha-check-list-item";
|
||||||
|
import "./ha-expansion-panel";
|
||||||
import "./ha-icon";
|
import "./ha-icon";
|
||||||
|
|
||||||
@customElement("ha-filter-states")
|
@customElement("ha-filter-states")
|
||||||
@ -43,7 +44,11 @@ export class HaFilterStates extends LitElement {
|
|||||||
<div slot="header" class="header">
|
<div slot="header" class="header">
|
||||||
${this.label}
|
${this.label}
|
||||||
${this.value?.length
|
${this.value?.length
|
||||||
? html`<div class="badge">${this.value?.length}</div>`
|
? html`<div class="badge">${this.value?.length}</div>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiFilterVariantRemove}
|
||||||
|
@click=${this._clearFilter}
|
||||||
|
></ha-icon-button>`
|
||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${this._shouldRender
|
${this._shouldRender
|
||||||
@ -118,6 +123,15 @@ export class HaFilterStates extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _clearFilter(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.value = undefined;
|
||||||
|
fireEvent(this, "data-table-filter-changed", {
|
||||||
|
value: undefined,
|
||||||
|
items: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyleScrollbar,
|
haStyleScrollbar,
|
||||||
@ -137,6 +151,10 @@ export class HaFilterStates extends LitElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.header ha-icon-button {
|
||||||
|
margin-inline-start: auto;
|
||||||
|
margin-inline-end: 8px;
|
||||||
|
}
|
||||||
.badge {
|
.badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
import { mdiMagnify } from "@mdi/js";
|
import { mdiClose, mdiMagnify } from "@mdi/js";
|
||||||
import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit";
|
import {
|
||||||
|
CSSResultGroup,
|
||||||
|
LitElement,
|
||||||
|
TemplateResult,
|
||||||
|
css,
|
||||||
|
html,
|
||||||
|
nothing,
|
||||||
|
} from "lit";
|
||||||
import { customElement, property, query } from "lit/decorators";
|
import { customElement, property, query } from "lit/decorators";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
@ -54,6 +61,15 @@ class SearchInputOutlined extends LitElement {
|
|||||||
.path=${mdiMagnify}
|
.path=${mdiMagnify}
|
||||||
></ha-svg-icon>
|
></ha-svg-icon>
|
||||||
</slot>
|
</slot>
|
||||||
|
${this.filter
|
||||||
|
? html`<ha-icon-button
|
||||||
|
aria-label="Clear input"
|
||||||
|
slot="trailing-icon"
|
||||||
|
@click=${this._clearSearch}
|
||||||
|
.path=${mdiClose}
|
||||||
|
>
|
||||||
|
</ha-icon-button>`
|
||||||
|
: nothing}
|
||||||
</ha-outlined-text-field>
|
</ha-outlined-text-field>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -66,12 +82,17 @@ class SearchInputOutlined extends LitElement {
|
|||||||
this._filterChanged(e.target.value);
|
this._filterChanged(e.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _clearSearch() {
|
||||||
|
this._filterChanged("");
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return css`
|
return css`
|
||||||
:host {
|
:host {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
/* For iOS */
|
/* For iOS */
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
--mdc-icon-button-size: 24px;
|
||||||
}
|
}
|
||||||
ha-outlined-text-field {
|
ha-outlined-text-field {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -368,14 +368,16 @@ export class HaTabsSubpageDataTable extends LitElement {
|
|||||||
"ui.components.subpage-data-table.filters"
|
"ui.components.subpage-data-table.filters"
|
||||||
)}</span
|
)}</span
|
||||||
>
|
>
|
||||||
<ha-icon-button
|
${this.filters
|
||||||
slot="actionItems"
|
? html`<ha-icon-button
|
||||||
@click=${this._clearFilters}
|
slot="actionItems"
|
||||||
.path=${mdiFilterVariantRemove}
|
@click=${this._clearFilters}
|
||||||
.label=${localize(
|
.path=${mdiFilterVariantRemove}
|
||||||
"ui.components.subpage-data-table.clear_filter"
|
.label=${localize(
|
||||||
)}
|
"ui.components.subpage-data-table.clear_filter"
|
||||||
></ha-icon-button>
|
)}
|
||||||
|
></ha-icon-button>`
|
||||||
|
: nothing}
|
||||||
</ha-dialog-header>
|
</ha-dialog-header>
|
||||||
<div class="filter-dialog-content">
|
<div class="filter-dialog-content">
|
||||||
<slot name="filter-pane"></slot></div
|
<slot name="filter-pane"></slot></div
|
||||||
@ -394,13 +396,15 @@ export class HaTabsSubpageDataTable extends LitElement {
|
|||||||
.path=${mdiFilterVariant}
|
.path=${mdiFilterVariant}
|
||||||
></ha-svg-icon>
|
></ha-svg-icon>
|
||||||
</ha-assist-chip>
|
</ha-assist-chip>
|
||||||
<ha-icon-button
|
${this.filters
|
||||||
.path=${mdiFilterVariantRemove}
|
? html`<ha-icon-button
|
||||||
@click=${this._clearFilters}
|
.path=${mdiFilterVariantRemove}
|
||||||
.label=${localize(
|
@click=${this._clearFilters}
|
||||||
"ui.components.subpage-data-table.clear_filter"
|
.label=${localize(
|
||||||
)}
|
"ui.components.subpage-data-table.clear_filter"
|
||||||
></ha-icon-button>
|
)}
|
||||||
|
></ha-icon-button>`
|
||||||
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
<div class="pane-content">
|
<div class="pane-content">
|
||||||
<slot name="filter-pane"></slot>
|
<slot name="filter-pane"></slot>
|
||||||
|
@ -271,7 +271,14 @@ export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) {
|
|||||||
? html`<ha-icon .icon=${area.icon}></ha-icon>`
|
? html`<ha-icon .icon=${area.icon}></ha-icon>`
|
||||||
: ""}
|
: ""}
|
||||||
</div>
|
</div>
|
||||||
<h1 class="card-header">${area.name}</h1>
|
<div class="card-header">
|
||||||
|
${area.name}
|
||||||
|
<ha-icon-button
|
||||||
|
.area=${area}
|
||||||
|
.path=${mdiPencil}
|
||||||
|
@click=${this._openAreaDetails}
|
||||||
|
></ha-icon-button>
|
||||||
|
</div>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div>
|
<div>
|
||||||
${formatListWithAnds(
|
${formatListWithAnds(
|
||||||
@ -305,6 +312,16 @@ export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) {
|
|||||||
loadAreaRegistryDetailDialog();
|
loadAreaRegistryDetailDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _openAreaDetails(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
const area = ev.currentTarget.area;
|
||||||
|
showAreaRegistryDetailDialog(this, {
|
||||||
|
entry: area,
|
||||||
|
updateEntry: async (values) =>
|
||||||
|
updateAreaRegistryEntry(this.hass!, area.area_id, values),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async _areaMoved(ev) {
|
private async _areaMoved(ev) {
|
||||||
const areasAndFloors = this._processAreas(
|
const areasAndFloors = this._processAreas(
|
||||||
this.hass.areas,
|
this.hass.areas,
|
||||||
@ -469,8 +486,10 @@ export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) {
|
|||||||
min-height: 16px;
|
min-height: 16px;
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
}
|
}
|
||||||
.floor {
|
.card-header {
|
||||||
--primary-color: var(--secondary-text-color);
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
.warning {
|
.warning {
|
||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
|
@ -35,6 +35,7 @@ import { ButtonsHeaderFooterConfig } from "../header-footer/types";
|
|||||||
const HIDE_DOMAIN = new Set([
|
const HIDE_DOMAIN = new Set([
|
||||||
"automation",
|
"automation",
|
||||||
"configurator",
|
"configurator",
|
||||||
|
"conversation",
|
||||||
"device_tracker",
|
"device_tracker",
|
||||||
"geo_location",
|
"geo_location",
|
||||||
"persistent_notification",
|
"persistent_notification",
|
||||||
|
@ -58,18 +58,12 @@ export interface AndCondition extends BaseCondition {
|
|||||||
|
|
||||||
function getValueFromEntityId(
|
function getValueFromEntityId(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
value: string | string[]
|
value: string
|
||||||
): string | string[] {
|
): string | undefined {
|
||||||
if (
|
if (isValidEntityId(value) && hass.states[value]) {
|
||||||
typeof value === "string" &&
|
return hass.states[value]?.state;
|
||||||
isValidEntityId(value) &&
|
|
||||||
hass.states[value]
|
|
||||||
) {
|
|
||||||
value = hass.states[value]?.state;
|
|
||||||
} else if (Array.isArray(value)) {
|
|
||||||
value = value.map((v) => getValueFromEntityId(hass, v) as string);
|
|
||||||
}
|
}
|
||||||
return value;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkStateCondition(
|
function checkStateCondition(
|
||||||
@ -83,8 +77,17 @@ function checkStateCondition(
|
|||||||
let value = condition.state ?? condition.state_not;
|
let value = condition.state ?? condition.state_not;
|
||||||
|
|
||||||
// Handle entity_id, UI should be updated for conditionnal card (filters does not have UI for now)
|
// Handle entity_id, UI should be updated for conditionnal card (filters does not have UI for now)
|
||||||
if (Array.isArray(value) || typeof value === "string") {
|
if (Array.isArray(value)) {
|
||||||
value = getValueFromEntityId(hass, value);
|
const entityValues = value
|
||||||
|
.map((v) => getValueFromEntityId(hass, v))
|
||||||
|
.filter((v): v is string => v !== undefined);
|
||||||
|
value = [...value, ...entityValues];
|
||||||
|
} else if (typeof value === "string") {
|
||||||
|
const entityValue = getValueFromEntityId(hass, value);
|
||||||
|
value = [value];
|
||||||
|
if (entityValue) {
|
||||||
|
value.push(entityValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return condition.state != null
|
return condition.state != null
|
||||||
@ -103,10 +106,10 @@ function checkStateNumericCondition(
|
|||||||
|
|
||||||
// Handle entity_id, UI should be updated for conditionnal card (filters does not have UI for now)
|
// Handle entity_id, UI should be updated for conditionnal card (filters does not have UI for now)
|
||||||
if (typeof above === "string") {
|
if (typeof above === "string") {
|
||||||
above = getValueFromEntityId(hass, above) as string;
|
above = getValueFromEntityId(hass, above) ?? above;
|
||||||
}
|
}
|
||||||
if (typeof below === "string") {
|
if (typeof below === "string") {
|
||||||
below = getValueFromEntityId(hass, below) as string;
|
below = getValueFromEntityId(hass, below) ?? below;
|
||||||
}
|
}
|
||||||
|
|
||||||
const numericState = Number(state);
|
const numericState = Number(state);
|
||||||
|
@ -172,12 +172,14 @@ class DialogDashboardStrategyEditor extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _takeControl() {
|
private _takeControl(ev) {
|
||||||
|
ev.stopPropagation();
|
||||||
this._params!.takeControl();
|
this._params!.takeControl();
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _showRawConfigEditor() {
|
private _showRawConfigEditor(ev) {
|
||||||
|
ev.stopPropagation();
|
||||||
this._params!.showRawConfigEditor();
|
this._params!.showRawConfigEditor();
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,9 @@ export const getMyRedirects = (hasSupervisor: boolean): Redirects => ({
|
|||||||
entities: {
|
entities: {
|
||||||
redirect: "/config/entities",
|
redirect: "/config/entities",
|
||||||
},
|
},
|
||||||
|
labels: {
|
||||||
|
redirect: "/config/labels",
|
||||||
|
},
|
||||||
energy: {
|
energy: {
|
||||||
component: "energy",
|
component: "energy",
|
||||||
redirect: "/energy",
|
redirect: "/energy",
|
||||||
|
@ -1962,6 +1962,7 @@
|
|||||||
"color": "Color"
|
"color": "Color"
|
||||||
},
|
},
|
||||||
"add_label": "Add label",
|
"add_label": "Add label",
|
||||||
|
"manage_labels": "Manage labels",
|
||||||
"no_labels": "You don't have any labels",
|
"no_labels": "You don't have any labels",
|
||||||
"introduction": "Labels can help you organize your areas, devices and entities. They can be used to filter in the UI, or use them as a target in automations.",
|
"introduction": "Labels can help you organize your areas, devices and entities. They can be used to filter in the UI, or use them as a target in automations.",
|
||||||
"introduction2": "Go to the area, device or entity you want to add a label to, and click on the edit button to assign labels to them.",
|
"introduction2": "Go to the area, device or entity you want to add a label to, and click on the edit button to assign labels to them.",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user