Compare commits

...

1 Commits

Author SHA1 Message Date
Wendelin 6b010b7ada Migrate getTriggerInfos to hassless 2026-05-26 09:12:17 +02:00
18 changed files with 543 additions and 348 deletions
@@ -75,7 +75,17 @@ export class DemoAutomationDescribeCondition extends LitElement {
<div class="condition">
<span>
${this._condition
? describeCondition(this._condition, this.hass, [])
? describeCondition(
this._condition,
this.hass.localize,
this.hass.locale,
[],
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue
)
: "<invalid YAML>"}
</span>
<ha-yaml-editor
@@ -88,7 +98,19 @@ export class DemoAutomationDescribeCondition extends LitElement {
${conditions.map(
(conf) => html`
<div class="condition">
<span>${describeCondition(conf as any, this.hass, [])}</span>
<span
>${describeCondition(
conf as any,
this.hass.localize,
this.hass.locale,
[],
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue
)}</span
>
<pre>${dump(conf)}</pre>
</div>
`
@@ -99,7 +99,17 @@ export class DemoAutomationDescribeTrigger extends LitElement {
<div class="trigger">
<span>
${this._trigger
? describeTrigger(this._trigger, this.hass, [])
? describeTrigger(
this._trigger,
this.hass.localize,
this.hass.locale,
[],
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue
)
: "<invalid YAML>"}
</span>
<ha-yaml-editor
@@ -111,7 +121,19 @@ export class DemoAutomationDescribeTrigger extends LitElement {
${triggers.map(
(conf) => html`
<div class="trigger">
<span>${describeTrigger(conf as any, this.hass, [])}</span>
<span
>${describeTrigger(
conf as any,
this.hass.localize,
this.hass.locale,
[],
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue
)}</span
>
<pre>${dump(conf)}</pre>
</div>
`
+14 -7
View File
@@ -1,3 +1,4 @@
import { consume, type ContextType } from "@lit/context";
import {
mdiAmpersand,
mdiClockOutline,
@@ -12,11 +13,11 @@ import {
mdiWeatherSunny,
} from "@mdi/js";
import { html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { customElement, property, state } from "lit/decorators";
import { until } from "lit/directives/until";
import { computeDomain } from "../common/entity/compute_domain";
import { configContext, connectionContext } from "../data/context";
import { conditionIcon, FALLBACK_DOMAIN_ICONS } from "../data/icons";
import type { HomeAssistant } from "../types";
import "./ha-icon";
import "./ha-svg-icon";
@@ -36,12 +37,18 @@ export const CONDITION_ICONS = {
@customElement("ha-condition-icon")
export class HaConditionIcon extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property() public condition?: string;
@property() public icon?: string;
@state()
@consume({ context: connectionContext, subscribe: true })
protected _connection?: ContextType<typeof connectionContext>;
@state()
@consume({ context: configContext, subscribe: true })
protected _config?: ContextType<typeof configContext>;
protected render() {
if (this.icon) {
return html`<ha-icon .icon=${this.icon}></ha-icon>`;
@@ -51,13 +58,13 @@ export class HaConditionIcon extends LitElement {
return nothing;
}
if (!this.hass) {
if (!this._connection || !this._config) {
return this._renderFallback();
}
const icon = conditionIcon(
this.hass.connection,
this.hass.config,
this._connection.connection,
this._config.config,
this.condition
).then((icn) => {
if (icn) {
+14 -4
View File
@@ -1,3 +1,4 @@
import { consume, type ContextType } from "@lit/context";
import {
mdiAvTimer,
mdiCalendar,
@@ -18,9 +19,10 @@ import {
mdiWebhook,
} from "@mdi/js";
import { html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { customElement, property, state } from "lit/decorators";
import { until } from "lit/directives/until";
import { computeDomain } from "../common/entity/compute_domain";
import { configContext, connectionContext } from "../data/context";
import { FALLBACK_DOMAIN_ICONS, triggerIcon } from "../data/icons";
import { mdiHomeAssistant } from "../resources/home-assistant-logo-svg";
import type { HomeAssistant } from "../types";
@@ -56,6 +58,14 @@ export class HaTriggerIcon extends LitElement {
@property() public icon?: string;
@state()
@consume({ context: connectionContext, subscribe: true })
protected _connection?: ContextType<typeof connectionContext>;
@state()
@consume({ context: configContext, subscribe: true })
protected _config?: ContextType<typeof configContext>;
protected render() {
if (this.icon) {
return html`<ha-icon .icon=${this.icon}></ha-icon>`;
@@ -65,13 +75,13 @@ export class HaTriggerIcon extends LitElement {
return nothing;
}
if (!this.hass) {
if (!this._connection || !this._config) {
return this._renderFallback();
}
const icon = triggerIcon(
this.hass.connection,
this.hass.config,
this._connection.connection,
this._config.config,
this.trigger
).then((icn) => {
if (icn) {
+24 -6
View File
@@ -171,16 +171,28 @@ export class HaTracePathDetails extends LitElement {
migrateAutomationTrigger({
...currentDetail,
}) as Trigger,
this.hass,
this._entityReg
this.hass.localize,
this.hass.locale,
this._entityReg,
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue
)}
</h2>`
: selectedType === "condition"
? html`<h2>
${describeCondition(
currentDetail,
this.hass,
this._entityReg
this.hass.localize,
this.hass.locale,
this._entityReg,
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue
)}
</h2>`
: selectedType === "action"
@@ -215,8 +227,14 @@ export class HaTracePathDetails extends LitElement {
.includes("condition")
? html`[${describeCondition(
currentDetail,
this.hass,
this._entityReg
this.hass.localize,
this.hass.locale,
this._entityReg,
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue
)}]<br />`
: nothing}
${this.hass!.localize(
+3 -3
View File
@@ -10,7 +10,7 @@ import type { WeekdayShort } from "../common/datetime/weekday";
import { navigate } from "../common/navigate";
import type { LocalizeKeys } from "../common/translations/localize";
import { createSearchParam } from "../common/url/search-params";
import type { Context, HomeAssistant } from "../types";
import type { CallWS, Context, HomeAssistant } from "../types";
import type { BlueprintInput } from "./blueprint";
import type { ConditionDescription } from "./condition";
import { CONDITION_BUILDING_BLOCKS } from "./condition";
@@ -578,11 +578,11 @@ export const subscribeTrigger = (
});
export const testCondition = (
hass: HomeAssistant,
callWS: CallWS,
condition: Condition | Condition[],
variables?: Record<string, unknown>
) =>
hass.callWS<{ result: boolean }>({
callWS<{ result: boolean }>({
type: "test_condition",
condition,
variables,
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1,4 +1,4 @@
import type { HomeAssistant } from "../types";
import type { CallWS } from "../types";
export interface ValidConfig {
valid: true;
@@ -13,10 +13,10 @@ export interface InvalidConfig {
type ValidKeys = "triggers" | "actions" | "conditions";
export const validateConfig = <T extends Partial<Record<ValidKeys, unknown>>>(
hass: HomeAssistant,
callWS: CallWS,
config: T
): Promise<Record<keyof T, ValidConfig | InvalidConfig>> =>
hass.callWS({
callWS({
type: "validate_config",
...config,
});
+12 -2
View File
@@ -9,8 +9,8 @@ import type { Condition } from "./automation";
import { describeCondition } from "./automation_i18n";
import { localizeDeviceAutomationAction } from "./device/device_automation";
import type { EntityRegistryEntry } from "./entity/entity_registry";
import { domainToName } from "./integration";
import type { DomainManifestLookup } from "./integration";
import { domainToName } from "./integration";
import type {
ActionType,
ActionTypes,
@@ -322,7 +322,17 @@ const tryDescribeAction = <T extends ActionType>(
return hass.localize(
`${actionTranslationBaseKey}.check_condition.description.full`,
{
condition: describeCondition(action as Condition, hass, entityRegistry),
condition: describeCondition(
action as Condition,
hass.localize,
hass.locale,
entityRegistry,
hass.states,
hass.entities,
hass.config,
hass.formatEntityState,
hass.formatEntityAttributeValue
),
}
);
}
@@ -801,7 +801,7 @@ export default class HaAutomationActionRow extends LitElement {
this._running = false;
this._runResult = undefined;
const validated = await validateConfig(this.hass, {
const validated = await validateConfig(this.hass.callWS, {
actions: this.action,
});
@@ -156,7 +156,6 @@ export class HaConditionAction
return html`<ha-condition-icon
slot="start"
.hass=${this.hass}
.condition=${condition}
></ha-condition-icon
><span slot="headline">${label}</span>`;
@@ -166,7 +165,6 @@ export class HaConditionAction
<ha-combo-box-item type="button">
<ha-condition-icon
slot="start"
.hass=${this.hass}
.condition=${item.search_labels!.condition || undefined}
></ha-condition-icon>
<span slot="headline">${item.primary}</span>
@@ -1897,12 +1897,7 @@ class DialogAddAutomationElement
): AddAutomationElementListItem {
const triggerName = getTriggerObjectId(trigger);
return {
icon: html`
<ha-trigger-icon
.hass=${this.hass}
.trigger=${trigger}
></ha-trigger-icon>
`,
icon: html` <ha-trigger-icon .trigger=${trigger}></ha-trigger-icon> `,
key: `${DYNAMIC_PREFIX}${trigger}`,
name:
localize(`component.${domain}.triggers.${triggerName}.name`) || trigger,
@@ -1920,10 +1915,7 @@ class DialogAddAutomationElement
const conditionName = getConditionObjectId(condition);
return {
icon: html`
<ha-condition-icon
.hass=${this.hass}
.condition=${condition}
></ha-condition-icon>
<ha-condition-icon .condition=${condition}></ha-condition-icon>
`,
key: `${DYNAMIC_PREFIX}${condition}`,
name:
@@ -233,7 +233,17 @@ export default class HaAutomationConditionRow extends LitElement {
this.condition as TriggerCondition
)
: capitalizeFirstLetter(
describeCondition(this.condition, this.hass, this._entityReg)
describeCondition(
this.condition,
this.hass.localize,
this.hass.locale,
this._entityReg,
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue
)
)}
${target !== undefined || (descriptionHasTarget && !this._isNew)
? this._renderTargets(
@@ -610,8 +620,14 @@ export default class HaAutomationConditionRow extends LitElement {
const triggerInfos = this._getTriggerInfos(
ensureArray(this._automationConfig?.triggers || []),
this.hass,
this._entityReg
this.hass.localize,
this.hass.locale,
this._entityReg,
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue
);
const infoById = new Map(triggerInfos.map((info) => [info.id, info]));
return html`${prefix}
@@ -858,7 +874,7 @@ export default class HaAutomationConditionRow extends LitElement {
let validateResult: Record<"conditions", InvalidConfig | ValidConfig>;
try {
validateResult = await validateConfig(this.hass, {
validateResult = await validateConfig(this.hass.callWS, {
conditions: condition,
});
} catch (err: any) {
@@ -889,7 +905,7 @@ export default class HaAutomationConditionRow extends LitElement {
let result: { result: boolean };
try {
result = await testCondition(this.hass, condition);
result = await testCondition(this.hass.callWS, condition);
} catch (err: any) {
if (this.condition !== condition) {
return;
@@ -921,7 +937,18 @@ export default class HaAutomationConditionRow extends LitElement {
),
inputType: "string",
placeholder: capitalizeFirstLetter(
describeCondition(this.condition, this.hass, this._entityReg, true)
describeCondition(
this.condition,
this.hass.localize,
this.hass.locale,
this._entityReg,
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue,
true
)
),
defaultValue: this.condition.alias,
confirmText: this.hass.localize("ui.common.submit"),
@@ -1,4 +1,4 @@
import { consume } from "@lit/context";
import { consume, type ContextType } from "@lit/context";
import { mdiAlert } from "@mdi/js";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
@@ -22,15 +22,19 @@ import {
getTriggerInfos,
type TriggerInfo,
} from "../../../../../data/automation_i18n";
import { fullEntitiesContext } from "../../../../../data/context";
import {
configContext,
entitiesContext,
formattersContext,
fullEntitiesContext,
internationalizationContext,
statesContext,
} from "../../../../../data/context";
import type { EntityRegistryEntry } from "../../../../../data/entity/entity_registry";
import type { HomeAssistant } from "../../../../../types";
import "../../ha-trigger-id-chip";
@customElement("ha-automation-condition-trigger")
export class HaTriggerCondition extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public condition!: TriggerCondition;
@property({ type: Boolean }) public disabled = false;
@@ -43,6 +47,22 @@ export class HaTriggerCondition extends LitElement {
@consume({ context: fullEntitiesContext, subscribe: true })
private _entityReg: EntityRegistryEntry[] = [];
@state()
@consume({ context: internationalizationContext, subscribe: true })
protected _i18n!: ContextType<typeof internationalizationContext>;
@consume({ context: statesContext, subscribe: true })
protected _states!: ContextType<typeof statesContext>;
@consume({ context: entitiesContext, subscribe: true })
protected _entities!: ContextType<typeof entitiesContext>;
@consume({ context: configContext, subscribe: true })
protected _config!: ContextType<typeof configContext>;
@consume({ context: formattersContext, subscribe: true })
protected _formatters!: ContextType<typeof formattersContext>;
private _triggerInfos = memoizeOne(
(
triggers: AutomationConfig["triggers"] | undefined,
@@ -50,8 +70,14 @@ export class HaTriggerCondition extends LitElement {
): TriggerInfo[] =>
getTriggerInfos(
triggers ? ensureArray(triggers) : undefined,
this.hass,
entityReg
this._i18n?.localize,
this._i18n?.locale,
entityReg,
this._states,
this._entities,
this._config?.config,
this._formatters?.formatEntityState,
this._formatters?.formatEntityAttributeValue
)
);
@@ -75,7 +101,7 @@ export class HaTriggerCondition extends LitElement {
if (!triggerInfos.length && !selectedIds.length) {
return html`
<ha-alert alert-type="info">
${this.hass.localize(
${this._i18n.localize(
"ui.panel.config.automation.editor.conditions.type.trigger.no_triggers"
)}
</ha-alert>
@@ -115,9 +141,9 @@ export class HaTriggerCondition extends LitElement {
>
${alertIcon}
</ha-trigger-id-chip>
${this.hass.localize("state.default.unavailable")}
${this._i18n.localize("state.default.unavailable")}
<ha-tooltip .for=${`trigger-${id}`}>
${this.hass.localize(
${this._i18n.localize(
"ui.panel.config.automation.editor.conditions.type.trigger.unavailable_info",
{ id: html`<b>${id}</b>` }
)}
@@ -143,7 +169,7 @@ export class HaTriggerCondition extends LitElement {
</ha-trigger-id-chip>
${info.label}${info.count > 1
? html`<ha-tooltip .for=${`trigger-${info.id}`}
>${this.hass.localize(
>${this._i18n.localize(
"ui.panel.config.automation.editor.conditions.type.trigger.duplicated_info"
)}</ha-tooltip
>`
@@ -647,7 +647,7 @@ export class HaAutomationEditor extends AutomationScriptEditorMixin<AutomationCo
if (stateObj?.state !== UNAVAILABLE) {
return;
}
const validation = await validateConfig(this.hass, {
const validation = await validateConfig(this.hass.callWS, {
triggers: this.config.triggers,
conditions: this.config.conditions,
actions: this.config.actions,
@@ -117,7 +117,18 @@ export default class HaAutomationOptionRow extends LitElement {
if (typeof conditions[0] === "string") {
str += conditions[0];
} else {
str += describeCondition(conditions[0], this.hass, this._entityReg);
str += describeCondition(
conditions[0],
this.hass.localize,
this.hass.locale,
this._entityReg,
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue,
true
);
}
if (conditions.length > 1) {
str += this.hass.localize(
@@ -273,7 +273,6 @@ export default class HaAutomationTriggerRow extends LitElement {
></ha-svg-icon>`
: html`<ha-trigger-icon
slot="leading-icon"
.hass=${this.hass}
.trigger=${(this.trigger as Exclude<Trigger, TriggerList>).trigger}
></ha-trigger-icon>`}
<h3 slot="header">
@@ -299,7 +298,17 @@ export default class HaAutomationTriggerRow extends LitElement {
</ha-tooltip>`
: nothing} `
: nothing}
${describeTrigger(this.trigger, this.hass, this._entityReg)}
${describeTrigger(
this.trigger,
this.hass.localize,
this.hass.locale,
this._entityReg,
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue
)}
${target !== undefined || (descriptionHasTarget && !this._isNew)
? this._renderTargets(
target,
@@ -675,7 +684,7 @@ export default class HaAutomationTriggerRow extends LitElement {
this._triggerUnsub = undefined;
}
const validateResult = await validateConfig(this.hass, {
const validateResult = await validateConfig(this.hass.callWS, {
triggers: trigger,
});
@@ -871,7 +880,18 @@ export default class HaAutomationTriggerRow extends LitElement {
),
inputType: "string",
placeholder: capitalizeFirstLetter(
describeTrigger(this.trigger, this.hass, this._entityReg, true)
describeTrigger(
this.trigger,
this.hass.localize,
this.hass.locale,
this._entityReg,
this.hass.states,
this.hass.entities,
this.hass.config,
this.hass.formatEntityState,
this.hass.formatEntityAttributeValue,
true
)
),
defaultValue: this.trigger.alias,
confirmText: this.hass.localize("ui.common.submit"),
+1 -1
View File
@@ -560,7 +560,7 @@ export class HaScriptEditor extends SubscribeMixin(
if (stateObj?.state !== UNAVAILABLE) {
return;
}
const validation = await validateConfig(this.hass, {
const validation = await validateConfig(this.hass.callWS, {
actions: this.config.sequence,
});
this.validationErrors = (