From 5448cbf1c5534628de3a1135f36cd13647b2a074 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 10 Sep 2019 03:01:58 +0800 Subject: [PATCH] Add device actions to automation editor. (#3637) * Add device actions to automation editor. * Copy automation on selection * Fix types * Remove device from device action schema --- .../device/ha-device-action-picker.ts | 32 ++++++++++ src/data/device_automation.ts | 27 ++++++++ src/data/script.ts | 6 ++ src/panels/config/js/preact-types.ts | 1 + src/panels/config/js/script/action_edit.tsx | 2 + src/panels/config/js/script/device.tsx | 63 +++++++++++++++++++ src/panels/config/js/trigger/device.tsx | 1 - src/translations/en.json | 3 + 8 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 src/components/device/ha-device-action-picker.ts create mode 100644 src/panels/config/js/script/device.tsx diff --git a/src/components/device/ha-device-action-picker.ts b/src/components/device/ha-device-action-picker.ts new file mode 100644 index 0000000000..a97957a8a7 --- /dev/null +++ b/src/components/device/ha-device-action-picker.ts @@ -0,0 +1,32 @@ +import { customElement } from "lit-element"; +import { + DeviceAction, + fetchDeviceActions, + localizeDeviceAutomationAction, +} from "../../data/device_automation"; +import "../../components/ha-paper-dropdown-menu"; +import { HaDeviceAutomationPicker } from "./ha-device-automation-picker"; + +@customElement("ha-device-action-picker") +class HaDeviceActionPicker extends HaDeviceAutomationPicker { + protected NO_AUTOMATION_TEXT = "No actions"; + protected UNKNOWN_AUTOMATION_TEXT = "Unknown action"; + + constructor() { + super( + localizeDeviceAutomationAction, + fetchDeviceActions, + (deviceId?: string) => ({ + device_id: deviceId || "", + domain: "", + entity_id: "", + }) + ); + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-device-action-picker": HaDeviceActionPicker; + } +} diff --git a/src/data/device_automation.ts b/src/data/device_automation.ts index b764f4b47b..0ff5581771 100644 --- a/src/data/device_automation.ts +++ b/src/data/device_automation.ts @@ -10,6 +10,9 @@ export interface DeviceAutomation { event?: string; } +// tslint:disable-next-line: no-empty-interface +export interface DeviceAction extends DeviceAutomation {} + export interface DeviceCondition extends DeviceAutomation { condition: string; } @@ -18,6 +21,12 @@ export interface DeviceTrigger extends DeviceAutomation { platform: string; } +export const fetchDeviceActions = (hass: HomeAssistant, deviceId: string) => + hass.callWS({ + type: "device_automation/action/list", + device_id: deviceId, + }); + export const fetchDeviceConditions = (hass: HomeAssistant, deviceId: string) => hass.callWS({ type: "device_automation/condition/list", @@ -52,6 +61,24 @@ export const deviceAutomationsEqual = ( return true; }; +export const localizeDeviceAutomationAction = ( + hass: HomeAssistant, + action: DeviceAction +) => { + const state = action.entity_id ? hass.states[action.entity_id] : undefined; + return hass.localize( + `component.${action.domain}.device_automation.action_type.${action.type}`, + "entity_name", + state ? compute_state_name(state) : "", + "subtype", + hass.localize( + `component.${action.domain}.device_automation.action_subtype.${ + action.subtype + }` + ) + ); +}; + export const localizeDeviceAutomationCondition = ( hass: HomeAssistant, condition: DeviceCondition diff --git a/src/data/script.ts b/src/data/script.ts index a86a62a153..4cf4490bef 100644 --- a/src/data/script.ts +++ b/src/data/script.ts @@ -7,6 +7,12 @@ export interface EventAction { event_data_template?: { [key: string]: any }; } +export interface DeviceAction { + device_id: string; + domain: string; + entity_id: string; +} + export const triggerScript = ( hass: HomeAssistant, entityId: string, diff --git a/src/panels/config/js/preact-types.ts b/src/panels/config/js/preact-types.ts index d8442845af..9873fa3dd1 100644 --- a/src/panels/config/js/preact-types.ts +++ b/src/panels/config/js/preact-types.ts @@ -23,6 +23,7 @@ declare global { "ha-service-picker": any; "mwc-button": any; "ha-device-trigger-picker": any; + "ha-device-action-picker": any; } } } diff --git a/src/panels/config/js/script/action_edit.tsx b/src/panels/config/js/script/action_edit.tsx index a4f0a02d32..078edbddea 100644 --- a/src/panels/config/js/script/action_edit.tsx +++ b/src/panels/config/js/script/action_edit.tsx @@ -6,6 +6,7 @@ import "@polymer/paper-item/paper-item"; import CallServiceAction from "./call_service"; import ConditionAction from "./condition"; import DelayAction from "./delay"; +import DeviceAction from "./device"; import EventAction from "./event"; import WaitAction from "./wait"; @@ -15,6 +16,7 @@ const TYPES = { wait_template: WaitAction, condition: ConditionAction, event: EventAction, + device_id: DeviceAction, }; const OPTIONS = Object.keys(TYPES).sort(); diff --git a/src/panels/config/js/script/device.tsx b/src/panels/config/js/script/device.tsx new file mode 100644 index 0000000000..7689f09aa3 --- /dev/null +++ b/src/panels/config/js/script/device.tsx @@ -0,0 +1,63 @@ +import { h, Component } from "preact"; + +import "../../../../components/device/ha-device-picker"; +import "../../../../components/device/ha-device-action-picker"; +import { HomeAssistant } from "../../../../types"; +import { DeviceAction } from "../../../../data/script"; + +export default class DeviceActionEditor extends Component< + { + index: number; + action: DeviceAction; + hass: HomeAssistant; + onChange(index: number, action: DeviceAction); + }, + { + device_id: string | undefined; + } +> { + public static defaultConfig: DeviceAction = { + device_id: "", + domain: "", + entity_id: "", + }; + + constructor() { + super(); + this.devicePicked = this.devicePicked.bind(this); + this.deviceActionPicked = this.deviceActionPicked.bind(this); + this.state = { device_id: undefined }; + } + + public render() { + const { action, hass } = this.props; + const deviceId = this.state.device_id || action.device_id; + + return ( +
+ + +
+ ); + } + + private devicePicked(ev) { + this.setState({ device_id: ev.target.value }); + } + + private deviceActionPicked(ev) { + const deviceAction = { ...ev.target.value }; + this.props.onChange(this.props.index, deviceAction); + } +} diff --git a/src/panels/config/js/trigger/device.tsx b/src/panels/config/js/trigger/device.tsx index 58d4dd65da..3a97b21e7c 100644 --- a/src/panels/config/js/trigger/device.tsx +++ b/src/panels/config/js/trigger/device.tsx @@ -2,7 +2,6 @@ import { h, Component } from "preact"; import "../../../../components/device/ha-device-picker"; import "../../../../components/device/ha-device-trigger-picker"; -import "../../../../components/device/ha-device-automation-picker"; export default class DeviceTrigger extends Component { constructor() { diff --git a/src/translations/en.json b/src/translations/en.json index 3af209aa68..c4db454d5b 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -871,6 +871,9 @@ "label": "Fire event", "event": "[%key:ui::panel::config::automation::editor::triggers::type::homeassistant::event%]", "service_data": "[%key:ui::panel::config::automation::editor::actions::type::service::service_data%]" + }, + "device_id": { + "label": "Device" } } }