mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Merge pull request #3970 from emontnemery/automation_device_action_form
Allow device triggers to specify extra fields
This commit is contained in:
commit
f1fabd09a6
@ -36,8 +36,9 @@ class HaForm extends EventsMixin(PolymerElement) {
|
|||||||
schema="[[item]]"
|
schema="[[item]]"
|
||||||
error="[[_getValue(error, item)]]"
|
error="[[_getValue(error, item)]]"
|
||||||
on-data-changed="_valueChanged"
|
on-data-changed="_valueChanged"
|
||||||
compute-label="[[computeLabel]]"
|
|
||||||
compute-error="[[computeError]]"
|
compute-error="[[computeError]]"
|
||||||
|
compute-label="[[computeLabel]]"
|
||||||
|
compute-suffix="[[computeSuffix]]"
|
||||||
></ha-form>
|
></ha-form>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
@ -126,7 +127,9 @@ class HaForm extends EventsMixin(PolymerElement) {
|
|||||||
required="[[schema.required]]"
|
required="[[schema.required]]"
|
||||||
auto-validate="[[schema.required]]"
|
auto-validate="[[schema.required]]"
|
||||||
error-message="Required"
|
error-message="Required"
|
||||||
></paper-input>
|
>
|
||||||
|
<span suffix="" slot="suffix">[[computeSuffix(schema)]]</span>
|
||||||
|
</paper-input>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template
|
<template
|
||||||
@ -173,14 +176,24 @@ class HaForm extends EventsMixin(PolymerElement) {
|
|||||||
schema: Object,
|
schema: Object,
|
||||||
error: Object,
|
error: Object,
|
||||||
|
|
||||||
// A function that will computes the label to be displayed for a given
|
// A function that computes the label to be displayed for a given
|
||||||
// schema object.
|
// schema object.
|
||||||
computeLabel: {
|
computeLabel: {
|
||||||
type: Function,
|
type: Function,
|
||||||
value: () => (schema) => schema && schema.name,
|
value: () => (schema) => schema && schema.name,
|
||||||
},
|
},
|
||||||
|
|
||||||
// A function that will computes an error message to be displayed for a
|
// A function that computes the suffix to be displayed for a given
|
||||||
|
// schema object.
|
||||||
|
computeSuffix: {
|
||||||
|
type: Function,
|
||||||
|
value: () => (schema) =>
|
||||||
|
schema &&
|
||||||
|
schema.description &&
|
||||||
|
schema.description.unit_of_measurement,
|
||||||
|
},
|
||||||
|
|
||||||
|
// A function that computes an error message to be displayed for a
|
||||||
// given error ID, and relevant schema object
|
// given error ID, and relevant schema object
|
||||||
computeError: {
|
computeError: {
|
||||||
type: Function,
|
type: Function,
|
||||||
|
@ -39,6 +39,17 @@ export const fetchDeviceTriggers = (hass: HomeAssistant, deviceId: string) =>
|
|||||||
device_id: deviceId,
|
device_id: deviceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const fetchDeviceTriggerCapabilities = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
trigger: DeviceTrigger
|
||||||
|
) =>
|
||||||
|
hass.callWS<DeviceTrigger[]>({
|
||||||
|
type: "device_automation/trigger/capabilities",
|
||||||
|
trigger,
|
||||||
|
});
|
||||||
|
|
||||||
|
const whitelist = ["above", "below", "for"];
|
||||||
|
|
||||||
export const deviceAutomationsEqual = (
|
export const deviceAutomationsEqual = (
|
||||||
a: DeviceAutomation,
|
a: DeviceAutomation,
|
||||||
b: DeviceAutomation
|
b: DeviceAutomation
|
||||||
@ -48,11 +59,17 @@ export const deviceAutomationsEqual = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const property in a) {
|
for (const property in a) {
|
||||||
|
if (whitelist.includes(property)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!Object.is(a[property], b[property])) {
|
if (!Object.is(a[property], b[property])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const property in b) {
|
for (const property in b) {
|
||||||
|
if (whitelist.includes(property)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!Object.is(a[property], b[property])) {
|
if (!Object.is(a[property], b[property])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ declare global {
|
|||||||
"mwc-button": any;
|
"mwc-button": any;
|
||||||
"ha-device-trigger-picker": any;
|
"ha-device-trigger-picker": any;
|
||||||
"ha-device-action-picker": any;
|
"ha-device-action-picker": any;
|
||||||
|
"ha-form": any;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,29 +2,50 @@ import { h, Component } from "preact";
|
|||||||
|
|
||||||
import "../../../../components/device/ha-device-picker";
|
import "../../../../components/device/ha-device-picker";
|
||||||
import "../../../../components/device/ha-device-trigger-picker";
|
import "../../../../components/device/ha-device-trigger-picker";
|
||||||
|
import "../../../../components/ha-form";
|
||||||
|
|
||||||
|
import {
|
||||||
|
fetchDeviceTriggerCapabilities,
|
||||||
|
deviceAutomationsEqual,
|
||||||
|
} from "../../../../data/device_automation";
|
||||||
|
|
||||||
export default class DeviceTrigger extends Component<any, any> {
|
export default class DeviceTrigger extends Component<any, any> {
|
||||||
|
private _origTrigger;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.devicePicked = this.devicePicked.bind(this);
|
this.devicePicked = this.devicePicked.bind(this);
|
||||||
this.deviceTriggerPicked = this.deviceTriggerPicked.bind(this);
|
this.deviceTriggerPicked = this.deviceTriggerPicked.bind(this);
|
||||||
this.state = { device_id: undefined };
|
this._extraFieldsChanged = this._extraFieldsChanged.bind(this);
|
||||||
|
this.state = { device_id: undefined, capabilities: undefined };
|
||||||
}
|
}
|
||||||
|
|
||||||
public devicePicked(ev) {
|
public devicePicked(ev) {
|
||||||
this.setState({ device_id: ev.target.value });
|
this.setState({ ...this.state, device_id: ev.target.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
public deviceTriggerPicked(ev) {
|
public deviceTriggerPicked(ev) {
|
||||||
const deviceTrigger = ev.target.value;
|
let trigger = ev.target.value;
|
||||||
this.props.onChange(this.props.index, deviceTrigger);
|
if (
|
||||||
|
this._origTrigger &&
|
||||||
|
deviceAutomationsEqual(this._origTrigger, trigger)
|
||||||
|
) {
|
||||||
|
trigger = this._origTrigger;
|
||||||
|
}
|
||||||
|
this.props.onChange(this.props.index, trigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
public render({ trigger, hass }, { device_id }) {
|
public render({ trigger, hass }, { device_id, capabilities }) {
|
||||||
if (device_id === undefined) {
|
if (device_id === undefined) {
|
||||||
device_id = trigger.device_id;
|
device_id = trigger.device_id;
|
||||||
}
|
}
|
||||||
|
const extraFieldsData =
|
||||||
|
capabilities && capabilities.extra_fields
|
||||||
|
? capabilities.extra_fields.map((item) => {
|
||||||
|
return { [item.name]: this.props.trigger[item.name] };
|
||||||
|
})
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -41,9 +62,64 @@ export default class DeviceTrigger extends Component<any, any> {
|
|||||||
hass={hass}
|
hass={hass}
|
||||||
label="Trigger"
|
label="Trigger"
|
||||||
/>
|
/>
|
||||||
|
{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.trigger) {
|
||||||
|
this._origTrigger = this.props.trigger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidUpdate(prevProps) {
|
||||||
|
if (prevProps.trigger !== this.props.trigger) {
|
||||||
|
this._getCapabilities();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _getCapabilities() {
|
||||||
|
const trigger = this.props.trigger;
|
||||||
|
|
||||||
|
const capabilities = trigger.domain
|
||||||
|
? await fetchDeviceTriggerCapabilities(this.props.hass, trigger)
|
||||||
|
: 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.trigger,
|
||||||
|
[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.triggers.type.device.extra_fields.${
|
||||||
|
schema.name
|
||||||
|
}`
|
||||||
|
) || schema.name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(DeviceTrigger as any).defaultConfig = {
|
(DeviceTrigger as any).defaultConfig = {
|
||||||
|
@ -737,7 +737,12 @@
|
|||||||
"type_select": "Trigger type",
|
"type_select": "Trigger type",
|
||||||
"type": {
|
"type": {
|
||||||
"device": {
|
"device": {
|
||||||
"label": "Device"
|
"label": "Device",
|
||||||
|
"extra_fields": {
|
||||||
|
"above": "Above",
|
||||||
|
"below": "Below",
|
||||||
|
"for": "Duration"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"event": {
|
"event": {
|
||||||
"label": "Event",
|
"label": "Event",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user