Compare commits

...
3 changed files with 159 additions and 4 deletions
+1 -1
View File
@@ -133,7 +133,7 @@ const numericThresholdSuffix = (config: {
return undefined;
};
const formatNumericLimitValue = (
export const formatNumericLimitValue = (
hass: HomeAssistant,
value?: number | string
) => {
@@ -15,6 +15,7 @@ import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { ensureArray } from "../../../../common/array/ensure-array";
import {
isEntityReference,
isLogicalCondition,
logicalChildren,
} from "../../../../common/condition/translate";
@@ -24,6 +25,12 @@ import { storage } from "../../../../common/decorators/storage";
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
import { fireEvent } from "../../../../common/dom/fire_event";
import { stopPropagation } from "../../../../common/dom/stop_propagation";
import { computeAttributeNameDisplay } from "../../../../common/entity/compute_attribute_display";
import { computeStateName } from "../../../../common/entity/compute_state_name";
import {
formatListWithAnds,
formatListWithOrs,
} from "../../../../common/string/format-list";
import { handleStructError } from "../../../../common/structs/handle-errors";
import "../../../../components/automation/ha-automation-row-event-chip";
import "../../../../components/automation/ha-automation-row-live-test";
@@ -55,6 +62,7 @@ import {
CONDITION_ROW_CONFIG_KEYS,
pickRowConfig,
} from "../../../../data/automation";
import { formatNumericLimitValue } from "../../../../data/automation_i18n";
import { ICON_CONDITION } from "../../common/icon-condition";
import type {
AndCondition,
@@ -79,6 +87,9 @@ const NO_ENTITY_CONDITIONS = ["state", "numeric_state"];
const CONTAINER_CONDITIONS = ["and", "or", "not"];
const CORE_STATE_ENTITY_ID =
/^input_(?:select|text|number|boolean|datetime)\.(?!.+__)(?!_)[\da-z_]+(?<!_)$/;
const isNoEntityCondition = (condition: string, noEntity: boolean): boolean =>
NO_ENTITY_CONDITIONS.includes(condition) && noEntity;
@@ -426,6 +437,132 @@ export class HaCardConditionEditor extends LitElement {
};
}
private _describeCondition(): string | undefined {
const condition = this.condition;
if (
!condition ||
typeof condition !== "object" ||
Array.isArray(condition) ||
("condition" in condition &&
condition.condition !== "state" &&
condition.condition !== "numeric_state")
) {
return undefined;
}
const entityIds = ensureArray(
("entity_id" in condition
? condition.entity_id
: "entity" in condition
? condition.entity
: undefined) ||
(this._entityContext?.mode === "current"
? this._entityContext.entityId
: undefined) ||
[]
);
const entityNames = entityIds.map((entityId) =>
this.hass.states[entityId]
? computeStateName(this.hass.states[entityId])
: entityId
);
const entity =
"match" in condition && condition.match === "any"
? formatListWithOrs(this.hass.locale, entityNames)
: formatListWithAnds(this.hass.locale, entityNames);
if (!entity) {
return undefined;
}
const stateObj = this.hass.states[entityIds[0]];
const attributeName =
"attribute" in condition ? condition.attribute : undefined;
const attribute =
attributeName && stateObj
? computeAttributeNameDisplay(
this.hass.localize,
stateObj,
this.hass.entities,
attributeName
)
: attributeName;
if (!("condition" in condition) || condition.condition === "state") {
const stateValue = "state" in condition ? condition.state : undefined;
const stateNot =
"state_not" in condition ? condition.state_not : undefined;
const value = stateValue ?? stateNot;
const values = ensureArray(value ?? [])
.filter((v) => v !== "")
.flatMap<string | number>((v) => {
if (!isEntityReference(v)) {
return [v];
}
const referencedState = this.hass.states[v]?.state;
if (referencedState === undefined) {
return [v];
}
// Core resolves helper references; legacy conditions also match the literal.
if ("entity_id" in condition) {
return CORE_STATE_ENTITY_ID.test(v) ? [referencedState] : [v];
}
return Array.isArray(value) || referencedState
? [v, referencedState]
: [v];
});
if (!values.length) {
return undefined;
}
const states = formatListWithOrs(
this.hass.locale,
values.map((v) =>
stateObj
? attributeName
? this.hass
.formatEntityAttributeValue(stateObj, attributeName, v)
.toString()
: this.hass.formatEntityState(stateObj, String(v))
: String(v)
)
);
const invert = stateValue == null && stateNot !== undefined;
const variant = invert ? "is_not" : "is";
return this.hass.localize(
`ui.panel.lovelace.editor.condition-editor.condition.state.description.${
attribute ? `${variant}_attribute` : variant
}`,
{ entity, state: states, attribute }
);
}
if (condition.condition === "numeric_state") {
const above = "above" in condition ? condition.above : undefined;
const below = "below" in condition ? condition.below : undefined;
if (above === undefined && below === undefined) {
return undefined;
}
const variant =
above !== undefined && below !== undefined
? "above_below"
: above !== undefined
? "above"
: "below";
return this.hass.localize(
`ui.panel.lovelace.editor.condition-editor.condition.numeric_state.description.${
attribute ? `${variant}_attribute` : variant
}`,
{
entity,
above: formatNumericLimitValue(this.hass, above),
below: formatNumericLimitValue(this.hass, below),
attribute,
}
);
}
return undefined;
}
protected render() {
const condition = this._condition;
@@ -433,6 +570,8 @@ export class HaCardConditionEditor extends LitElement {
const hideLiveTest = this._hideLiveTest(condition);
const description = this._describeCondition();
return html`
<div class="container">
<ha-expansion-panel left-chevron>
@@ -464,9 +603,11 @@ export class HaCardConditionEditor extends LitElement {
}
<h3 slot="header">
${
description ||
this.hass.localize(
`ui.panel.lovelace.editor.condition-editor.condition.${condition.condition}.label`
) || condition.condition
) ||
condition.condition
}
</h3>
<ha-automation-row-event-chip
+16 -2
View File
@@ -9893,7 +9893,15 @@
"label": "Entity numeric state",
"attribute": "[%key:ui::panel::lovelace::editor::condition-editor::condition::state::attribute%]",
"above": "Above",
"below": "Below"
"below": "Below",
"description": {
"above": "{entity} is above {above}",
"below": "{entity} is below {below}",
"above_below": "{entity} is above {above} and below {below}",
"above_attribute": "{entity} {attribute} is above {above}",
"below_attribute": "{entity} {attribute} is below {below}",
"above_below_attribute": "{entity} {attribute} is above {above} and below {below}"
}
},
"screen": {
"label": "Screen",
@@ -9911,7 +9919,13 @@
"attribute": "Attribute (optional)",
"current_entity": "Current entity",
"state_equal": "State is equal to",
"state_not_equal": "State is not equal to"
"state_not_equal": "State is not equal to",
"description": {
"is": "{entity} is {state}",
"is_not": "{entity} is not {state}",
"is_attribute": "{entity} {attribute} is {state}",
"is_not_attribute": "{entity} {attribute} is not {state}"
}
},
"time": {
"label": "Time",