Don't add undefined values to extra data in device automations (#6499)

This commit is contained in:
Bram Kragten 2020-07-31 19:07:11 +02:00 committed by GitHub
parent 3a41b3bdcf
commit 89569355be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 47 deletions

View File

@ -100,7 +100,7 @@ export interface HaFormTimeData {
} }
export interface HaFormElement extends LitElement { export interface HaFormElement extends LitElement {
schema: HaFormSchema; schema: HaFormSchema | HaFormSchema[];
data?: HaFormDataContainer | HaFormData; data?: HaFormDataContainer | HaFormData;
label?: string; label?: string;
suffix?: string; suffix?: string;
@ -110,7 +110,7 @@ export interface HaFormElement extends LitElement {
export class HaForm extends LitElement implements HaFormElement { export class HaForm extends LitElement implements HaFormElement {
@property() public data!: HaFormDataContainer | HaFormData; @property() public data!: HaFormDataContainer | HaFormData;
@property() public schema!: HaFormSchema; @property() public schema!: HaFormSchema | HaFormSchema[];
@property() public error; @property() public error;
@ -190,7 +190,7 @@ export class HaForm extends LitElement implements HaFormElement {
: ""; : "";
} }
private _computeError(error, schema: HaFormSchema) { private _computeError(error, schema: HaFormSchema | HaFormSchema[]) {
return this.computeError ? this.computeError(error, schema) : error; return this.computeError ? this.computeError(error, schema) : error;
} }
@ -203,7 +203,7 @@ export class HaForm extends LitElement implements HaFormElement {
private _valueChanged(ev: CustomEvent) { private _valueChanged(ev: CustomEvent) {
ev.stopPropagation(); ev.stopPropagation();
const schema = (ev.target as HaFormElement).schema; const schema = (ev.target as HaFormElement).schema as HaFormSchema;
const data = this.data as HaFormDataContainer; const data = this.data as HaFormDataContainer;
data[schema.name] = ev.detail.value; data[schema.name] = ev.detail.value;
fireEvent(this, "value-changed", { fireEvent(this, "value-changed", {

View File

@ -50,6 +50,8 @@ export class HaYamlEditor extends LitElement {
try { try {
this._yaml = value && !isEmpty(value) ? safeDump(value) : ""; this._yaml = value && !isEmpty(value) ? safeDump(value) : "";
} catch (err) { } catch (err) {
// eslint-disable-next-line no-console
console.error(err);
alert(`There was an error converting to YAML: ${err}`); alert(`There was an error converting to YAML: ${err}`);
} }
afterNextRender(() => { afterNextRender(() => {

View File

@ -1,5 +1,6 @@
import { computeStateName } from "../common/entity/compute_state_name"; import { computeStateName } from "../common/entity/compute_state_name";
import { HomeAssistant } from "../types"; import { HomeAssistant } from "../types";
import { HaFormSchema } from "../components/ha-form/ha-form";
export interface DeviceAutomation { export interface DeviceAutomation {
device_id: string; device_id: string;
@ -20,6 +21,10 @@ export interface DeviceTrigger extends DeviceAutomation {
platform: "device"; platform: "device";
} }
export interface DeviceCapabilities {
extra_fields: HaFormSchema[];
}
export const fetchDeviceActions = (hass: HomeAssistant, deviceId: string) => export const fetchDeviceActions = (hass: HomeAssistant, deviceId: string) =>
hass.callWS<DeviceAction[]>({ hass.callWS<DeviceAction[]>({
type: "device_automation/action/list", type: "device_automation/action/list",
@ -42,7 +47,7 @@ export const fetchDeviceActionCapabilities = (
hass: HomeAssistant, hass: HomeAssistant,
action: DeviceAction action: DeviceAction
) => ) =>
hass.callWS<DeviceAction[]>({ hass.callWS<DeviceCapabilities>({
type: "device_automation/action/capabilities", type: "device_automation/action/capabilities",
action, action,
}); });
@ -51,7 +56,7 @@ export const fetchDeviceConditionCapabilities = (
hass: HomeAssistant, hass: HomeAssistant,
condition: DeviceCondition condition: DeviceCondition
) => ) =>
hass.callWS<DeviceCondition[]>({ hass.callWS<DeviceCapabilities>({
type: "device_automation/condition/capabilities", type: "device_automation/condition/capabilities",
condition, condition,
}); });
@ -60,7 +65,7 @@ export const fetchDeviceTriggerCapabilities = (
hass: HomeAssistant, hass: HomeAssistant,
trigger: DeviceTrigger trigger: DeviceTrigger
) => ) =>
hass.callWS<DeviceTrigger[]>({ hass.callWS<DeviceCapabilities>({
type: "device_automation/trigger/capabilities", type: "device_automation/trigger/capabilities",
trigger, trigger,
}); });

View File

@ -14,6 +14,7 @@ import {
DeviceAction, DeviceAction,
deviceAutomationsEqual, deviceAutomationsEqual,
fetchDeviceActionCapabilities, fetchDeviceActionCapabilities,
DeviceCapabilities,
} from "../../../../../data/device_automation"; } from "../../../../../data/device_automation";
import { HomeAssistant } from "../../../../../types"; import { HomeAssistant } from "../../../../../types";
@ -21,11 +22,11 @@ import { HomeAssistant } from "../../../../../types";
export class HaDeviceAction extends LitElement { export class HaDeviceAction extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public action!: DeviceAction; @property({ type: Object }) public action!: DeviceAction;
@internalProperty() private _deviceId?: string; @internalProperty() private _deviceId?: string;
@internalProperty() private _capabilities?; @internalProperty() private _capabilities?: DeviceCapabilities;
private _origAction?: DeviceAction; private _origAction?: DeviceAction;
@ -37,20 +38,20 @@ export class HaDeviceAction extends LitElement {
}; };
} }
private _extraFieldsData = memoizeOne((capabilities, action: DeviceAction) => private _extraFieldsData = memoizeOne(
capabilities && capabilities.extra_fields (action: DeviceAction, capabilities: DeviceCapabilities) => {
? capabilities.extra_fields.map((item) => { const extraFieldsData: { [key: string]: any } = {};
return { [item.name]: action[item.name] }; capabilities.extra_fields.forEach((item) => {
}) if (action[item.name] !== undefined) {
: undefined extraFieldsData![item.name] = action[item.name];
}
});
return extraFieldsData;
}
); );
protected render() { protected render() {
const deviceId = this._deviceId || this.action.device_id; const deviceId = this._deviceId || this.action.device_id;
const extraFieldsData = this._extraFieldsData(
this._capabilities,
this.action
);
return html` return html`
<ha-device-picker <ha-device-picker
@ -70,10 +71,10 @@ export class HaDeviceAction extends LitElement {
"ui.panel.config.automation.editor.actions.type.device_id.action" "ui.panel.config.automation.editor.actions.type.device_id.action"
)} )}
></ha-device-action-picker> ></ha-device-action-picker>
${extraFieldsData ${this._capabilities?.extra_fields
? html` ? html`
<ha-form <ha-form
.data=${Object.assign({}, ...extraFieldsData)} .data=${this._extraFieldsData(this.action, this._capabilities)}
.schema=${this._capabilities.extra_fields} .schema=${this._capabilities.extra_fields}
.computeLabel=${this._extraFieldsComputeLabelCallback( .computeLabel=${this._extraFieldsComputeLabelCallback(
this.hass.localize this.hass.localize
@ -105,7 +106,7 @@ export class HaDeviceAction extends LitElement {
private async _getCapabilities() { private async _getCapabilities() {
this._capabilities = this.action.domain this._capabilities = this.action.domain
? await fetchDeviceActionCapabilities(this.hass, this.action) ? await fetchDeviceActionCapabilities(this.hass, this.action)
: null; : undefined;
} }
private _devicePicked(ev) { private _devicePicked(ev) {

View File

@ -13,18 +13,20 @@ import {
deviceAutomationsEqual, deviceAutomationsEqual,
DeviceCondition, DeviceCondition,
fetchDeviceConditionCapabilities, fetchDeviceConditionCapabilities,
DeviceCapabilities,
} from "../../../../../data/device_automation"; } from "../../../../../data/device_automation";
import { HomeAssistant } from "../../../../../types"; import { HomeAssistant } from "../../../../../types";
import memoizeOne from "memoize-one";
@customElement("ha-automation-condition-device") @customElement("ha-automation-condition-device")
export class HaDeviceCondition extends LitElement { export class HaDeviceCondition extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public condition!: DeviceCondition; @property({ type: Object }) public condition!: DeviceCondition;
@internalProperty() private _deviceId?: string; @internalProperty() private _deviceId?: string;
@internalProperty() private _capabilities?; @internalProperty() private _capabilities?: DeviceCapabilities;
private _origCondition?: DeviceCondition; private _origCondition?: DeviceCondition;
@ -36,16 +38,21 @@ export class HaDeviceCondition extends LitElement {
}; };
} }
private _extraFieldsData = memoizeOne(
(condition: DeviceCondition, capabilities: DeviceCapabilities) => {
const extraFieldsData: { [key: string]: any } = {};
capabilities.extra_fields.forEach((item) => {
if (condition[item.name] !== undefined) {
extraFieldsData![item.name] = condition[item.name];
}
});
return extraFieldsData;
}
);
protected render() { protected render() {
const deviceId = this._deviceId || this.condition.device_id; const deviceId = this._deviceId || this.condition.device_id;
const extraFieldsData =
this._capabilities && this._capabilities.extra_fields
? this._capabilities.extra_fields.map((item) => {
return { [item.name]: this.condition[item.name] };
})
: undefined;
return html` return html`
<ha-device-picker <ha-device-picker
.value=${deviceId} .value=${deviceId}
@ -64,10 +71,10 @@ export class HaDeviceCondition extends LitElement {
"ui.panel.config.automation.editor.conditions.type.device.condition" "ui.panel.config.automation.editor.conditions.type.device.condition"
)} )}
></ha-device-condition-picker> ></ha-device-condition-picker>
${extraFieldsData ${this._capabilities?.extra_fields
? html` ? html`
<ha-form <ha-form
.data=${Object.assign({}, ...extraFieldsData)} .data=${this._extraFieldsData(this.condition, this._capabilities)}
.schema=${this._capabilities.extra_fields} .schema=${this._capabilities.extra_fields}
.computeLabel=${this._extraFieldsComputeLabelCallback( .computeLabel=${this._extraFieldsComputeLabelCallback(
this.hass.localize this.hass.localize
@ -103,7 +110,7 @@ export class HaDeviceCondition extends LitElement {
this._capabilities = condition.domain this._capabilities = condition.domain
? await fetchDeviceConditionCapabilities(this.hass, condition) ? await fetchDeviceConditionCapabilities(this.hass, condition)
: null; : undefined;
} }
private _devicePicked(ev) { private _devicePicked(ev) {
@ -141,3 +148,9 @@ export class HaDeviceCondition extends LitElement {
) || schema.name; ) || schema.name;
} }
} }
declare global {
interface HTMLElementTagNameMap {
"ha-automation-condition-device": HaDeviceCondition;
}
}

View File

@ -13,18 +13,20 @@ import {
deviceAutomationsEqual, deviceAutomationsEqual,
DeviceTrigger, DeviceTrigger,
fetchDeviceTriggerCapabilities, fetchDeviceTriggerCapabilities,
DeviceCapabilities,
} from "../../../../../data/device_automation"; } from "../../../../../data/device_automation";
import { HomeAssistant } from "../../../../../types"; import { HomeAssistant } from "../../../../../types";
import memoizeOne from "memoize-one";
@customElement("ha-automation-trigger-device") @customElement("ha-automation-trigger-device")
export class HaDeviceTrigger extends LitElement { export class HaDeviceTrigger extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public trigger!: DeviceTrigger; @property({ type: Object }) public trigger!: DeviceTrigger;
@internalProperty() private _deviceId?: string; @internalProperty() private _deviceId?: string;
@internalProperty() private _capabilities?; @internalProperty() private _capabilities?: DeviceCapabilities;
private _origTrigger?: DeviceTrigger; private _origTrigger?: DeviceTrigger;
@ -36,16 +38,21 @@ export class HaDeviceTrigger extends LitElement {
}; };
} }
private _extraFieldsData = memoizeOne(
(trigger: DeviceTrigger, capabilities: DeviceCapabilities) => {
const extraFieldsData: { [key: string]: any } = {};
capabilities.extra_fields.forEach((item) => {
if (trigger[item.name] !== undefined) {
extraFieldsData![item.name] = trigger[item.name];
}
});
return extraFieldsData;
}
);
protected render() { protected render() {
const deviceId = this._deviceId || this.trigger.device_id; const deviceId = this._deviceId || this.trigger.device_id;
const extraFieldsData =
this._capabilities && this._capabilities.extra_fields
? this._capabilities.extra_fields.map((item) => {
return { [item.name]: this.trigger[item.name] };
})
: undefined;
return html` return html`
<ha-device-picker <ha-device-picker
.value=${deviceId} .value=${deviceId}
@ -64,10 +71,10 @@ export class HaDeviceTrigger extends LitElement {
"ui.panel.config.automation.editor.triggers.type.device.trigger" "ui.panel.config.automation.editor.triggers.type.device.trigger"
)} )}
></ha-device-trigger-picker> ></ha-device-trigger-picker>
${extraFieldsData ${this._capabilities?.extra_fields
? html` ? html`
<ha-form <ha-form
.data=${Object.assign({}, ...extraFieldsData)} .data=${this._extraFieldsData(this.trigger, this._capabilities)}
.schema=${this._capabilities.extra_fields} .schema=${this._capabilities.extra_fields}
.computeLabel=${this._extraFieldsComputeLabelCallback( .computeLabel=${this._extraFieldsComputeLabelCallback(
this.hass.localize this.hass.localize
@ -100,7 +107,7 @@ export class HaDeviceTrigger extends LitElement {
this._capabilities = trigger.domain this._capabilities = trigger.domain
? await fetchDeviceTriggerCapabilities(this.hass, trigger) ? await fetchDeviceTriggerCapabilities(this.hass, trigger)
: null; : undefined;
} }
private _devicePicked(ev) { private _devicePicked(ev) {
@ -120,7 +127,7 @@ export class HaDeviceTrigger extends LitElement {
fireEvent(this, "value-changed", { value: trigger }); fireEvent(this, "value-changed", { value: trigger });
} }
private _extraFieldsChanged(ev) { private _extraFieldsChanged(ev: CustomEvent) {
ev.stopPropagation(); ev.stopPropagation();
fireEvent(this, "value-changed", { fireEvent(this, "value-changed", {
value: { value: {
@ -138,3 +145,9 @@ export class HaDeviceTrigger extends LitElement {
) || schema.name; ) || schema.name;
} }
} }
declare global {
interface HTMLElementTagNameMap {
"ha-automation-trigger-device": HaDeviceTrigger;
}
}