add conditional row (#4569)

*  add conditional row

* fix types

* address comments
This commit is contained in:
Ian Richardson 2020-01-24 02:59:36 -06:00 committed by Bram Kragten
parent 23865c31e6
commit 74c6b9077a
29 changed files with 167 additions and 107 deletions

View File

@ -10,7 +10,7 @@ import {
import "../../../src/components/ha-icon";
import {
EntityRow,
LovelaceRow,
CastConfig,
} from "../../../src/panels/lovelace/entity-rows/types";
import { HomeAssistant } from "../../../src/types";
@ -18,7 +18,7 @@ import { CastManager } from "../../../src/cast/cast_manager";
import { castSendShowDemo } from "../../../src/cast/receiver_messages";
@customElement("cast-demo-row")
class CastDemoRow extends LitElement implements EntityRow {
class CastDemoRow extends LitElement implements LovelaceRow {
public hass!: HomeAssistant;
@property() private _castManager?: CastManager | null;

View File

@ -1,66 +1,25 @@
import { customElement } from "lit-element";
import { HuiConditionalBase } from "../components/hui-conditional-base";
import { createCardElement } from "../create-element/create-card-element";
import { computeCardSize } from "../common/compute-card-size";
import {
checkConditionsMet,
validateConditionalConfig,
} from "../../lovelace/common/validate-condition";
import { HomeAssistant } from "../../../types";
import { LovelaceCard } from "../types";
import { computeCardSize } from "../common/compute-card-size";
import { ConditionalCardConfig } from "./types";
class HuiConditionalCard extends HTMLElement implements LovelaceCard {
private _hass?: HomeAssistant;
private _config?: ConditionalCardConfig;
private _card?: LovelaceCard;
@customElement("hui-conditional-card")
class HuiConditionalCard extends HuiConditionalBase implements LovelaceCard {
public setConfig(config: ConditionalCardConfig): void {
this.validateConfig(config);
public setConfig(config) {
if (
!config.card ||
!config.conditions ||
!Array.isArray(config.conditions) ||
!validateConditionalConfig(config.conditions)
) {
throw new Error("Error in card configuration.");
if (!config.card) {
throw new Error("No card configured.");
}
if (this._card && this._card.parentElement) {
this.removeChild(this._card);
}
this._config = config;
this._card = createCardElement(config.card);
this.update();
this._element = createCardElement(config.card) as LovelaceCard;
}
set hass(hass: HomeAssistant) {
this._hass = hass;
this.update();
}
public getCardSize() {
return computeCardSize(this._card!);
}
private update() {
if (!this._card || !this._hass) {
return;
}
const visible =
this._config && checkConditionsMet(this._config.conditions, this._hass);
if (visible) {
this._card.hass = this._hass;
if (!this._card.parentElement) {
this.appendChild(this._card);
}
} else if (this._card.parentElement) {
this.removeChild(this._card);
}
// This will hide the complete card so it won't get styled by parent
this.style.setProperty("display", visible ? "" : "none");
public getCardSize(): number {
return computeCardSize(this._element as LovelaceCard);
}
}
@ -69,5 +28,3 @@ declare global {
"hui-conditional-card": HuiConditionalCard;
}
}
customElements.define("hui-conditional-card", HuiConditionalCard);

View File

@ -13,7 +13,7 @@ import "../../../components/ha-card";
import "../components/hui-entities-toggle";
import { HomeAssistant } from "../../../types";
import { EntityRow } from "../entity-rows/types";
import { LovelaceRow } from "../entity-rows/types";
import { LovelaceCard, LovelaceCardEditor } from "../types";
import { processConfigEntities } from "../common/process-config-entities";
import { createRowElement } from "../create-element/create-row-element";
@ -45,7 +45,7 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
this._hass = hass;
this.shadowRoot!.querySelectorAll("#states > div > *").forEach(
(element: unknown) => {
(element as EntityRow).hass = hass;
(element as LovelaceRow).hass = hass;
}
);
const entitiesToggle = this.shadowRoot!.querySelector(

View File

@ -18,7 +18,7 @@ import { computeObjectId } from "../../../common/entity/compute_object_id";
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import { computeDomain } from "../../../common/entity/compute_domain";
import { EntityRowConfig, WeblinkConfig } from "../entity-rows/types";
import { LovelaceRowConfig, WeblinkConfig } from "../entity-rows/types";
import { LocalizeFunc } from "../../../common/translations/localize";
import { EntitiesCardConfig } from "../cards/types";
import {
@ -105,7 +105,7 @@ export const computeCards = (
const cards: LovelaceCardConfig[] = [];
// For entity card
const entities: Array<string | EntityRowConfig> = [];
const entities: Array<string | LovelaceRowConfig> = [];
for (const [entityId, stateObj] of states) {
const domain = computeDomain(entityId);

View File

@ -0,0 +1,63 @@
import { customElement, property, UpdatingElement } from "lit-element";
import {
checkConditionsMet,
validateConditionalConfig,
} from "../common/validate-condition";
import { HomeAssistant } from "../../../types";
import { LovelaceCard } from "../types";
import { LovelaceRow, ConditionalRowConfig } from "../entity-rows/types";
import { ConditionalCardConfig } from "../cards/types";
@customElement("hui-conditional-base")
export class HuiConditionalBase extends UpdatingElement {
@property() public hass?: HomeAssistant;
@property() protected _config?: ConditionalCardConfig | ConditionalRowConfig;
protected _element?: LovelaceCard | LovelaceRow;
protected validateConfig(
config: ConditionalCardConfig | ConditionalRowConfig
): void {
if (!config.conditions) {
throw new Error("No conditions configured.");
}
if (!Array.isArray(config.conditions)) {
throw new Error("Conditions should be in an array.");
}
if (!validateConditionalConfig(config.conditions)) {
throw new Error("Conditions are invalid.");
}
if (this._element && this._element.parentElement) {
this.removeChild(this._element);
}
this._config = config;
}
protected update(): void {
if (!this._element || !this.hass) {
return;
}
const visible =
this._config && checkConditionsMet(this._config.conditions, this.hass);
if (visible) {
this._element.hass = this.hass;
if (!this._element.parentElement) {
this.appendChild(this._element);
}
}
this.style.setProperty("display", visible ? "" : "none");
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-conditional-base": HuiConditionalBase;
}
}

View File

@ -0,0 +1,8 @@
import { LovelaceCardConfig } from "../../../data/lovelace";
import { Condition } from "../common/validate-condition";
import { LovelaceElementConfig } from "../elements/types";
export interface ConditionalBaseConfig extends LovelaceCardConfig {
card: LovelaceCardConfig | LovelaceElementConfig;
conditions: Condition[];
}

View File

@ -10,7 +10,7 @@ import {
import { LovelaceCard, LovelaceBadge, LovelaceHeaderFooter } from "../types";
import { fireEvent } from "../../../common/dom/fire_event";
import { LovelaceElementConfig, LovelaceElement } from "../elements/types";
import { EntityRow, EntityRowConfig } from "../entity-rows/types";
import { LovelaceRow, LovelaceRowConfig } from "../entity-rows/types";
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
const CUSTOM_TYPE_PREFIX = "custom:";
@ -20,7 +20,7 @@ interface CreateElementConfigTypes {
card: { config: LovelaceCardConfig; element: LovelaceCard };
badge: { config: LovelaceBadgeConfig; element: LovelaceBadge };
element: { config: LovelaceElementConfig; element: LovelaceElement };
row: { config: EntityRowConfig; element: EntityRow };
row: { config: LovelaceRowConfig; element: LovelaceRow };
"header-footer": {
config: LovelaceHeaderFooterConfig;
element: LovelaceHeaderFooter;

View File

@ -14,6 +14,7 @@ import "../entity-rows/hui-text-entity-row";
import "../entity-rows/hui-timer-entity-row";
import "../entity-rows/hui-toggle-entity-row";
import "../special-rows/hui-call-service-row";
import "../special-rows/hui-conditional-row";
import "../special-rows/hui-divider-row";
import "../special-rows/hui-section-row";
import "../special-rows/hui-weblink-row";
@ -23,11 +24,12 @@ import { createLovelaceElement } from "./create-element-base";
const SPECIAL_TYPES = new Set([
"call-service",
"cast",
"conditional",
"divider",
"section",
"weblink",
"cast",
"select",
"weblink",
]);
const DOMAIN_TO_ELEMENT_TYPE = {
_domain_not_found: "text",

View File

@ -14,11 +14,11 @@ import "../components/hui-generic-entity-row";
import "../components/hui-warning";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-climate-entity-row")
class HuiClimateEntityRow extends LitElement implements EntityRow {
class HuiClimateEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -16,11 +16,11 @@ import "../components/hui-warning";
import { isTiltOnly } from "../../../util/cover-model";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-cover-entity-row")
class HuiCoverEntityRow extends LitElement implements EntityRow {
class HuiCoverEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -14,11 +14,11 @@ import "../components/hui-warning";
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { DOMAINS_TOGGLE } from "../../../common/const";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-group-entity-row")
class HuiGroupEntityRow extends LitElement implements EntityRow {
class HuiGroupEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -16,12 +16,12 @@ import "../../../components/ha-date-input";
import { HaDateInput } from "../../../components/ha-date-input";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { setInputDateTimeValue } from "../../../data/input_datetime";
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-input-datetime-entity-row")
class HuiInputDatetimeEntityRow extends LitElement implements EntityRow {
class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -14,13 +14,13 @@ import "../../../components/ha-slider";
import "../components/hui-warning";
import { computeRTLDirection } from "../../../common/util/compute_rtl";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { HomeAssistant } from "../../../types";
import { setValue } from "../../../data/input_text";
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-input-number-entity-row")
class HuiInputNumberEntityRow extends LitElement implements EntityRow {
class HuiInputNumberEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -19,7 +19,7 @@ import "../components/hui-warning";
import { computeStateName } from "../../../common/entity/compute_state_name";
import { HomeAssistant, InputSelectEntity } from "../../../types";
import { EntityRow } from "./types";
import { LovelaceRow } from "./types";
import { setInputSelectOption } from "../../../data/input-select";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { forwardHaptic } from "../../../data/haptics";
@ -34,7 +34,7 @@ import { ActionHandlerEvent } from "../../../data/lovelace";
import { handleAction } from "../common/handle-action";
@customElement("hui-input-select-entity-row")
class HuiInputSelectEntityRow extends LitElement implements EntityRow {
class HuiInputSelectEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntitiesCardEntityConfig;

View File

@ -12,12 +12,12 @@ import "../components/hui-generic-entity-row";
import "../components/hui-warning";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { setValue } from "../../../data/input_text";
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-input-text-entity-row")
class HuiInputTextEntityRow extends LitElement implements EntityRow {
class HuiInputTextEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -13,11 +13,11 @@ import "../components/hui-generic-entity-row";
import "../components/hui-warning";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-lock-entity-row")
class HuiLockEntityRow extends LitElement implements EntityRow {
class HuiLockEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -13,7 +13,7 @@ import "@polymer/paper-icon-button/paper-icon-button";
import "../components/hui-generic-entity-row";
import "../components/hui-warning";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { HomeAssistant } from "../../../types";
import { HassEntity } from "home-assistant-js-websocket";
import { supportsFeature } from "../../../common/entity/supports-feature";
@ -26,7 +26,7 @@ import {
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-media-player-entity-row")
class HuiMediaPlayerEntityRow extends LitElement implements EntityRow {
class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -14,12 +14,12 @@ import "../../../components/entity/ha-entity-toggle";
import "../components/hui-warning";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { activateScene } from "../../../data/scene";
@customElement("hui-scene-entity-row")
class HuiSceneEntityRow extends LitElement implements EntityRow {
class HuiSceneEntityRow extends LitElement implements LovelaceRow {
@property() public hass!: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -14,11 +14,11 @@ import "../../../components/entity/ha-entity-toggle";
import "../components/hui-warning";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-script-entity-row")
class HuiScriptEntityRow extends LitElement implements EntityRow {
class HuiScriptEntityRow extends LitElement implements LovelaceRow {
public hass?: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -14,7 +14,7 @@ import "../components/hui-timestamp-display";
import "../components/hui-warning";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
@ -23,7 +23,7 @@ interface SensorEntityConfig extends EntityConfig {
}
@customElement("hui-sensor-entity-row")
class HuiSensorEntityRow extends LitElement implements EntityRow {
class HuiSensorEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: SensorEntityConfig;

View File

@ -14,11 +14,11 @@ import "../components/hui-warning";
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-text-entity-row")
class HuiTextEntityRow extends LitElement implements EntityRow {
class HuiTextEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -13,11 +13,11 @@ import "../components/hui-warning";
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { LovelaceRow, EntityConfig } from "./types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-toggle-entity-row")
class HuiToggleEntityRow extends LitElement implements EntityRow {
class HuiToggleEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;

View File

@ -1,4 +1,5 @@
import { HomeAssistant } from "../../../types";
import { Condition } from "../common/validate-condition";
export interface EntityConfig {
entity: string;
@ -38,7 +39,7 @@ export interface CastConfig {
// Hide the row if either unsupported browser or no API available.
hide_if_unavailable: boolean;
}
export type EntityRowConfig =
export type LovelaceRowConfig =
| EntityConfig
| DividerConfig
| SectionConfig
@ -46,7 +47,12 @@ export type EntityRowConfig =
| CallServiceConfig
| CastConfig;
export interface EntityRow extends HTMLElement {
export interface LovelaceRow extends HTMLElement {
hass?: HomeAssistant;
setConfig(config: EntityRowConfig);
setConfig(config: LovelaceRowConfig);
}
export interface ConditionalRowConfig extends EntityConfig {
row: EntityConfig;
conditions: Condition[];
}

View File

@ -12,11 +12,11 @@ import "@material/mwc-button";
import "../../../components/ha-icon";
import { callService } from "../common/call-service";
import { EntityRow, CallServiceConfig } from "../entity-rows/types";
import { LovelaceRow, CallServiceConfig } from "../entity-rows/types";
import { HomeAssistant } from "../../../types";
@customElement("hui-call-service-row")
class HuiCallServiceRow extends LitElement implements EntityRow {
class HuiCallServiceRow extends LitElement implements LovelaceRow {
public hass?: HomeAssistant;
@property() private _config?: CallServiceConfig;

View File

@ -9,7 +9,7 @@ import {
} from "lit-element";
import { classMap } from "lit-html/directives/class-map";
import { EntityRow, CastConfig } from "../entity-rows/types";
import { LovelaceRow, CastConfig } from "../entity-rows/types";
import { HomeAssistant } from "../../../types";
import "../../../components/ha-icon";
@ -20,7 +20,7 @@ import {
} from "../../../cast/receiver_messages";
@customElement("hui-cast-row")
class HuiCastRow extends LitElement implements EntityRow {
class HuiCastRow extends LitElement implements LovelaceRow {
public hass!: HomeAssistant;
@property() private _config?: CastConfig;

View File

@ -0,0 +1,24 @@
import { customElement } from "lit-element";
import { HuiConditionalBase } from "../components/hui-conditional-base";
import { createRowElement } from "../create-element/create-row-element";
import { LovelaceRow, ConditionalRowConfig } from "../entity-rows/types";
@customElement("hui-conditional-row")
class HuiConditionalRow extends HuiConditionalBase implements LovelaceRow {
public setConfig(config: ConditionalRowConfig): void {
this.validateConfig(config);
if (!config.row) {
throw new Error("No row configured.");
}
this._element = createRowElement(config.row) as LovelaceRow;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-conditional-row": HuiConditionalRow;
}
}

View File

@ -6,11 +6,11 @@ import {
property,
} from "lit-element";
import { EntityRow, DividerConfig } from "../entity-rows/types";
import { LovelaceRow, DividerConfig } from "../entity-rows/types";
import { HomeAssistant } from "../../../types";
@customElement("hui-divider-row")
class HuiDividerRow extends LitElement implements EntityRow {
class HuiDividerRow extends LitElement implements LovelaceRow {
public hass?: HomeAssistant;
@property() private _config?: DividerConfig;

View File

@ -8,13 +8,13 @@ import {
CSSResult,
} from "lit-element";
import { EntityRow, SectionConfig } from "../entity-rows/types";
import { LovelaceRow, SectionConfig } from "../entity-rows/types";
import { HomeAssistant } from "../../../types";
import "../../../components/ha-icon";
@customElement("hui-section-row")
class HuiSectionRow extends LitElement implements EntityRow {
class HuiSectionRow extends LitElement implements LovelaceRow {
public hass?: HomeAssistant;
@property() private _config?: SectionConfig;

View File

@ -8,13 +8,13 @@ import {
CSSResult,
} from "lit-element";
import { EntityRow, WeblinkConfig } from "../entity-rows/types";
import { LovelaceRow, WeblinkConfig } from "../entity-rows/types";
import { HomeAssistant } from "../../../types";
import "../../../components/ha-icon";
@customElement("hui-weblink-row")
class HuiWeblinkRow extends LitElement implements EntityRow {
class HuiWeblinkRow extends LitElement implements LovelaceRow {
public hass?: HomeAssistant;
@property() private _config?: WeblinkConfig;