diff --git a/src/data/device_automation.ts b/src/data/device_automation.ts index 0a308fcdbc..58be904d62 100644 --- a/src/data/device_automation.ts +++ b/src/data/device_automation.ts @@ -39,6 +39,15 @@ export const fetchDeviceTriggers = (hass: HomeAssistant, deviceId: string) => device_id: deviceId, }); +export const fetchDeviceActionCapabilities = ( + hass: HomeAssistant, + action: DeviceAction +) => + hass.callWS({ + type: "device_automation/action/capabilities", + action, + }); + export const fetchDeviceConditionCapabilities = ( hass: HomeAssistant, condition: DeviceCondition @@ -57,7 +66,7 @@ export const fetchDeviceTriggerCapabilities = ( trigger, }); -const whitelist = ["above", "below", "for"]; +const whitelist = ["above", "below", "code", "for"]; export const deviceAutomationsEqual = ( a: DeviceAutomation, diff --git a/src/panels/config/js/condition/device.tsx b/src/panels/config/js/condition/device.tsx index 6c3206c4b6..1fd9a8385e 100644 --- a/src/panels/config/js/condition/device.tsx +++ b/src/panels/config/js/condition/device.tsx @@ -83,7 +83,7 @@ export default class DeviceCondition extends Component { } public componentDidUpdate(prevProps) { - if (prevProps.condition !== this.props.condition) { + if (!deviceAutomationsEqual(prevProps.condition, this.props.condition)) { this._getCapabilities(); } } diff --git a/src/panels/config/js/script/device.tsx b/src/panels/config/js/script/device.tsx index 7689f09aa3..344ff96253 100644 --- a/src/panels/config/js/script/device.tsx +++ b/src/panels/config/js/script/device.tsx @@ -2,8 +2,14 @@ import { h, Component } from "preact"; import "../../../../components/device/ha-device-picker"; import "../../../../components/device/ha-device-action-picker"; -import { HomeAssistant } from "../../../../types"; +import "../../../../components/ha-form"; + +import { + fetchDeviceActionCapabilities, + deviceAutomationsEqual, +} from "../../../../data/device_automation"; import { DeviceAction } from "../../../../data/script"; +import { HomeAssistant } from "../../../../types"; export default class DeviceActionEditor extends Component< { @@ -14,6 +20,7 @@ export default class DeviceActionEditor extends Component< }, { device_id: string | undefined; + capabilities: any | undefined; } > { public static defaultConfig: DeviceAction = { @@ -22,16 +29,26 @@ export default class DeviceActionEditor extends Component< entity_id: "", }; + private _origAction; + constructor() { super(); this.devicePicked = this.devicePicked.bind(this); this.deviceActionPicked = this.deviceActionPicked.bind(this); - this.state = { device_id: undefined }; + this._extraFieldsChanged = this._extraFieldsChanged.bind(this); + this.state = { device_id: undefined, capabilities: undefined }; } public render() { const { action, hass } = this.props; const deviceId = this.state.device_id || action.device_id; + const capabilities = this.state.capabilities; + const extraFieldsData = + capabilities && capabilities.extra_fields + ? capabilities.extra_fields.map((item) => { + return { [item.name]: this.props.action[item.name] }; + }) + : undefined; return (
@@ -48,16 +65,77 @@ export default class DeviceActionEditor extends Component< hass={hass} label="Action" /> + {extraFieldsData && ( + + )}
); } + public componentDidMount() { + if (!this.state.capabilities) { + this._getCapabilities(); + } + if (this.props.action) { + this._origAction = this.props.action; + } + } + + public componentDidUpdate(prevProps) { + if (!deviceAutomationsEqual(prevProps.action, this.props.action)) { + this._getCapabilities(); + } + } + private devicePicked(ev) { - this.setState({ device_id: ev.target.value }); + this.setState({ ...this.state, device_id: ev.target.value }); } private deviceActionPicked(ev) { - const deviceAction = { ...ev.target.value }; + let deviceAction = ev.target.value; + if ( + this._origAction && + deviceAutomationsEqual(this._origAction, deviceAction) + ) { + deviceAction = this._origAction; + } this.props.onChange(this.props.index, deviceAction); } + + private async _getCapabilities() { + const action = this.props.action; + + const capabilities = action.domain + ? await fetchDeviceActionCapabilities(this.props.hass, action) + : 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.action, + [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.actions.type.device_id.extra_fields.${ + schema.name + }` + ) || schema.name; + } } diff --git a/src/panels/config/js/trigger/device.tsx b/src/panels/config/js/trigger/device.tsx index 982fe55a01..a9dd929ac1 100644 --- a/src/panels/config/js/trigger/device.tsx +++ b/src/panels/config/js/trigger/device.tsx @@ -84,7 +84,7 @@ export default class DeviceTrigger extends Component { } public componentDidUpdate(prevProps) { - if (prevProps.trigger !== this.props.trigger) { + if (!deviceAutomationsEqual(prevProps.trigger, this.props.trigger)) { this._getCapabilities(); } } diff --git a/src/translations/en.json b/src/translations/en.json index abd73af154..a7f99e6645 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -908,7 +908,10 @@ "service_data": "[%key:ui::panel::config::automation::editor::actions::type::service::service_data%]" }, "device_id": { - "label": "Device" + "label": "Device", + "extra_fields": { + "code": "Code" + } }, "scene": { "label": "Activate scene"