Compare commits

...
4 changed files with 160 additions and 47 deletions
@@ -20,10 +20,19 @@ import {
type TriggerIdOption,
} from "../../trigger/automation-trigger-id";
import { describeTrigger } from "../../../../../data/automation_i18n";
import { fullEntitiesContext } from "../../../../../data/context";
import {
fullEntitiesContext,
triggerDescriptionsContext,
} from "../../../../../data/context";
import type { EntityRegistryEntry } from "../../../../../data/entity/entity_registry";
import type { TriggerDescriptions } from "../../../../../data/trigger";
import { isTriggerList } from "../../../../../data/trigger";
import type { HomeAssistant } from "../../../../../types";
import "../../ha-automation-row-options";
import "../../ha-automation-row-threshold";
import { rowStyles } from "../../styles";
import { getTriggerTarget } from "../../target/get_trigger_target";
import "../../target/ha-automation-row-targets";
@customElement("ha-automation-condition-trigger")
export class HaTriggerCondition extends LitElement {
@@ -41,6 +50,10 @@ export class HaTriggerCondition extends LitElement {
@consume({ context: fullEntitiesContext, subscribe: true })
private _entityReg: EntityRegistryEntry[] = [];
@state()
@consume({ context: triggerDescriptionsContext, subscribe: true })
private _triggerDescriptions: TriggerDescriptions = {};
public static get defaultConfig(): TriggerCondition {
return {
condition: "trigger",
@@ -111,10 +124,11 @@ export class HaTriggerCondition extends LitElement {
}
></ha-trigger-icon>
</span>
<span slot="headline">
<span slot="headline" class="trigger-summary">
${capitalizeFirstLetter(
describeTrigger(option.trigger, this.hass, this._entityReg)
)}
${this._renderTriggerDetails(option.trigger)}
</span>
${
option.duplicate
@@ -151,6 +165,42 @@ export class HaTriggerCondition extends LitElement {
`;
}
private _renderTriggerDetails(trigger: TriggerIdOption["trigger"]) {
if (isTriggerList(trigger)) {
return nothing;
}
const description = this._triggerDescriptions[trigger.trigger];
const triggerTarget = getTriggerTarget(trigger, this._triggerDescriptions);
return html`
${
description
? html`<ha-automation-row-threshold
.config=${trigger}
.description=${description}
></ha-automation-row-threshold>
<ha-automation-row-options
.config=${trigger}
></ha-automation-row-options>`
: nothing
}
${
triggerTarget &&
(triggerTarget.target !== undefined || triggerTarget.targetRequired)
? html`<ha-automation-row-targets
size="s"
.target=${triggerTarget.target}
.targetRequired=${triggerTarget.targetRequired}
.selector=${
triggerTarget.targetSpec
? { target: triggerTarget.targetSpec }
: undefined
}
></ha-automation-row-targets>`
: nothing
}
`;
}
private _handleSelected = (ev: CustomEvent<number>) => {
ev.stopPropagation();
const list = ev.currentTarget as HaListSelectable;
@@ -222,6 +272,13 @@ export class HaTriggerCondition extends LitElement {
ha-list-item-option {
--ha-list-item-padding: var(--ha-space-1) var(--ha-space-2);
}
.trigger-summary {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--ha-space-1) var(--ha-space-2);
white-space: normal;
}
.trigger-row-leading {
display: inline-flex;
align-items: center;
@@ -0,0 +1,56 @@
import type { HassServiceTarget } from "home-assistant-js-websocket";
import type { Trigger } from "../../../../data/automation";
import type { TargetSelector } from "../../../../data/selector";
import type { TriggerDescriptions } from "../../../../data/trigger";
import { isTriggerList } from "../../../../data/trigger";
import { getDeviceTarget } from "./get_device_target";
import { getEntityTarget } from "./get_entity_target";
export interface TriggerTarget {
target?: HassServiceTarget;
/** The trigger type expects a target, so a missing one is shown as such. */
targetRequired: boolean;
targetSpec?: TargetSelector["target"];
}
/**
* Resolve what a trigger targets: the `target` of platform triggers, the
* entities of state and numeric state triggers, or the device of device triggers.
*/
export const getTriggerTarget = (
trigger: Trigger,
triggerDescriptions: TriggerDescriptions
): TriggerTarget | undefined => {
if (isTriggerList(trigger)) {
return undefined;
}
const description = triggerDescriptions[trigger.trigger];
if (description) {
const targetRequired = "target" in description;
return {
target:
targetRequired && "target" in trigger ? trigger.target : undefined,
targetRequired,
targetSpec: description.target,
};
}
if (trigger.trigger === "state" || trigger.trigger === "numeric_state") {
return {
target:
"entity_id" in trigger ? getEntityTarget(trigger.entity_id) : undefined,
targetRequired: true,
};
}
if (trigger.trigger === "device") {
return {
target:
"device_id" in trigger ? getDeviceTarget(trigger.device_id) : undefined,
targetRequired: false,
};
}
return undefined;
};
@@ -9,9 +9,15 @@ import "../../../../components/ha-tooltip";
import "../../../../components/ha-trigger-icon";
import type { TriggerCondition } from "../../../../data/automation";
import { describeTrigger } from "../../../../data/automation_i18n";
import { fullEntitiesContext } from "../../../../data/context";
import {
fullEntitiesContext,
triggerDescriptionsContext,
} from "../../../../data/context";
import type { EntityRegistryEntry } from "../../../../data/entity/entity_registry";
import type { TriggerDescriptions } from "../../../../data/trigger";
import type { HomeAssistant } from "../../../../types";
import { getTriggerTarget } from "../target/get_trigger_target";
import "../target/ha-automation-row-targets";
import {
automationTriggerContext,
type AutomationTriggerContext,
@@ -31,6 +37,10 @@ export class HaAutomationTriggerReferences extends LitElement {
@consume({ context: automationTriggerContext, subscribe: true })
private _triggers?: AutomationTriggerContext;
@state()
@consume({ context: triggerDescriptionsContext, subscribe: true })
private _triggerDescriptions: TriggerDescriptions = {};
protected render() {
const options = this._triggers?.options ?? [];
const showIndices = this._triggers?.showIndices ?? false;
@@ -51,8 +61,12 @@ export class HaAutomationTriggerReferences extends LitElement {
}
return [
selectedTriggers.map(
(option) => html`
selectedTriggers.map((option) => {
const triggerTarget = getTriggerTarget(
option.trigger,
this._triggerDescriptions
);
return html`
<span class="trigger-reference">
<span
id="trigger-index-badge-${option.index}"
@@ -84,9 +98,25 @@ export class HaAutomationTriggerReferences extends LitElement {
describeTrigger(option.trigger, this.hass, this._entityReg)
)}
</span>
${
triggerTarget &&
(triggerTarget.target !== undefined ||
triggerTarget.targetRequired)
? html`<ha-automation-row-targets
size="s"
.target=${triggerTarget.target}
.targetRequired=${triggerTarget.targetRequired}
.selector=${
triggerTarget.targetSpec
? { target: triggerTarget.targetSpec }
: undefined
}
></ha-automation-row-targets>`
: nothing
}
</span>
`
),
`;
}),
missingIds.map(
() => html`
<span class="trigger-reference missing">
@@ -113,6 +143,7 @@ export class HaAutomationTriggerReferences extends LitElement {
.trigger-reference {
display: inline-flex;
align-items: center;
flex-wrap: wrap;
gap: var(--ha-space-2);
min-width: 0;
max-width: 100%;
@@ -75,8 +75,7 @@ import "../ha-automation-editor-warning";
import "../ha-automation-row-options";
import "../ha-automation-row-threshold";
import { overflowStyles, rowStyles } from "../styles";
import { getDeviceTarget } from "../target/get_device_target";
import { getEntityTarget } from "../target/get_entity_target";
import { getTriggerTarget } from "../target/get_trigger_target";
import "../target/ha-automation-row-targets";
import {
automationTriggerContext,
@@ -226,23 +225,12 @@ export default class HaAutomationTriggerRow extends LitElement {
const yamlMode = this._yamlMode || !supported;
const descriptionHasTarget =
type === "platform" &&
"target" in
this.triggerDescriptions[(this.trigger as PlatformTrigger).trigger];
const hasEntityTarget = type === "state" || type === "numeric_state";
const target = this._getTarget(type, descriptionHasTarget, hasEntityTarget);
const targetRequired =
(descriptionHasTarget || hasEntityTarget) && !this._isNew;
const triggerTargetSpec =
type === "platform"
? this.triggerDescriptions[(this.trigger as PlatformTrigger).trigger]
?.target
: undefined;
const triggerTarget = this._getTriggerTarget(
this.trigger,
this.triggerDescriptions
);
const target = triggerTarget?.target;
const targetRequired = !!triggerTarget?.targetRequired && !this._isNew;
const noteTooltipText = truncateWithEllipsis(
(type !== "list" &&
@@ -321,7 +309,7 @@ export default class HaAutomationTriggerRow extends LitElement {
? this._renderTargets(
target,
targetRequired,
triggerTargetSpec,
triggerTarget?.targetSpec,
type !== "device"
)
: nothing
@@ -625,26 +613,7 @@ export default class HaAutomationTriggerRow extends LitElement {
`;
}
private _getEntityTarget = memoizeOne(getEntityTarget);
private _getDeviceTarget = memoizeOne(getDeviceTarget);
private _getTarget(
type: string,
descriptionHasTarget: boolean,
hasEntityTarget: boolean
): HassServiceTarget | undefined {
if (descriptionHasTarget && "target" in this.trigger) {
return this.trigger.target;
}
if (hasEntityTarget && "entity_id" in this.trigger) {
return this._getEntityTarget(this.trigger.entity_id);
}
if (type === "device" && "device_id" in this.trigger) {
return this._getDeviceTarget(this.trigger.device_id);
}
return undefined;
}
private _getTriggerTarget = memoizeOne(getTriggerTarget);
private _renderTargets = memoizeOne(
(