Move condition handlers to their own files

This commit is contained in:
Paul Bottein 2024-03-19 17:58:31 +01:00
parent 52fdbfe44c
commit c632204939
No known key found for this signature in database
18 changed files with 354 additions and 249 deletions

View File

@ -5,8 +5,9 @@ import { Statistic, StatisticType } from "../../../data/recorder";
import { ForecastType } from "../../../data/weather"; import { ForecastType } from "../../../data/weather";
import { FullCalendarView, TranslationDict } from "../../../types"; import { FullCalendarView, TranslationDict } from "../../../types";
import { LovelaceCardFeatureConfig } from "../card-features/types"; import { LovelaceCardFeatureConfig } from "../card-features/types";
import { LovelaceCondition } from "../common/conditions/types";
import { LegacyStateFilter } from "../common/evaluate-filter"; import { LegacyStateFilter } from "../common/evaluate-filter";
import { Condition, LegacyCondition } from "../common/validate-condition"; import { LegacyCondition } from "../common/validate-condition";
import { HuiImage } from "../components/hui-image"; import { HuiImage } from "../components/hui-image";
import { TimestampRenderingFormat } from "../components/types"; import { TimestampRenderingFormat } from "../components/types";
import { LovelaceElementConfig } from "../elements/types"; import { LovelaceElementConfig } from "../elements/types";
@ -40,7 +41,7 @@ export interface CalendarCardConfig extends LovelaceCardConfig {
export interface ConditionalCardConfig extends LovelaceCardConfig { export interface ConditionalCardConfig extends LovelaceCardConfig {
card: LovelaceCardConfig; card: LovelaceCardConfig;
conditions: (Condition | LegacyCondition)[]; conditions: (LovelaceCondition | LegacyCondition)[];
} }
export interface EmptyStateCardConfig extends LovelaceCardConfig { export interface EmptyStateCardConfig extends LovelaceCardConfig {
@ -203,7 +204,7 @@ export interface EntityFilterCardConfig extends LovelaceCardConfig {
type: "entity-filter"; type: "entity-filter";
entities: Array<EntityFilterEntityConfig | string>; entities: Array<EntityFilterEntityConfig | string>;
state_filter?: Array<LegacyStateFilter>; state_filter?: Array<LegacyStateFilter>;
conditions: Array<Condition>; conditions: Array<LovelaceCondition>;
card?: Partial<LovelaceCardConfig>; card?: Partial<LovelaceCardConfig>;
show_empty?: boolean; show_empty?: boolean;
} }

View File

@ -0,0 +1,21 @@
import { HomeAssistant } from "../../../../types";
import { ConditionHandler, checkCondition } from "./handle-condition";
import { LovelaceBaseCondition, LovelaceCondition } from "./types";
export type LovelaceAndCondition = LovelaceBaseCondition & {
condition: "and";
conditions?: LovelaceCondition[];
};
export class AndConditionHandler
implements ConditionHandler<LovelaceAndCondition>
{
validate(condition: LovelaceAndCondition): boolean {
return condition.conditions != null;
}
check(condition: LovelaceAndCondition, hass: HomeAssistant): boolean {
if (!condition.conditions) return true;
return condition.conditions.every((c) => checkCondition(c, hass));
}
}

View File

@ -0,0 +1,64 @@
import { isValidEntityId } from "../../../../common/entity/valid_entity_id";
import { HomeAssistant } from "../../../../types";
import { ConditionHandler } from "./handle-condition";
import { LovelaceBaseCondition } from "./types";
function getValueFromEntityId(hass: HomeAssistant, value: string): string {
if (isValidEntityId(value) && hass.states[value]) {
return hass.states[value]?.state;
}
return value;
}
export type LovelaceNumericStateCondition = LovelaceBaseCondition & {
condition: "numeric_state";
entity?: string;
below?: string | number;
above?: string | number;
};
export class NumericStateConditionHandler
implements ConditionHandler<LovelaceNumericStateCondition>
{
validate(condition: LovelaceNumericStateCondition): boolean {
return (
condition.entity != null &&
(condition.above != null || condition.below != null)
);
}
check(
condition: LovelaceNumericStateCondition,
hass: HomeAssistant
): boolean {
const state = (condition.entity ? hass.states[condition.entity] : undefined)
?.state;
let above = condition.above;
let below = condition.below;
// Handle entity_id, UI should be updated for conditionnal card (filters does not have UI for now)
if (typeof above === "string") {
above = getValueFromEntityId(hass, above) as string;
}
if (typeof below === "string") {
below = getValueFromEntityId(hass, below) as string;
}
const numericState = Number(state);
const numericAbove = Number(above);
const numericBelow = Number(below);
if (isNaN(numericState)) {
return false;
}
return (
(condition.above == null ||
isNaN(numericAbove) ||
numericAbove < numericState) &&
(condition.below == null ||
isNaN(numericBelow) ||
numericBelow > numericState)
);
}
}

View File

@ -0,0 +1,21 @@
import { HomeAssistant } from "../../../../types";
import { ConditionHandler, checkCondition } from "./handle-condition";
import { LovelaceBaseCondition, LovelaceCondition } from "./types";
export type LovelaceOrCondition = LovelaceBaseCondition & {
condition: "or";
conditions?: LovelaceCondition[];
};
export class OrConditionHandler
implements ConditionHandler<LovelaceOrCondition>
{
validate(condition: LovelaceOrCondition): boolean {
return condition.conditions != null;
}
check(condition: LovelaceOrCondition, hass: HomeAssistant): boolean {
if (!condition.conditions) return true;
return condition.conditions.some((c) => checkCondition(c, hass));
}
}

View File

@ -0,0 +1,22 @@
import { HomeAssistant } from "../../../../types";
import { ConditionHandler } from "./handle-condition";
import { LovelaceBaseCondition } from "./types";
export type LovelaceScreenCondition = LovelaceBaseCondition & {
condition: "screen";
media_query?: string;
};
export class ScreenConditionHandler
implements ConditionHandler<LovelaceScreenCondition>
{
validate(condition: LovelaceScreenCondition): boolean {
return condition.media_query != null;
}
check(condition: LovelaceScreenCondition, _hass: HomeAssistant): boolean {
return condition.media_query
? window.matchMedia(condition.media_query).matches
: false;
}
}

View File

@ -0,0 +1,50 @@
import { ensureArray } from "../../../../common/array/ensure-array";
import { isValidEntityId } from "../../../../common/entity/valid_entity_id";
import { UNAVAILABLE } from "../../../../data/entity";
import { HomeAssistant } from "../../../../types";
import { ConditionHandler } from "./handle-condition";
import { LovelaceBaseCondition } from "./types";
function getValueFromEntityId(hass: HomeAssistant, value: string): string {
if (isValidEntityId(value) && hass.states[value]) {
return hass.states[value]?.state;
}
return value;
}
export type LovelaceStateCondition = LovelaceBaseCondition & {
condition: "state";
entity?: string;
state?: string | string[];
state_not?: string | string[];
};
export class StateConditionHandler
implements ConditionHandler<LovelaceStateCondition>
{
validate(condition: LovelaceStateCondition): boolean {
return (
condition.entity != null &&
(condition.state != null || condition.state_not != null)
);
}
check(condition: LovelaceStateCondition, hass: HomeAssistant): boolean {
const state =
condition.entity && hass.states[condition.entity]
? hass.states[condition.entity].state
: UNAVAILABLE;
let value = condition.state ?? condition.state_not;
if (typeof value === "string") {
value = getValueFromEntityId(hass, value);
}
if (Array.isArray(value)) {
value = value.map((val) => getValueFromEntityId(hass, val));
}
return condition.state != null
? ensureArray(value).includes(state)
: !ensureArray(value).includes(state);
}
}

View File

@ -0,0 +1,22 @@
import { HomeAssistant } from "../../../../types";
import { ConditionHandler } from "./handle-condition";
import { LovelaceBaseCondition } from "./types";
export type LovelaceUserCondition = LovelaceBaseCondition & {
condition: "user";
users?: string[];
};
export class UserConditionHandler
implements ConditionHandler<LovelaceUserCondition>
{
validate(condition: LovelaceUserCondition): boolean {
return condition.users != null;
}
check(condition: LovelaceUserCondition, hass: HomeAssistant): boolean {
return condition.users && hass.user?.id
? condition.users.includes(hass.user.id)
: false;
}
}

View File

@ -0,0 +1,35 @@
import { HomeAssistant } from "../../../../types";
import { AndConditionHandler } from "./condition-and";
import { NumericStateConditionHandler } from "./condition-numeric-state";
import { OrConditionHandler } from "./condition-or";
import { ScreenConditionHandler } from "./condition-screen";
import { StateConditionHandler } from "./condition-state";
import { UserConditionHandler } from "./condition-user";
import { LovelaceBaseCondition, LovelaceCondition } from "./types";
export interface ConditionHandler<
T extends LovelaceBaseCondition = LovelaceBaseCondition,
> {
validate(condition: T): boolean;
check(condition: T, hass: HomeAssistant): boolean;
}
const HANDLER: Record<LovelaceCondition["condition"], ConditionHandler> = {
state: new StateConditionHandler(),
numeric_state: new NumericStateConditionHandler(),
screen: new ScreenConditionHandler(),
and: new AndConditionHandler(),
or: new OrConditionHandler(),
user: new UserConditionHandler(),
};
export function checkCondition(
condition: LovelaceCondition,
hass: HomeAssistant
): boolean {
return HANDLER[condition.condition].check(condition, hass);
}
export function validateCondition(condition: LovelaceCondition): boolean {
return HANDLER[condition.condition].validate(condition);
}

View File

@ -0,0 +1,45 @@
export type LovelaceCondition =
| LovelaceNumericStateCondition
| LovelaceStateCondition
| LovelaceScreenCondition
| LovelaceOrCondition
| LovelaceAndCondition
| LovelaceUserCondition;
export type LovelaceBaseCondition = {
condition: string;
};
export type LovelaceNumericStateCondition = LovelaceBaseCondition & {
condition: "numeric_state";
entity?: string;
below?: string | number;
above?: string | number;
};
export type LovelaceStateCondition = LovelaceBaseCondition & {
condition: "state";
entity?: string;
state?: string | string[];
state_not?: string | string[];
};
export type LovelaceScreenCondition = LovelaceBaseCondition & {
condition: "screen";
media_query?: string;
};
export type LovelaceUserCondition = LovelaceBaseCondition & {
condition: "user";
users?: string[];
};
export type LovelaceOrCondition = LovelaceBaseCondition & {
condition: "or";
conditions?: LovelaceCondition[];
};
export type LovelaceAndCondition = LovelaceBaseCondition & {
condition: "and";
conditions?: LovelaceCondition[];
};

View File

@ -1,15 +1,11 @@
import { ensureArray } from "../../../common/array/ensure-array"; import { ensureArray } from "../../../common/array/ensure-array";
import { isValidEntityId } from "../../../common/entity/valid_entity_id"; import { isValidEntityId } from "../../../common/entity/valid_entity_id";
import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import {
export type Condition = checkCondition,
| NumericStateCondition validateCondition,
| StateCondition } from "./conditions/handle-condition";
| ScreenCondition import { LovelaceCondition } from "./conditions/types";
| UserCondition
| OrCondition
| AndCondition;
// Legacy conditional card condition // Legacy conditional card condition
export interface LegacyCondition { export interface LegacyCondition {
@ -18,131 +14,6 @@ export interface LegacyCondition {
state_not?: string | string[]; state_not?: string | string[];
} }
interface BaseCondition {
condition: string;
}
export interface NumericStateCondition extends BaseCondition {
condition: "numeric_state";
entity?: string;
below?: string | number;
above?: string | number;
}
export interface StateCondition extends BaseCondition {
condition: "state";
entity?: string;
state?: string | string[];
state_not?: string | string[];
}
export interface ScreenCondition extends BaseCondition {
condition: "screen";
media_query?: string;
}
export interface UserCondition extends BaseCondition {
condition: "user";
users?: string[];
}
export interface OrCondition extends BaseCondition {
condition: "or";
conditions?: Condition[];
}
export interface AndCondition extends BaseCondition {
condition: "and";
conditions?: Condition[];
}
function getValueFromEntityId(hass: HomeAssistant, value: string): string {
if (isValidEntityId(value) && hass.states[value]) {
return hass.states[value]?.state;
}
return value;
}
function checkStateCondition(
condition: StateCondition | LegacyCondition,
hass: HomeAssistant
) {
const state =
condition.entity && hass.states[condition.entity]
? hass.states[condition.entity].state
: UNAVAILABLE;
let value = condition.state ?? condition.state_not;
// Handle entity_id, UI should be updated for conditionnal card (filters does not have UI for now)
if (typeof value === "string") {
value = getValueFromEntityId(hass, value);
}
if (Array.isArray(value)) {
value = value.map((val) => getValueFromEntityId(hass, val));
}
return condition.state != null
? ensureArray(value).includes(state)
: !ensureArray(value).includes(state);
}
function checkStateNumericCondition(
condition: NumericStateCondition,
hass: HomeAssistant
) {
const state = (condition.entity ? hass.states[condition.entity] : undefined)
?.state;
let above = condition.above;
let below = condition.below;
// Handle entity_id, UI should be updated for conditionnal card (filters does not have UI for now)
if (typeof above === "string") {
above = getValueFromEntityId(hass, above) as string;
}
if (typeof below === "string") {
below = getValueFromEntityId(hass, below) as string;
}
const numericState = Number(state);
const numericAbove = Number(above);
const numericBelow = Number(below);
if (isNaN(numericState)) {
return false;
}
return (
(condition.above == null ||
isNaN(numericAbove) ||
numericAbove < numericState) &&
(condition.below == null ||
isNaN(numericBelow) ||
numericBelow > numericState)
);
}
function checkScreenCondition(condition: ScreenCondition, _: HomeAssistant) {
return condition.media_query
? matchMedia(condition.media_query).matches
: false;
}
function checkUserCondition(condition: UserCondition, hass: HomeAssistant) {
return condition.users && hass.user?.id
? condition.users.includes(hass.user.id)
: false;
}
function checkAndCondition(condition: AndCondition, hass: HomeAssistant) {
if (!condition.conditions) return true;
return checkConditionsMet(condition.conditions, hass);
}
function checkOrCondition(condition: OrCondition, hass: HomeAssistant) {
if (!condition.conditions) return true;
return condition.conditions.some((c) => checkConditionsMet([c], hass));
}
/** /**
* Return the result of applying conditions * Return the result of applying conditions
* @param conditions conditions to apply * @param conditions conditions to apply
@ -150,32 +21,25 @@ function checkOrCondition(condition: OrCondition, hass: HomeAssistant) {
* @returns true if conditions are respected * @returns true if conditions are respected
*/ */
export function checkConditionsMet( export function checkConditionsMet(
conditions: (Condition | LegacyCondition)[], conditions: (LovelaceCondition | LegacyCondition)[],
hass: HomeAssistant hass: HomeAssistant
): boolean { ): boolean {
return conditions.every((c) => { return conditions.every((c) => {
if ("condition" in c) { if ("condition" in c) {
switch (c.condition) { return checkCondition(c, hass);
case "screen":
return checkScreenCondition(c, hass);
case "user":
return checkUserCondition(c, hass);
case "numeric_state":
return checkStateNumericCondition(c, hass);
case "and":
return checkAndCondition(c, hass);
case "or":
return checkOrCondition(c, hass);
default:
return checkStateCondition(c, hass);
}
} }
return checkStateCondition(c, hass); return checkCondition(
{
condition: "state",
...c,
},
hass
);
}); });
} }
export function extractConditionEntityIds( export function extractConditionEntityIds(
conditions: Condition[] conditions: LovelaceCondition[]
): Set<string> { ): Set<string> {
const entityIds: Set<string> = new Set(); const entityIds: Set<string> = new Set();
for (const condition of conditions) { for (const condition of conditions) {
@ -211,61 +75,22 @@ export function extractConditionEntityIds(
return entityIds; return entityIds;
} }
function validateStateCondition(condition: StateCondition | LegacyCondition) {
return (
condition.entity != null &&
(condition.state != null || condition.state_not != null)
);
}
function validateScreenCondition(condition: ScreenCondition) {
return condition.media_query != null;
}
function validateUserCondition(condition: UserCondition) {
return condition.users != null;
}
function validateAndCondition(condition: AndCondition) {
return condition.conditions != null;
}
function validateOrCondition(condition: OrCondition) {
return condition.conditions != null;
}
function validateNumericStateCondition(condition: NumericStateCondition) {
return (
condition.entity != null &&
(condition.above != null || condition.below != null)
);
}
/** /**
* Validate the conditions config for the UI * Validate the conditions config for the UI
* @param conditions conditions to apply * @param conditions conditions to apply
* @returns true if conditions are validated * @returns true if conditions are validated
*/ */
export function validateConditionalConfig( export function validateConditionalConfig(
conditions: (Condition | LegacyCondition)[] conditions: (LovelaceCondition | LegacyCondition)[]
): boolean { ): boolean {
return conditions.every((c) => { return conditions.every((c) => {
if ("condition" in c) { if ("condition" in c) {
switch (c.condition) { return validateCondition(c);
case "screen":
return validateScreenCondition(c);
case "user":
return validateUserCondition(c);
case "numeric_state":
return validateNumericStateCondition(c);
case "and":
return validateAndCondition(c);
case "or":
return validateOrCondition(c);
default:
return validateStateCondition(c);
}
} }
return validateStateCondition(c); return validateCondition({
condition: "state",
...c,
});
}); });
} }
@ -276,9 +101,9 @@ export function validateConditionalConfig(
* @returns a new condition with entity id * @returns a new condition with entity id
*/ */
export function addEntityToCondition( export function addEntityToCondition(
condition: Condition, condition: LovelaceCondition,
entityId: string entityId: string
): Condition { ): LovelaceCondition {
if ("conditions" in condition && condition.conditions) { if ("conditions" in condition && condition.conditions) {
return { return {
...condition, ...condition,

View File

@ -19,9 +19,9 @@ import "../../../../components/ha-yaml-editor";
import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box"; import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
import { haStyle } from "../../../../resources/styles"; import { haStyle } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import { LovelaceCondition } from "../../common/conditions/types";
import { ICON_CONDITION } from "../../common/icon-condition"; import { ICON_CONDITION } from "../../common/icon-condition";
import { import {
Condition,
LegacyCondition, LegacyCondition,
checkConditionsMet, checkConditionsMet,
validateConditionalConfig, validateConditionalConfig,
@ -32,7 +32,9 @@ import type { LovelaceConditionEditorConstructor } from "./types";
export class HaCardConditionEditor extends LitElement { export class HaCardConditionEditor extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) condition!: Condition | LegacyCondition; @property({ attribute: false }) condition!:
| LovelaceCondition
| LegacyCondition;
@state() public _yamlMode = false; @state() public _yamlMode = false;
@ -40,7 +42,7 @@ export class HaCardConditionEditor extends LitElement {
@state() public _uiWarnings: string[] = []; @state() public _uiWarnings: string[] = [];
@state() _condition?: Condition; @state() _condition?: LovelaceCondition;
@state() private _testingResult?: boolean; @state() private _testingResult?: boolean;

View File

@ -16,17 +16,18 @@ import "../../../../components/ha-list-item";
import type { HaSelect } from "../../../../components/ha-select"; import type { HaSelect } from "../../../../components/ha-select";
import "../../../../components/ha-svg-icon"; import "../../../../components/ha-svg-icon";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import { LovelaceCondition } from "../../common/conditions/types";
import { ICON_CONDITION } from "../../common/icon-condition"; import { ICON_CONDITION } from "../../common/icon-condition";
import { Condition, LegacyCondition } from "../../common/validate-condition"; import { LegacyCondition } from "../../common/validate-condition";
import "./ha-card-condition-editor"; import "./ha-card-condition-editor";
import type { HaCardConditionEditor } from "./ha-card-condition-editor"; import type { HaCardConditionEditor } from "./ha-card-condition-editor";
import { LovelaceConditionEditorConstructor } from "./types"; import { LovelaceConditionEditorConstructor } from "./types";
import "./types/ha-card-condition-and";
import "./types/ha-card-condition-numeric_state"; import "./types/ha-card-condition-numeric_state";
import "./types/ha-card-condition-or";
import "./types/ha-card-condition-screen"; import "./types/ha-card-condition-screen";
import "./types/ha-card-condition-state"; import "./types/ha-card-condition-state";
import "./types/ha-card-condition-user"; import "./types/ha-card-condition-user";
import "./types/ha-card-condition-or";
import "./types/ha-card-condition-and";
const UI_CONDITION = [ const UI_CONDITION = [
"numeric_state", "numeric_state",
@ -35,14 +36,14 @@ const UI_CONDITION = [
"user", "user",
"and", "and",
"or", "or",
] as const satisfies readonly Condition["condition"][]; ] as const satisfies readonly LovelaceCondition["condition"][];
@customElement("ha-card-conditions-editor") @customElement("ha-card-conditions-editor")
export class HaCardConditionsEditor extends LitElement { export class HaCardConditionsEditor extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public conditions!: ( @property({ attribute: false }) public conditions!: (
| Condition | LovelaceCondition
| LegacyCondition | LegacyCondition
)[]; )[];
@ -138,7 +139,7 @@ export class HaCardConditionsEditor extends LitElement {
private _addCondition(ev: CustomEvent): void { private _addCondition(ev: CustomEvent): void {
const condition = (ev.currentTarget as HaSelect).items[ev.detail.index] const condition = (ev.currentTarget as HaSelect).items[ev.detail.index]
.value as Condition["condition"]; .value as LovelaceCondition["condition"];
const conditions = [...this.conditions]; const conditions = [...this.conditions];
const elClass = customElements.get(`ha-card-condition-${condition}`) as const elClass = customElements.get(`ha-card-condition-${condition}`) as

View File

@ -5,10 +5,9 @@ import { fireEvent } from "../../../../../common/dom/fire_event";
import "../../../../../components/ha-form/ha-form"; import "../../../../../components/ha-form/ha-form";
import type { HomeAssistant } from "../../../../../types"; import type { HomeAssistant } from "../../../../../types";
import { import {
AndCondition, LovelaceAndCondition,
Condition, LovelaceCondition,
StateCondition, } from "../../../common/conditions/types";
} from "../../../common/validate-condition";
import "../ha-card-conditions-editor"; import "../ha-card-conditions-editor";
const andConditionStruct = object({ const andConditionStruct = object({
@ -20,15 +19,15 @@ const andConditionStruct = object({
export class HaCardConditionNumericAnd extends LitElement { export class HaCardConditionNumericAnd extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public condition!: AndCondition; @property({ attribute: false }) public condition!: LovelaceAndCondition;
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled = false;
public static get defaultConfig(): AndCondition { public static get defaultConfig(): LovelaceAndCondition {
return { condition: "and", conditions: [] }; return { condition: "and", conditions: [] };
} }
protected static validateUIConfig(condition: StateCondition) { protected static validateUIConfig(condition: LovelaceAndCondition) {
return assert(condition, andConditionStruct); return assert(condition, andConditionStruct);
} }
@ -46,7 +45,7 @@ export class HaCardConditionNumericAnd extends LitElement {
private _valueChanged(ev: CustomEvent): void { private _valueChanged(ev: CustomEvent): void {
ev.stopPropagation(); ev.stopPropagation();
const conditions = ev.detail.value as Condition[]; const conditions = ev.detail.value as LovelaceCondition[];
const condition = { const condition = {
...this.condition, ...this.condition,
conditions, conditions,

View File

@ -8,10 +8,7 @@ import "../../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../../components/ha-form/types"; import type { SchemaUnion } from "../../../../../components/ha-form/types";
import { HaFormSchema } from "../../../../../components/ha-form/types"; import { HaFormSchema } from "../../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../../types"; import type { HomeAssistant } from "../../../../../types";
import { import { LovelaceNumericStateCondition } from "../../../common/conditions/types";
NumericStateCondition,
StateCondition,
} from "../../../common/validate-condition";
const numericStateConditionStruct = object({ const numericStateConditionStruct = object({
condition: literal("numeric_state"), condition: literal("numeric_state"),
@ -24,15 +21,16 @@ const numericStateConditionStruct = object({
export class HaCardConditionNumericState extends LitElement { export class HaCardConditionNumericState extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public condition!: NumericStateCondition; @property({ attribute: false })
public condition!: LovelaceNumericStateCondition;
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled = false;
public static get defaultConfig(): NumericStateCondition { public static get defaultConfig(): LovelaceNumericStateCondition {
return { condition: "numeric_state", entity: "" }; return { condition: "numeric_state", entity: "" };
} }
protected static validateUIConfig(condition: StateCondition) { protected static validateUIConfig(condition: LovelaceNumericStateCondition) {
return assert(condition, numericStateConditionStruct); return assert(condition, numericStateConditionStruct);
} }
@ -88,7 +86,7 @@ export class HaCardConditionNumericState extends LitElement {
private _valueChanged(ev: CustomEvent): void { private _valueChanged(ev: CustomEvent): void {
ev.stopPropagation(); ev.stopPropagation();
const condition = ev.detail.value as NumericStateCondition; const condition = ev.detail.value as LovelaceNumericStateCondition;
fireEvent(this, "value-changed", { value: condition }); fireEvent(this, "value-changed", { value: condition });
} }

View File

@ -5,10 +5,9 @@ import { fireEvent } from "../../../../../common/dom/fire_event";
import "../../../../../components/ha-form/ha-form"; import "../../../../../components/ha-form/ha-form";
import type { HomeAssistant } from "../../../../../types"; import type { HomeAssistant } from "../../../../../types";
import { import {
Condition, LovelaceCondition,
OrCondition, LovelaceOrCondition,
StateCondition, } from "../../../common/conditions/types";
} from "../../../common/validate-condition";
import "../ha-card-conditions-editor"; import "../ha-card-conditions-editor";
const orConditionStruct = object({ const orConditionStruct = object({
@ -20,15 +19,15 @@ const orConditionStruct = object({
export class HaCardConditionOr extends LitElement { export class HaCardConditionOr extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public condition!: OrCondition; @property({ attribute: false }) public condition!: LovelaceOrCondition;
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled = false;
public static get defaultConfig(): OrCondition { public static get defaultConfig(): LovelaceOrCondition {
return { condition: "or", conditions: [] }; return { condition: "or", conditions: [] };
} }
protected static validateUIConfig(condition: StateCondition) { protected static validateUIConfig(condition: LovelaceOrCondition) {
return assert(condition, orConditionStruct); return assert(condition, orConditionStruct);
} }
@ -46,7 +45,7 @@ export class HaCardConditionOr extends LitElement {
private _valueChanged(ev: CustomEvent): void { private _valueChanged(ev: CustomEvent): void {
ev.stopPropagation(); ev.stopPropagation();
const conditions = ev.detail.value as Condition[]; const conditions = ev.detail.value as LovelaceCondition[];
const condition = { const condition = {
...this.condition, ...this.condition,
conditions, conditions,

View File

@ -8,7 +8,7 @@ import "../../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../../components/ha-form/types"; import type { SchemaUnion } from "../../../../../components/ha-form/types";
import { HaFormSchema } from "../../../../../components/ha-form/types"; import { HaFormSchema } from "../../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../../types"; import type { HomeAssistant } from "../../../../../types";
import { ScreenCondition } from "../../../common/validate-condition"; import { LovelaceScreenCondition } from "../../../common/conditions/types";
const BREAKPOINT_VALUES = [0, 768, 1024, 1280, Infinity]; const BREAKPOINT_VALUES = [0, 768, 1024, 1280, Infinity];
const BREAKPOINTS = ["mobile", "tablet", "desktop", "wide"] as const; const BREAKPOINTS = ["mobile", "tablet", "desktop", "wide"] as const;
@ -95,16 +95,16 @@ type ScreenConditionData = {
export class HaCardConditionScreen extends LitElement { export class HaCardConditionScreen extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public condition!: ScreenCondition; @property({ attribute: false }) public condition!: LovelaceScreenCondition;
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled = false;
public static get defaultConfig(): ScreenCondition { public static get defaultConfig(): LovelaceScreenCondition {
return { condition: "screen", media_query: "" }; return { condition: "screen", media_query: "" };
} }
protected static validateUIConfig( protected static validateUIConfig(
condition: ScreenCondition, condition: LovelaceScreenCondition,
hass: HomeAssistant hass: HomeAssistant
) { ) {
const valid = const valid =
@ -174,7 +174,7 @@ export class HaCardConditionScreen extends LitElement {
const { breakpoints } = data; const { breakpoints } = data;
const condition: ScreenCondition = { const condition: LovelaceScreenCondition = {
condition: "screen", condition: "screen",
media_query: mediaQueryMap.get(computeBreakpointsKey(breakpoints)) ?? "", media_query: mediaQueryMap.get(computeBreakpointsKey(breakpoints)) ?? "",
}; };

View File

@ -8,7 +8,7 @@ import "../../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../../components/ha-form/types"; import type { SchemaUnion } from "../../../../../components/ha-form/types";
import { HaFormSchema } from "../../../../../components/ha-form/types"; import { HaFormSchema } from "../../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../../types"; import type { HomeAssistant } from "../../../../../types";
import { StateCondition } from "../../../common/validate-condition"; import { LovelaceStateCondition } from "../../../common/conditions/types";
const stateConditionStruct = object({ const stateConditionStruct = object({
condition: literal("state"), condition: literal("state"),
@ -28,15 +28,15 @@ type StateConditionData = {
export class HaCardConditionState extends LitElement { export class HaCardConditionState extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public condition!: StateCondition; @property({ attribute: false }) public condition!: LovelaceStateCondition;
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled = false;
public static get defaultConfig(): StateCondition { public static get defaultConfig(): LovelaceStateCondition {
return { condition: "state", entity: "", state: "" }; return { condition: "state", entity: "", state: "" };
} }
protected static validateUIConfig(condition: StateCondition) { protected static validateUIConfig(condition: LovelaceStateCondition) {
return assert(condition, stateConditionStruct); return assert(condition, stateConditionStruct);
} }
@ -124,7 +124,7 @@ export class HaCardConditionState extends LitElement {
const { invert, state, condition: _, ...content } = data; const { invert, state, condition: _, ...content } = data;
const condition: StateCondition = { const condition: LovelaceStateCondition = {
condition: "state", condition: "state",
...content, ...content,
state: invert === "false" ? state ?? "" : undefined, state: invert === "false" ? state ?? "" : undefined,

View File

@ -10,7 +10,7 @@ import "../../../../../components/ha-switch";
import "../../../../../components/user/ha-user-badge"; import "../../../../../components/user/ha-user-badge";
import { User, fetchUsers } from "../../../../../data/user"; import { User, fetchUsers } from "../../../../../data/user";
import type { HomeAssistant } from "../../../../../types"; import type { HomeAssistant } from "../../../../../types";
import { UserCondition } from "../../../common/validate-condition"; import { LovelaceUserCondition } from "../../../common/conditions/types";
const userConditionStruct = object({ const userConditionStruct = object({
condition: literal("user"), condition: literal("user"),
@ -21,17 +21,17 @@ const userConditionStruct = object({
export class HaCardConditionUser extends LitElement { export class HaCardConditionUser extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public condition!: UserCondition; @property({ attribute: false }) public condition!: LovelaceUserCondition;
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled = false;
public static get defaultConfig(): UserCondition { public static get defaultConfig(): LovelaceUserCondition {
return { condition: "user", users: [] }; return { condition: "user", users: [] };
} }
@state() private _users: User[] = []; @state() private _users: User[] = [];
protected static validateUIConfig(condition: UserCondition) { protected static validateUIConfig(condition: LovelaceUserCondition) {
return assert(condition, userConditionStruct); return assert(condition, userConditionStruct);
} }
@ -95,7 +95,7 @@ export class HaCardConditionUser extends LitElement {
users = users.filter((user) => user !== userId); users = users.filter((user) => user !== userId);
} }
const condition: UserCondition = { const condition: LovelaceUserCondition = {
...this.condition, ...this.condition,
users, users,
}; };