mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-18 23:06:40 +00:00
Conditional element support for use in picture-elements (#2865)
* Conditional element support for use in picture-elements * Refactored * Refactor to HTMLElement, separated files * New file * Added disconnected callback, handled multiple config calls. * Added update method * Refactored and simplified - elements contained internally * Removed excess if * Refactored also picture elements
This commit is contained in:
parent
241d7345d0
commit
19c44f7c7b
@ -1,15 +1,14 @@
|
||||
import { createCardElement } from "../common/create-card-element";
|
||||
import { computeCardSize } from "../common/compute-card-size";
|
||||
import {
|
||||
Condition,
|
||||
checkConditionsMet,
|
||||
validateConditionalConfig,
|
||||
} from "../../lovelace/common/validate-condition";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { LovelaceCard } from "../types";
|
||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
||||
|
||||
interface Condition {
|
||||
entity: string;
|
||||
state?: string;
|
||||
state_not?: string;
|
||||
}
|
||||
|
||||
interface Config extends LovelaceCardConfig {
|
||||
card: LovelaceCardConfig;
|
||||
conditions: Condition[];
|
||||
@ -25,7 +24,7 @@ class HuiConditionalCard extends HTMLElement implements LovelaceCard {
|
||||
!config.card ||
|
||||
!config.conditions ||
|
||||
!Array.isArray(config.conditions) ||
|
||||
!config.conditions.every((c) => c.entity && (c.state || c.state_not))
|
||||
!validateConditionalConfig(config.conditions)
|
||||
) {
|
||||
throw new Error("Error in card configuration.");
|
||||
}
|
||||
@ -36,32 +35,30 @@ class HuiConditionalCard extends HTMLElement implements LovelaceCard {
|
||||
|
||||
this._config = config;
|
||||
this._card = createCardElement(config.card);
|
||||
if (this._hass) {
|
||||
this.hass = this._hass;
|
||||
}
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
set hass(hass: HomeAssistant) {
|
||||
this._hass = hass;
|
||||
|
||||
if (!this._card) {
|
||||
this.update();
|
||||
}
|
||||
|
||||
public getCardSize() {
|
||||
return computeCardSize(this._card!);
|
||||
}
|
||||
|
||||
private update() {
|
||||
if (!this._card || !this._hass) {
|
||||
return;
|
||||
}
|
||||
|
||||
const visible =
|
||||
this._config &&
|
||||
this._config.conditions.every((c) => {
|
||||
if (!(c.entity in hass.states)) {
|
||||
return false;
|
||||
}
|
||||
if (c.state) {
|
||||
return hass.states[c.entity].state === c.state;
|
||||
}
|
||||
return hass.states[c.entity].state !== c.state_not;
|
||||
});
|
||||
this._config && checkConditionsMet(this._config.conditions, this._hass);
|
||||
|
||||
if (visible) {
|
||||
this._card.hass = hass;
|
||||
this._card.hass = this._hass;
|
||||
if (!this._card.parentElement) {
|
||||
this.appendChild(this._card);
|
||||
}
|
||||
@ -71,10 +68,6 @@ class HuiConditionalCard extends HTMLElement implements LovelaceCard {
|
||||
// This will hide the complete card so it won't get styled by parent
|
||||
this.style.setProperty("display", visible ? "" : "none");
|
||||
}
|
||||
|
||||
public getCardSize() {
|
||||
return computeCardSize(this._card!);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { html, LitElement, TemplateResult } from "lit-element";
|
||||
|
||||
import { createHuiElement } from "../common/create-hui-element";
|
||||
import { createStyledHuiElement } from "./picture-elements/create-styled-hui-element";
|
||||
|
||||
import { LovelaceCard } from "../types";
|
||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
||||
@ -71,8 +71,13 @@ class HuiPictureElementsCard extends LitElement implements LovelaceCard {
|
||||
.entity="${this._config.entity}"
|
||||
.aspectRatio="${this._config.aspect_ratio}"
|
||||
></hui-image>
|
||||
${this._config.elements.map((elementConfig: LovelaceElementConfig) =>
|
||||
this._createHuiElement(elementConfig)
|
||||
${this._config.elements.map(
|
||||
(elementConfig: LovelaceElementConfig) => {
|
||||
const element = createStyledHuiElement(elementConfig);
|
||||
element.hass = this._hass;
|
||||
|
||||
return element;
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</ha-card>
|
||||
@ -95,20 +100,6 @@ class HuiPictureElementsCard extends LitElement implements LovelaceCard {
|
||||
</style>
|
||||
`;
|
||||
}
|
||||
|
||||
private _createHuiElement(
|
||||
elementConfig: LovelaceElementConfig
|
||||
): LovelaceElement {
|
||||
const element = createHuiElement(elementConfig) as LovelaceElement;
|
||||
element.hass = this._hass;
|
||||
element.classList.add("element");
|
||||
|
||||
Object.keys(elementConfig.style).forEach((prop) => {
|
||||
element.style.setProperty(prop, elementConfig.style[prop]);
|
||||
});
|
||||
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@ -0,0 +1,20 @@
|
||||
import { LovelaceElement, LovelaceElementConfig } from "../../elements/types";
|
||||
import { createHuiElement } from "../../common/create-hui-element";
|
||||
|
||||
export function createStyledHuiElement(
|
||||
elementConfig: LovelaceElementConfig
|
||||
): LovelaceElement {
|
||||
const element = createHuiElement(elementConfig) as LovelaceElement;
|
||||
// keep conditional card as a transparent container so let its position remain static
|
||||
if (element.tagName !== "HUI-CONDITIONAL-ELEMENT") {
|
||||
element.classList.add("element");
|
||||
}
|
||||
|
||||
if (elementConfig.style) {
|
||||
Object.keys(elementConfig.style).forEach((prop) => {
|
||||
element.style.setProperty(prop, elementConfig.style[prop]);
|
||||
});
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import deepClone from "deep-clone-simple";
|
||||
|
||||
import "../elements/hui-conditional-element";
|
||||
import "../elements/hui-icon-element";
|
||||
import "../elements/hui-image-element";
|
||||
import "../elements/hui-service-button-element";
|
||||
@ -17,6 +18,7 @@ import { LovelaceElementConfig, LovelaceElement } from "../elements/types";
|
||||
|
||||
const CUSTOM_TYPE_PREFIX = "custom:";
|
||||
const ELEMENT_TYPES = new Set([
|
||||
"conditional",
|
||||
"icon",
|
||||
"image",
|
||||
"service-button",
|
||||
|
28
src/panels/lovelace/common/validate-condition.ts
Normal file
28
src/panels/lovelace/common/validate-condition.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { HomeAssistant } from "../../../types";
|
||||
|
||||
export interface Condition {
|
||||
entity: string;
|
||||
state?: string;
|
||||
state_not?: string;
|
||||
}
|
||||
|
||||
export function checkConditionsMet(
|
||||
conditions: Condition[],
|
||||
hass: HomeAssistant
|
||||
): boolean {
|
||||
return conditions.every((c) => {
|
||||
if (!(c.entity in hass.states)) {
|
||||
return false;
|
||||
}
|
||||
if (c.state) {
|
||||
return hass.states[c.entity].state === c.state;
|
||||
}
|
||||
return hass!.states[c.entity].state !== c.state_not;
|
||||
});
|
||||
}
|
||||
|
||||
export function validateConditionalConfig(conditions: Condition[]): boolean {
|
||||
return conditions.every(
|
||||
(c) => ((c.entity && (c.state || c.state_not)) as unknown) as boolean
|
||||
);
|
||||
}
|
83
src/panels/lovelace/elements/hui-conditional-element.ts
Normal file
83
src/panels/lovelace/elements/hui-conditional-element.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import {
|
||||
Condition,
|
||||
checkConditionsMet,
|
||||
validateConditionalConfig,
|
||||
} from "../../lovelace/common/validate-condition";
|
||||
import { createStyledHuiElement } from "../cards/picture-elements/create-styled-hui-element";
|
||||
|
||||
import { LovelaceElement, LovelaceElementConfig } from "./types";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
|
||||
interface Config extends LovelaceElementConfig {
|
||||
conditions: Condition[];
|
||||
elements: LovelaceElementConfig[];
|
||||
}
|
||||
|
||||
class HuiConditionalElement extends HTMLElement implements LovelaceElement {
|
||||
public _hass?: HomeAssistant;
|
||||
private _config?: Config;
|
||||
private _elements: LovelaceElement[] = [];
|
||||
|
||||
public setConfig(config: Config): void {
|
||||
if (
|
||||
!config.conditions ||
|
||||
!Array.isArray(config.conditions) ||
|
||||
!config.elements ||
|
||||
!Array.isArray(config.elements) ||
|
||||
!validateConditionalConfig(config.conditions)
|
||||
) {
|
||||
throw new Error("Error in card configuration.");
|
||||
}
|
||||
|
||||
if (this._elements.length > 0) {
|
||||
this._elements.map((el: LovelaceElement) => {
|
||||
if (el.parentElement) {
|
||||
el.parentElement.removeChild(el);
|
||||
}
|
||||
});
|
||||
|
||||
this._elements = [];
|
||||
}
|
||||
|
||||
this._config = config;
|
||||
|
||||
this._config.elements.map((elementConfig: LovelaceElementConfig) => {
|
||||
this._elements.push(createStyledHuiElement(elementConfig));
|
||||
});
|
||||
|
||||
this.updateElements();
|
||||
}
|
||||
|
||||
set hass(hass: HomeAssistant) {
|
||||
this._hass = hass;
|
||||
|
||||
this.updateElements();
|
||||
}
|
||||
|
||||
private updateElements() {
|
||||
if (!this._hass || !this._config) {
|
||||
return;
|
||||
}
|
||||
|
||||
const visible = checkConditionsMet(this._config.conditions, this._hass);
|
||||
|
||||
this._elements.map((el: LovelaceElement) => {
|
||||
if (visible) {
|
||||
el.hass = this._hass;
|
||||
if (!el.parentElement) {
|
||||
this.appendChild(el);
|
||||
}
|
||||
} else if (el.parentElement) {
|
||||
el.parentElement.removeChild(el);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-conditional-element": HuiConditionalElement;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("hui-conditional-element", HuiConditionalElement);
|
Loading…
x
Reference in New Issue
Block a user