Allow device conditions to specify extra fields (#3973)

This commit is contained in:
Erik Montnemery 2019-10-11 13:16:54 +02:00 committed by Bram Kragten
parent 495f4aa19c
commit 78900e05ad
3 changed files with 95 additions and 6 deletions

View File

@ -39,6 +39,15 @@ export const fetchDeviceTriggers = (hass: HomeAssistant, deviceId: string) =>
device_id: deviceId,
});
export const fetchDeviceConditionCapabilities = (
hass: HomeAssistant,
condition: DeviceCondition
) =>
hass.callWS<DeviceCondition[]>({
type: "device_automation/condition/capabilities",
condition,
});
export const fetchDeviceTriggerCapabilities = (
hass: HomeAssistant,
trigger: DeviceTrigger

View File

@ -2,29 +2,49 @@ import { h, Component } from "preact";
import "../../../../components/device/ha-device-picker";
import "../../../../components/device/ha-device-condition-picker";
import "../../../../components/ha-form";
import {
fetchDeviceConditionCapabilities,
deviceAutomationsEqual,
} from "../../../../data/device_automation";
export default class DeviceCondition extends Component<any, any> {
private _origCondition;
constructor() {
super();
this.devicePicked = this.devicePicked.bind(this);
this.deviceConditionPicked = this.deviceConditionPicked.bind(this);
this.state = { device_id: undefined };
this._extraFieldsChanged = this._extraFieldsChanged.bind(this);
this.state = { device_id: undefined, capabilities: undefined };
}
public devicePicked(ev) {
this.setState({ device_id: ev.target.value });
this.setState({ ...this.state, device_id: ev.target.value });
}
public deviceConditionPicked(ev) {
const deviceCondition = ev.target.value;
this.props.onChange(this.props.index, deviceCondition);
let condition = ev.target.value;
if (
this._origCondition &&
deviceAutomationsEqual(this._origCondition, condition)
) {
condition = this._origCondition;
}
this.props.onChange(this.props.index, condition);
}
/* eslint-disable camelcase */
public render({ condition, hass }, { device_id }) {
public render({ condition, hass }, { device_id, capabilities }) {
if (device_id === undefined) {
device_id = condition.device_id;
}
const extraFieldsData =
capabilities && capabilities.extra_fields
? capabilities.extra_fields.map((item) => {
return { [item.name]: this.props.condition[item.name] };
})
: undefined;
return (
<div>
@ -41,9 +61,64 @@ export default class DeviceCondition extends Component<any, any> {
hass={hass}
label="Condition"
/>
{extraFieldsData && (
<ha-form
data={Object.assign({}, ...extraFieldsData)}
onData-changed={this._extraFieldsChanged}
schema={this.state.capabilities.extra_fields}
computeLabel={this._extraFieldsComputeLabelCallback(hass.localize)}
/>
)}
</div>
);
}
public componentDidMount() {
if (!this.state.capabilities) {
this._getCapabilities();
}
if (this.props.condition) {
this._origCondition = this.props.condition;
}
}
public componentDidUpdate(prevProps) {
if (prevProps.condition !== this.props.condition) {
this._getCapabilities();
}
}
private async _getCapabilities() {
const condition = this.props.condition;
const capabilities = condition.domain
? await fetchDeviceConditionCapabilities(this.props.hass, condition)
: null;
this.setState({ ...this.state, capabilities });
}
private _extraFieldsChanged(ev) {
if (!ev.detail.path) {
return;
}
const item = ev.detail.path.replace("data.", "");
const value = ev.detail.value || undefined;
this.props.onChange(this.props.index, {
...this.props.condition,
[item]: value,
});
}
private _extraFieldsComputeLabelCallback(localize) {
// Returns a callback for ha-form to calculate labels per schema object
return (schema) =>
localize(
`ui.panel.config.automation.editor.condition.type.device.extra_fields.${
schema.name
}`
) || schema.name;
}
}
(DeviceCondition as any).defaultConfig = {

View File

@ -830,7 +830,12 @@
"label": "And"
},
"device": {
"label": "Device"
"label": "Device",
"extra_fields": {
"above": "Above",
"below": "Below",
"for": "Duration"
}
},
"numeric_state": {
"label": "[%key:ui::panel::config::automation::editor::triggers::type::numeric_state::label%]",