mirror of
https://github.com/home-assistant/frontend.git
synced 2026-04-02 00:27:49 +01:00
Hide behavior selector for single target in triggers and conditions (labs) (#30145)
This commit is contained in:
@@ -47,13 +47,34 @@ export interface ExtractFromTargetResultReferenced {
|
||||
|
||||
export const extractFromTarget = async (
|
||||
hass: HomeAssistant,
|
||||
target: HassServiceTarget
|
||||
target: HassServiceTarget,
|
||||
expandGroup = false
|
||||
) =>
|
||||
hass.callWS<ExtractFromTargetResult>({
|
||||
type: "extract_from_target",
|
||||
target,
|
||||
expand_group: expandGroup,
|
||||
});
|
||||
|
||||
export const getResolvedTargetEntityCount = async (
|
||||
hass: HomeAssistant,
|
||||
target?: HassServiceTarget
|
||||
): Promise<number | undefined> => {
|
||||
if (!target) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
try {
|
||||
return (await extractFromTarget(hass, target, true)).referenced_entities
|
||||
.length;
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Error resolving target entity count", err);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const getTriggersForTarget = async (
|
||||
callWS: HomeAssistant["callWS"],
|
||||
target: HassServiceTarget,
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
import type { IntegrationManifest } from "../../../../../data/integration";
|
||||
import { fetchIntegrationManifest } from "../../../../../data/integration";
|
||||
import type { TargetSelector } from "../../../../../data/selector";
|
||||
import { getResolvedTargetEntityCount } from "../../../../../data/target";
|
||||
import type { HomeAssistant } from "../../../../../types";
|
||||
import { documentationUrl } from "../../../../../util/documentation-url";
|
||||
|
||||
@@ -38,6 +39,8 @@ export class HaPlatformCondition extends LitElement {
|
||||
|
||||
@state() private _manifest?: IntegrationManifest;
|
||||
|
||||
@state() private _resolvedTargetEntityCount?: number;
|
||||
|
||||
public static get defaultConfig(): PlatformCondition {
|
||||
return { condition: "" };
|
||||
}
|
||||
@@ -107,6 +110,10 @@ export class HaPlatformCondition extends LitElement {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (oldValue?.target !== this.condition?.target) {
|
||||
this._updateResolvedTargetEntityCount(this.condition?.target);
|
||||
}
|
||||
}
|
||||
|
||||
protected render() {
|
||||
@@ -214,51 +221,57 @@ export class HaPlatformCondition extends LitElement {
|
||||
|
||||
const showOptional = showOptionalToggle(dataField);
|
||||
|
||||
return dataField.selector
|
||||
? html`<ha-settings-row narrow>
|
||||
${!showOptional
|
||||
? hasOptional
|
||||
? html`<div slot="prefix" class="checkbox-spacer"></div>`
|
||||
: nothing
|
||||
: html`<ha-checkbox
|
||||
.key=${fieldName}
|
||||
.checked=${this._checkedKeys.has(fieldName) ||
|
||||
(this.condition?.options &&
|
||||
this.condition.options[fieldName] !== undefined)}
|
||||
.disabled=${this.disabled}
|
||||
@change=${this._checkboxChanged}
|
||||
slot="prefix"
|
||||
></ha-checkbox>`}
|
||||
<span slot="heading"
|
||||
>${this.hass.localize(
|
||||
`component.${domain}.conditions.${conditionName}.fields.${fieldName}.name`
|
||||
) || conditionName}</span
|
||||
>
|
||||
<span slot="description"
|
||||
>${this.hass.localize(
|
||||
`component.${domain}.conditions.${conditionName}.fields.${fieldName}.description`
|
||||
)}</span
|
||||
>
|
||||
<ha-selector
|
||||
.disabled=${this.disabled ||
|
||||
(showOptional &&
|
||||
!this._checkedKeys.has(fieldName) &&
|
||||
(!this.condition?.options ||
|
||||
this.condition.options[fieldName] === undefined))}
|
||||
.hass=${this.hass}
|
||||
.selector=${selector}
|
||||
.context=${this._generateContext(dataField)}
|
||||
if (!dataField.selector) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
if (fieldName === "behavior" && this._resolvedTargetEntityCount === 1) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
return html`<ha-settings-row narrow>
|
||||
${!showOptional
|
||||
? hasOptional
|
||||
? html`<div slot="prefix" class="checkbox-spacer"></div>`
|
||||
: nothing
|
||||
: html`<ha-checkbox
|
||||
.key=${fieldName}
|
||||
@value-changed=${this._dataChanged}
|
||||
.value=${this.condition?.options
|
||||
? this.condition.options[fieldName]
|
||||
: undefined}
|
||||
.placeholder=${dataField.default}
|
||||
.localizeValue=${this._localizeValueCallback}
|
||||
.required=${dataField.required}
|
||||
></ha-selector>
|
||||
</ha-settings-row>`
|
||||
: nothing;
|
||||
.checked=${this._checkedKeys.has(fieldName) ||
|
||||
(this.condition?.options &&
|
||||
this.condition.options[fieldName] !== undefined)}
|
||||
.disabled=${this.disabled}
|
||||
@change=${this._checkboxChanged}
|
||||
slot="prefix"
|
||||
></ha-checkbox>`}
|
||||
<span slot="heading"
|
||||
>${this.hass.localize(
|
||||
`component.${domain}.conditions.${conditionName}.fields.${fieldName}.name`
|
||||
) || conditionName}</span
|
||||
>
|
||||
<span slot="description"
|
||||
>${this.hass.localize(
|
||||
`component.${domain}.conditions.${conditionName}.fields.${fieldName}.description`
|
||||
)}</span
|
||||
>
|
||||
<ha-selector
|
||||
.disabled=${this.disabled ||
|
||||
(showOptional &&
|
||||
!this._checkedKeys.has(fieldName) &&
|
||||
(!this.condition?.options ||
|
||||
this.condition.options[fieldName] === undefined))}
|
||||
.hass=${this.hass}
|
||||
.selector=${selector}
|
||||
.context=${this._generateContext(dataField)}
|
||||
.key=${fieldName}
|
||||
@value-changed=${this._dataChanged}
|
||||
.value=${this.condition?.options
|
||||
? this.condition.options[fieldName]
|
||||
: undefined}
|
||||
.placeholder=${dataField.default}
|
||||
.localizeValue=${this._localizeValueCallback}
|
||||
.required=${dataField.required}
|
||||
></ha-selector>
|
||||
</ha-settings-row>`;
|
||||
};
|
||||
|
||||
private _generateContext(
|
||||
@@ -395,6 +408,47 @@ export class HaPlatformCondition extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private _resolveTargetEntityCount = memoizeOne(
|
||||
async (target: PlatformCondition["target"]) =>
|
||||
getResolvedTargetEntityCount(this.hass, target)
|
||||
);
|
||||
|
||||
private async _updateResolvedTargetEntityCount(
|
||||
target: PlatformCondition["target"]
|
||||
) {
|
||||
this._resolvedTargetEntityCount =
|
||||
await this._resolveTargetEntityCount(target);
|
||||
|
||||
if (
|
||||
this._resolvedTargetEntityCount === 1 &&
|
||||
this.condition.options?.behavior !== undefined
|
||||
) {
|
||||
const options = { ...this.condition.options };
|
||||
delete options.behavior;
|
||||
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
...this.condition,
|
||||
options,
|
||||
},
|
||||
});
|
||||
} else if (
|
||||
this._resolvedTargetEntityCount !== undefined &&
|
||||
this._resolvedTargetEntityCount > 1 &&
|
||||
this.condition.options?.behavior === undefined
|
||||
) {
|
||||
const behaviorDefault = this.description?.fields?.behavior?.default;
|
||||
if (behaviorDefault !== undefined) {
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
...this.condition,
|
||||
options: { ...this.condition.options, behavior: behaviorDefault },
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
|
||||
@@ -11,6 +11,7 @@ import type { PlatformTrigger } from "../../../../../data/automation";
|
||||
import type { IntegrationManifest } from "../../../../../data/integration";
|
||||
import { fetchIntegrationManifest } from "../../../../../data/integration";
|
||||
import type { TargetSelector } from "../../../../../data/selector";
|
||||
import { getResolvedTargetEntityCount } from "../../../../../data/target";
|
||||
import {
|
||||
getTriggerDomain,
|
||||
getTriggerObjectId,
|
||||
@@ -48,6 +49,8 @@ export class HaPlatformTrigger extends LitElement {
|
||||
|
||||
@state() private _manifest?: IntegrationManifest;
|
||||
|
||||
@state() private _resolvedTargetEntityCount?: number;
|
||||
|
||||
public static get defaultConfig(): PlatformTrigger {
|
||||
return { trigger: "" };
|
||||
}
|
||||
@@ -143,6 +146,10 @@ export class HaPlatformTrigger extends LitElement {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (oldValue?.target !== this.trigger?.target) {
|
||||
this._updateResolvedTargetEntityCount(this.trigger?.target);
|
||||
}
|
||||
}
|
||||
|
||||
protected render() {
|
||||
@@ -250,51 +257,58 @@ export class HaPlatformTrigger extends LitElement {
|
||||
|
||||
const showOptional = showOptionalToggle(dataField);
|
||||
|
||||
return dataField.selector
|
||||
? html`<ha-settings-row narrow>
|
||||
${!showOptional
|
||||
? hasOptional
|
||||
? html`<div slot="prefix" class="checkbox-spacer"></div>`
|
||||
: nothing
|
||||
: html`<ha-checkbox
|
||||
.key=${fieldName}
|
||||
.checked=${this._checkedKeys.has(fieldName) ||
|
||||
(this.trigger?.options &&
|
||||
this.trigger.options[fieldName] !== undefined)}
|
||||
.disabled=${this.disabled}
|
||||
@change=${this._checkboxChanged}
|
||||
slot="prefix"
|
||||
></ha-checkbox>`}
|
||||
<span slot="heading"
|
||||
>${this.hass.localize(
|
||||
`component.${domain}.triggers.${triggerName}.fields.${fieldName}.name`
|
||||
) || triggerName}</span
|
||||
>
|
||||
<span slot="description"
|
||||
>${this.hass.localize(
|
||||
`component.${domain}.triggers.${triggerName}.fields.${fieldName}.description`
|
||||
)}</span
|
||||
>
|
||||
<ha-selector
|
||||
.disabled=${this.disabled ||
|
||||
(showOptional &&
|
||||
!this._checkedKeys.has(fieldName) &&
|
||||
(!this.trigger?.options ||
|
||||
this.trigger.options[fieldName] === undefined))}
|
||||
.hass=${this.hass}
|
||||
.selector=${selector}
|
||||
.context=${this._generateContext(dataField)}
|
||||
if (!dataField.selector) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
// Hide behavior when the target is a single direct entity.
|
||||
if (fieldName === "behavior" && this._resolvedTargetEntityCount === 1) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
return html`<ha-settings-row narrow>
|
||||
${!showOptional
|
||||
? hasOptional
|
||||
? html`<div slot="prefix" class="checkbox-spacer"></div>`
|
||||
: nothing
|
||||
: html`<ha-checkbox
|
||||
.key=${fieldName}
|
||||
@value-changed=${this._dataChanged}
|
||||
.value=${this.trigger?.options
|
||||
? this.trigger.options[fieldName]
|
||||
: undefined}
|
||||
.placeholder=${dataField.default}
|
||||
.localizeValue=${this._localizeValueCallback}
|
||||
.required=${dataField.required}
|
||||
></ha-selector>
|
||||
</ha-settings-row>`
|
||||
: nothing;
|
||||
.checked=${this._checkedKeys.has(fieldName) ||
|
||||
(this.trigger?.options &&
|
||||
this.trigger.options[fieldName] !== undefined)}
|
||||
.disabled=${this.disabled}
|
||||
@change=${this._checkboxChanged}
|
||||
slot="prefix"
|
||||
></ha-checkbox>`}
|
||||
<span slot="heading"
|
||||
>${this.hass.localize(
|
||||
`component.${domain}.triggers.${triggerName}.fields.${fieldName}.name`
|
||||
) || triggerName}</span
|
||||
>
|
||||
<span slot="description"
|
||||
>${this.hass.localize(
|
||||
`component.${domain}.triggers.${triggerName}.fields.${fieldName}.description`
|
||||
)}</span
|
||||
>
|
||||
<ha-selector
|
||||
.disabled=${this.disabled ||
|
||||
(showOptional &&
|
||||
!this._checkedKeys.has(fieldName) &&
|
||||
(!this.trigger?.options ||
|
||||
this.trigger.options[fieldName] === undefined))}
|
||||
.hass=${this.hass}
|
||||
.selector=${selector}
|
||||
.context=${this._generateContext(dataField)}
|
||||
.key=${fieldName}
|
||||
@value-changed=${this._dataChanged}
|
||||
.value=${this.trigger?.options
|
||||
? this.trigger.options[fieldName]
|
||||
: undefined}
|
||||
.placeholder=${dataField.default}
|
||||
.localizeValue=${this._localizeValueCallback}
|
||||
.required=${dataField.required}
|
||||
></ha-selector>
|
||||
</ha-settings-row>`;
|
||||
};
|
||||
|
||||
private _generateContext(
|
||||
@@ -431,6 +445,47 @@ export class HaPlatformTrigger extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private _resolveTargetEntityCount = memoizeOne(
|
||||
async (target: PlatformTrigger["target"]) =>
|
||||
getResolvedTargetEntityCount(this.hass, target)
|
||||
);
|
||||
|
||||
private async _updateResolvedTargetEntityCount(
|
||||
target: PlatformTrigger["target"]
|
||||
) {
|
||||
this._resolvedTargetEntityCount =
|
||||
await this._resolveTargetEntityCount(target);
|
||||
|
||||
if (
|
||||
this._resolvedTargetEntityCount === 1 &&
|
||||
this.trigger.options?.behavior !== undefined
|
||||
) {
|
||||
const options = { ...this.trigger.options };
|
||||
delete options.behavior;
|
||||
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
...this.trigger,
|
||||
options,
|
||||
},
|
||||
});
|
||||
} else if (
|
||||
this._resolvedTargetEntityCount !== undefined &&
|
||||
this._resolvedTargetEntityCount > 1 &&
|
||||
this.trigger.options?.behavior === undefined
|
||||
) {
|
||||
const behaviorDefault = this.description?.fields?.behavior?.default;
|
||||
if (behaviorDefault !== undefined) {
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
...this.trigger,
|
||||
options: { ...this.trigger.options, behavior: behaviorDefault },
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
|
||||
Reference in New Issue
Block a user