mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-29 20:26:39 +00:00
Add support for multiple entities and target for state selector
This commit is contained in:
parent
039ef18d8c
commit
77afb9ac1a
@ -2,6 +2,7 @@ import type { HassEntity } from "home-assistant-js-websocket";
|
|||||||
import type { PropertyValues } from "lit";
|
import type { PropertyValues } from "lit";
|
||||||
import { LitElement, html, nothing } from "lit";
|
import { LitElement, html, nothing } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
|
import { ensureArray } from "../../common/array/ensure-array";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import { getStates } from "../../common/entity/get_states";
|
import { getStates } from "../../common/entity/get_states";
|
||||||
import type { HomeAssistant, ValueChangedEvent } from "../../types";
|
import type { HomeAssistant, ValueChangedEvent } from "../../types";
|
||||||
@ -14,7 +15,7 @@ export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;
|
|||||||
class HaEntityStatePicker extends LitElement {
|
class HaEntityStatePicker extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public entityId?: string;
|
@property({ attribute: false }) public entityId?: string | string[];
|
||||||
|
|
||||||
@property() public attribute?: string;
|
@property() public attribute?: string;
|
||||||
|
|
||||||
@ -30,6 +31,9 @@ class HaEntityStatePicker extends LitElement {
|
|||||||
@property({ type: Boolean, attribute: "allow-custom-value" })
|
@property({ type: Boolean, attribute: "allow-custom-value" })
|
||||||
public allowCustomValue;
|
public allowCustomValue;
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
public excludeStates?: string[];
|
||||||
|
|
||||||
@property() public label?: string;
|
@property() public label?: string;
|
||||||
|
|
||||||
@property() public value?: string;
|
@property() public value?: string;
|
||||||
@ -51,23 +55,37 @@ class HaEntityStatePicker extends LitElement {
|
|||||||
changedProps.has("attribute") ||
|
changedProps.has("attribute") ||
|
||||||
changedProps.has("extraOptions")
|
changedProps.has("extraOptions")
|
||||||
) {
|
) {
|
||||||
const stateObj = this.entityId
|
const entityIds = this.entityId ? ensureArray(this.entityId) : [];
|
||||||
? this.hass.states[this.entityId]
|
const stateOptions: { value: string; label: string }[] = [];
|
||||||
: undefined;
|
const statesSet = new Set<string>();
|
||||||
(this._comboBox as any).items = [
|
|
||||||
...(this.extraOptions ?? []),
|
for (const entityId of entityIds) {
|
||||||
...(this.entityId && stateObj
|
const stateObj = this.hass.states[entityId];
|
||||||
? getStates(this.hass, stateObj, this.attribute).map((key) => ({
|
const states = getStates(this.hass, stateObj, this.attribute).filter(
|
||||||
value: key,
|
(s) => !this.excludeStates || !this.excludeStates.includes(s)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const s of states) {
|
||||||
|
if (!statesSet.has(s)) {
|
||||||
|
statesSet.add(s);
|
||||||
|
const options = {
|
||||||
|
value: s,
|
||||||
label: !this.attribute
|
label: !this.attribute
|
||||||
? this.hass.formatEntityState(stateObj, key)
|
? this.hass.formatEntityState(stateObj, s)
|
||||||
: this.hass.formatEntityAttributeValue(
|
: this.hass.formatEntityAttributeValue(
|
||||||
stateObj,
|
stateObj,
|
||||||
this.attribute,
|
this.attribute,
|
||||||
key
|
s
|
||||||
),
|
),
|
||||||
}))
|
};
|
||||||
: []),
|
stateOptions.push(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(this._comboBox as any).filteredItems = [
|
||||||
|
...(this.extraOptions ?? []),
|
||||||
|
...stateOptions,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ export class HaSelectorState extends SubscribeMixin(LitElement) {
|
|||||||
|
|
||||||
@property({ attribute: false }) public context?: {
|
@property({ attribute: false }) public context?: {
|
||||||
filter_attribute?: string;
|
filter_attribute?: string;
|
||||||
filter_entity?: string;
|
filter_entity?: string | string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
@ -41,6 +41,7 @@ export class HaSelectorState extends SubscribeMixin(LitElement) {
|
|||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
allow-custom-value
|
allow-custom-value
|
||||||
|
.excludeStates=${this.selector.state?.exclude_states}
|
||||||
></ha-entity-state-picker>
|
></ha-entity-state-picker>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -627,7 +627,7 @@ export class HaServiceControl extends LitElement {
|
|||||||
const fieldDataHasTemplate =
|
const fieldDataHasTemplate =
|
||||||
this._value?.data && hasTemplate(this._value.data[dataField.key]);
|
this._value?.data && hasTemplate(this._value.data[dataField.key]);
|
||||||
|
|
||||||
const selector =
|
let selector =
|
||||||
fieldDataHasTemplate &&
|
fieldDataHasTemplate &&
|
||||||
typeof this._value!.data![dataField.key] === "string"
|
typeof this._value!.data![dataField.key] === "string"
|
||||||
? { template: null }
|
? { template: null }
|
||||||
@ -637,6 +637,16 @@ export class HaServiceControl extends LitElement {
|
|||||||
: (this._stickySelector[dataField.key] ??
|
: (this._stickySelector[dataField.key] ??
|
||||||
dataField?.selector ?? { text: null });
|
dataField?.selector ?? { text: null });
|
||||||
|
|
||||||
|
if ("state" in selector) {
|
||||||
|
selector = {
|
||||||
|
...selector,
|
||||||
|
state: {
|
||||||
|
...selector.state,
|
||||||
|
entity_id: targetEntities || undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (fieldDataHasTemplate) {
|
if (fieldDataHasTemplate) {
|
||||||
// Hold this selector type until the field is cleared
|
// Hold this selector type until the field is cleared
|
||||||
this._stickySelector[dataField.key] = selector;
|
this._stickySelector[dataField.key] = selector;
|
||||||
|
@ -393,8 +393,9 @@ export interface SelectorSelector {
|
|||||||
export interface StateSelector {
|
export interface StateSelector {
|
||||||
state: {
|
state: {
|
||||||
extra_options?: { label: string; value: any }[];
|
extra_options?: { label: string; value: any }[];
|
||||||
entity_id?: string;
|
entity_id?: string | string[];
|
||||||
attribute?: string;
|
attribute?: string;
|
||||||
|
exclude_states?: string[];
|
||||||
} | null;
|
} | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,10 @@ import { baseTriggerStruct, forDictStruct } from "../../structs";
|
|||||||
import type { TriggerElement } from "../ha-automation-trigger-row";
|
import type { TriggerElement } from "../ha-automation-trigger-row";
|
||||||
import "../../../../../components/ha-form/ha-form";
|
import "../../../../../components/ha-form/ha-form";
|
||||||
import { createDurationData } from "../../../../../common/datetime/create_duration_data";
|
import { createDurationData } from "../../../../../common/datetime/create_duration_data";
|
||||||
import type { SchemaUnion } from "../../../../../components/ha-form/types";
|
import type {
|
||||||
|
HaFormSchema,
|
||||||
|
SchemaUnion,
|
||||||
|
} from "../../../../../components/ha-form/types";
|
||||||
|
|
||||||
const stateTriggerStruct = assign(
|
const stateTriggerStruct = assign(
|
||||||
baseTriggerStruct,
|
baseTriggerStruct,
|
||||||
@ -121,6 +124,9 @@ export class HaStateTrigger extends LitElement implements TriggerElement {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "from",
|
name: "from",
|
||||||
|
context: {
|
||||||
|
filter_entity: "entity_id",
|
||||||
|
},
|
||||||
selector: {
|
selector: {
|
||||||
state: {
|
state: {
|
||||||
extra_options: (attribute
|
extra_options: (attribute
|
||||||
@ -133,13 +139,15 @@ export class HaStateTrigger extends LitElement implements TriggerElement {
|
|||||||
value: ANY_STATE_VALUE,
|
value: ANY_STATE_VALUE,
|
||||||
},
|
},
|
||||||
]) as any,
|
]) as any,
|
||||||
entity_id: entityId ? entityId[0] : undefined,
|
|
||||||
attribute: attribute,
|
attribute: attribute,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "to",
|
name: "to",
|
||||||
|
context: {
|
||||||
|
filter_entity: "entity_id",
|
||||||
|
},
|
||||||
selector: {
|
selector: {
|
||||||
state: {
|
state: {
|
||||||
extra_options: (attribute
|
extra_options: (attribute
|
||||||
@ -152,13 +160,12 @@ export class HaStateTrigger extends LitElement implements TriggerElement {
|
|||||||
value: ANY_STATE_VALUE,
|
value: ANY_STATE_VALUE,
|
||||||
},
|
},
|
||||||
]) as any,
|
]) as any,
|
||||||
entity_id: entityId ? entityId[0] : undefined,
|
|
||||||
attribute: attribute,
|
attribute: attribute,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ name: "for", selector: { duration: {} } },
|
{ name: "for", selector: { duration: {} } },
|
||||||
] as const
|
] as const satisfies HaFormSchema[]
|
||||||
);
|
);
|
||||||
|
|
||||||
public shouldUpdate(changedProperties: PropertyValues) {
|
public shouldUpdate(changedProperties: PropertyValues) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user