mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-02 14:07:55 +00:00
Allow device actions to specify extra fields (#4002)
* Allow device actions to specify extra fields * Typing etc. * Use deviceAutomationsEqual to compare automations
This commit is contained in:
parent
ce6a97d065
commit
555b746f4b
@ -39,6 +39,15 @@ export const fetchDeviceTriggers = (hass: HomeAssistant, deviceId: string) =>
|
|||||||
device_id: deviceId,
|
device_id: deviceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const fetchDeviceActionCapabilities = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
action: DeviceAction
|
||||||
|
) =>
|
||||||
|
hass.callWS<DeviceAction[]>({
|
||||||
|
type: "device_automation/action/capabilities",
|
||||||
|
action,
|
||||||
|
});
|
||||||
|
|
||||||
export const fetchDeviceConditionCapabilities = (
|
export const fetchDeviceConditionCapabilities = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
condition: DeviceCondition
|
condition: DeviceCondition
|
||||||
@ -57,7 +66,7 @@ export const fetchDeviceTriggerCapabilities = (
|
|||||||
trigger,
|
trigger,
|
||||||
});
|
});
|
||||||
|
|
||||||
const whitelist = ["above", "below", "for"];
|
const whitelist = ["above", "below", "code", "for"];
|
||||||
|
|
||||||
export const deviceAutomationsEqual = (
|
export const deviceAutomationsEqual = (
|
||||||
a: DeviceAutomation,
|
a: DeviceAutomation,
|
||||||
|
@ -83,7 +83,7 @@ export default class DeviceCondition extends Component<any, any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public componentDidUpdate(prevProps) {
|
public componentDidUpdate(prevProps) {
|
||||||
if (prevProps.condition !== this.props.condition) {
|
if (!deviceAutomationsEqual(prevProps.condition, this.props.condition)) {
|
||||||
this._getCapabilities();
|
this._getCapabilities();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,14 @@ import { h, Component } from "preact";
|
|||||||
|
|
||||||
import "../../../../components/device/ha-device-picker";
|
import "../../../../components/device/ha-device-picker";
|
||||||
import "../../../../components/device/ha-device-action-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 { DeviceAction } from "../../../../data/script";
|
||||||
|
import { HomeAssistant } from "../../../../types";
|
||||||
|
|
||||||
export default class DeviceActionEditor extends Component<
|
export default class DeviceActionEditor extends Component<
|
||||||
{
|
{
|
||||||
@ -14,6 +20,7 @@ export default class DeviceActionEditor extends Component<
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
device_id: string | undefined;
|
device_id: string | undefined;
|
||||||
|
capabilities: any | undefined;
|
||||||
}
|
}
|
||||||
> {
|
> {
|
||||||
public static defaultConfig: DeviceAction = {
|
public static defaultConfig: DeviceAction = {
|
||||||
@ -22,16 +29,26 @@ export default class DeviceActionEditor extends Component<
|
|||||||
entity_id: "",
|
entity_id: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private _origAction;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.devicePicked = this.devicePicked.bind(this);
|
this.devicePicked = this.devicePicked.bind(this);
|
||||||
this.deviceActionPicked = this.deviceActionPicked.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() {
|
public render() {
|
||||||
const { action, hass } = this.props;
|
const { action, hass } = this.props;
|
||||||
const deviceId = this.state.device_id || action.device_id;
|
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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -48,16 +65,77 @@ export default class DeviceActionEditor extends Component<
|
|||||||
hass={hass}
|
hass={hass}
|
||||||
label="Action"
|
label="Action"
|
||||||
/>
|
/>
|
||||||
|
{extraFieldsData && (
|
||||||
|
<ha-form
|
||||||
|
data={Object.assign({}, ...extraFieldsData)}
|
||||||
|
onData-changed={this._extraFieldsChanged}
|
||||||
|
schema={this.state.capabilities.extra_fields}
|
||||||
|
computeLabel={this._extraFieldsComputeLabelCallback(hass.localize)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
private devicePicked(ev) {
|
||||||
this.setState({ device_id: ev.target.value });
|
this.setState({ ...this.state, device_id: ev.target.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
private deviceActionPicked(ev) {
|
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);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ export default class DeviceTrigger extends Component<any, any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public componentDidUpdate(prevProps) {
|
public componentDidUpdate(prevProps) {
|
||||||
if (prevProps.trigger !== this.props.trigger) {
|
if (!deviceAutomationsEqual(prevProps.trigger, this.props.trigger)) {
|
||||||
this._getCapabilities();
|
this._getCapabilities();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -908,7 +908,10 @@
|
|||||||
"service_data": "[%key:ui::panel::config::automation::editor::actions::type::service::service_data%]"
|
"service_data": "[%key:ui::panel::config::automation::editor::actions::type::service::service_data%]"
|
||||||
},
|
},
|
||||||
"device_id": {
|
"device_id": {
|
||||||
"label": "Device"
|
"label": "Device",
|
||||||
|
"extra_fields": {
|
||||||
|
"code": "Code"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"scene": {
|
"scene": {
|
||||||
"label": "Activate scene"
|
"label": "Activate scene"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user