Keep targets when switching services (#18772)

This commit is contained in:
Bram Kragten 2023-11-28 14:42:40 +01:00 committed by GitHub
parent c1f76e0565
commit 05a22e3271
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 108 additions and 4 deletions

View File

@ -17,11 +17,14 @@ import {
IntegrationManifest,
} from "../data/integration";
import {
areaMeetsTargetSelector,
deviceMeetsTargetSelector,
entityMeetsTargetSelector,
expandAreaTarget,
expandDeviceTarget,
Selector,
} from "../data/selector";
import { ValueChangedEvent, HomeAssistant } from "../types";
import { HomeAssistant, ValueChangedEvent } from "../types";
import { documentationUrl } from "../util/documentation-url";
import "./ha-checkbox";
import "./ha-icon-button";
@ -546,8 +549,68 @@ export class HaServiceControl extends LitElement {
if (ev.detail.value === this._value?.service) {
return;
}
const newService = ev.detail.value || "";
let target: HassServiceTarget | undefined;
if (newService) {
const serviceData = this._getServiceInfo(newService, this.hass.services);
const currentTarget = this._value?.target;
if (currentTarget && serviceData?.target) {
const targetSelector = { target: { ...serviceData.target } };
let targetEntities =
ensureArray(
currentTarget.entity_id || this._value!.data?.entity_id
)?.slice() || [];
let targetDevices =
ensureArray(
currentTarget.device_id || this._value!.data?.device_id
)?.slice() || [];
let targetAreas =
ensureArray(
currentTarget.area_id || this._value!.data?.area_id
)?.slice() || [];
if (targetAreas.length) {
targetAreas = targetAreas.filter((area) =>
areaMeetsTargetSelector(
this.hass,
this.hass.entities,
this.hass.devices,
area,
targetSelector
)
);
}
if (targetDevices.length) {
targetDevices = targetDevices.filter((device) =>
deviceMeetsTargetSelector(
this.hass,
Object.values(this.hass.entities),
this.hass.devices[device],
targetSelector
)
);
}
if (targetEntities.length) {
targetEntities = targetEntities.filter((entity) =>
entityMeetsTargetSelector(this.hass.states[entity], targetSelector)
);
}
target = {
entity_id: targetEntities,
device_id: targetDevices,
area_id: targetAreas,
};
}
}
const value = {
service: newService,
target,
};
fireEvent(this, "value-changed", {
value: { service: ev.detail.value || "" },
value,
});
}

View File

@ -464,7 +464,48 @@ export const expandDeviceTarget = (
return { entities: newEntities };
};
const deviceMeetsTargetSelector = (
export const areaMeetsTargetSelector = (
hass: HomeAssistant,
entities: HomeAssistant["entities"],
devices: HomeAssistant["devices"],
areaId: string,
targetSelector: TargetSelector,
entitySources?: EntitySources
): boolean => {
const hasMatchingdevice = Object.values(devices).some((device) => {
if (
device.area_id === areaId &&
deviceMeetsTargetSelector(
hass,
Object.values(entities),
device,
targetSelector,
entitySources
)
) {
return true;
}
return false;
});
if (hasMatchingdevice) {
return true;
}
return Object.values(entities).some((entity) => {
if (
entity.area_id === areaId &&
entityMeetsTargetSelector(
hass.states[entity.entity_id],
targetSelector,
entitySources
)
) {
return true;
}
return false;
});
};
export const deviceMeetsTargetSelector = (
hass: HomeAssistant,
entityRegistry: EntityRegistryDisplayEntry[],
device: DeviceRegistryEntry,
@ -500,7 +541,7 @@ const deviceMeetsTargetSelector = (
return true;
};
const entityMeetsTargetSelector = (
export const entityMeetsTargetSelector = (
entity: HassEntity,
targetSelector: TargetSelector,
entitySources?: EntitySources