Optimize automation editor (#5591)

This commit is contained in:
Bram Kragten 2020-04-24 13:36:51 +02:00 committed by GitHub
parent 14330fbd93
commit a0dae802f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 207 additions and 174 deletions

View File

@ -45,7 +45,9 @@ import { HaDeviceTrigger } from "./trigger/types/ha-automation-trigger-device";
export class HaAutomationEditor extends LitElement {
@property() public hass!: HomeAssistant;
@property() public automation!: AutomationEntity;
@property() public automationId!: string;
@property() public automations!: AutomationEntity[];
@property() public isWide?: boolean;
@ -53,15 +55,18 @@ export class HaAutomationEditor extends LitElement {
@property() public route!: Route;
@property() public creatingNew?: boolean;
@property() private _config?: AutomationConfig;
@property() private _dirty?: boolean;
@property() private _errors?: string;
@property() private _entityId?: string;
protected render(): TemplateResult {
const stateObj = this._entityId
? this.hass.states[this._entityId]
: undefined;
return html`
<hass-tabs-subpage
.hass=${this.hass}
@ -70,7 +75,7 @@ export class HaAutomationEditor extends LitElement {
.backCallback=${() => this._backTapped()}
.tabs=${configSections.automation}
>
${this.creatingNew
${!this.automationId
? ""
: html`
<paper-icon-button
@ -82,153 +87,162 @@ export class HaAutomationEditor extends LitElement {
@click=${this._deleteConfirm}
></paper-icon-button>
`}
${this._errors ? html` <div class="errors">${this._errors}</div> ` : ""}
${this._config
? html`
${this.narrow
? html` <span slot="header">${this._config?.alias}</span> `
: ""}
<ha-config-section .isWide=${this.isWide}>
${!this.narrow
? html` <span slot="header">${this._config.alias}</span> `
<div class="content">
${this._errors
? html` <div class="errors">${this._errors}</div> `
: ""}
<span slot="introduction">
${this.hass.localize(
"ui.panel.config.automation.editor.introduction"
)}
</span>
<ha-card>
<div class="card-content">
<paper-input
.label=${this.hass.localize(
"ui.panel.config.automation.editor.alias"
)}
name="alias"
.value=${this._config.alias}
@value-changed=${this._valueChanged}
>
</paper-input>
<ha-textarea
.label=${this.hass.localize(
"ui.panel.config.automation.editor.description.label"
)}
.placeholder=${this.hass.localize(
"ui.panel.config.automation.editor.description.placeholder"
)}
name="description"
.value=${this._config.description}
@value-changed=${this._valueChanged}
></ha-textarea>
</div>
${this.creatingNew
? ""
: html`
<div
class="card-actions layout horizontal justified center"
>
<div class="layout horizontal center">
<ha-entity-toggle
.hass=${this.hass}
.stateObj=${this.automation}
></ha-entity-toggle>
${this.hass.localize(
"ui.panel.config.automation.editor.enable_disable"
)}
<ha-config-section .isWide=${this.isWide}>
${!this.narrow
? html` <span slot="header">${this._config.alias}</span> `
: ""}
<span slot="introduction">
${this.hass.localize(
"ui.panel.config.automation.editor.introduction"
)}
</span>
<ha-card>
<div class="card-content">
<paper-input
.label=${this.hass.localize(
"ui.panel.config.automation.editor.alias"
)}
name="alias"
.value=${this._config.alias}
@value-changed=${this._valueChanged}
>
</paper-input>
<ha-textarea
.label=${this.hass.localize(
"ui.panel.config.automation.editor.description.label"
)}
.placeholder=${this.hass.localize(
"ui.panel.config.automation.editor.description.placeholder"
)}
name="description"
.value=${this._config.description}
@value-changed=${this._valueChanged}
></ha-textarea>
</div>
${stateObj
? html`
<div
class="card-actions layout horizontal justified center"
>
<div class="layout horizontal center">
<ha-entity-toggle
.hass=${this.hass}
.stateObj=${stateObj}
></ha-entity-toggle>
${this.hass.localize(
"ui.panel.config.automation.editor.enable_disable"
)}
</div>
<mwc-button
@click=${this._excuteAutomation}
.stateObj=${stateObj}
>
${this.hass.localize(
"ui.card.automation.trigger"
)}
</mwc-button>
</div>
<mwc-button @click=${this._excuteAutomation}>
${this.hass.localize("ui.card.automation.trigger")}
</mwc-button>
</div>
`}
</ha-card>
</ha-config-section>
`
: ""}
</ha-card>
</ha-config-section>
<ha-config-section .isWide=${this.isWide}>
<span slot="header">
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.header"
)}
</span>
<span slot="introduction">
<p>
<ha-config-section .isWide=${this.isWide}>
<span slot="header">
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.introduction"
"ui.panel.config.automation.editor.triggers.header"
)}
</p>
<a
href="https://home-assistant.io/docs/automation/trigger/"
target="_blank"
rel="noreferrer"
>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.learn_more"
)}
</a>
</span>
<ha-automation-trigger
.triggers=${this._config.trigger}
@value-changed=${this._triggerChanged}
.hass=${this.hass}
></ha-automation-trigger>
</ha-config-section>
</span>
<span slot="introduction">
<p>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.introduction"
)}
</p>
<a
href="https://home-assistant.io/docs/automation/trigger/"
target="_blank"
rel="noreferrer"
>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.learn_more"
)}
</a>
</span>
<ha-automation-trigger
.triggers=${this._config.trigger}
@value-changed=${this._triggerChanged}
.hass=${this.hass}
></ha-automation-trigger>
</ha-config-section>
<ha-config-section .isWide=${this.isWide}>
<span slot="header">
${this.hass.localize(
"ui.panel.config.automation.editor.conditions.header"
)}
</span>
<span slot="introduction">
<p>
<ha-config-section .isWide=${this.isWide}>
<span slot="header">
${this.hass.localize(
"ui.panel.config.automation.editor.conditions.introduction"
"ui.panel.config.automation.editor.conditions.header"
)}
</p>
<a
href="https://home-assistant.io/docs/scripts/conditions/"
target="_blank"
rel="noreferrer"
>
${this.hass.localize(
"ui.panel.config.automation.editor.conditions.learn_more"
)}
</a>
</span>
<ha-automation-condition
.conditions=${this._config.condition || []}
@value-changed=${this._conditionChanged}
.hass=${this.hass}
></ha-automation-condition>
</ha-config-section>
</span>
<span slot="introduction">
<p>
${this.hass.localize(
"ui.panel.config.automation.editor.conditions.introduction"
)}
</p>
<a
href="https://home-assistant.io/docs/scripts/conditions/"
target="_blank"
rel="noreferrer"
>
${this.hass.localize(
"ui.panel.config.automation.editor.conditions.learn_more"
)}
</a>
</span>
<ha-automation-condition
.conditions=${this._config.condition || []}
@value-changed=${this._conditionChanged}
.hass=${this.hass}
></ha-automation-condition>
</ha-config-section>
<ha-config-section .isWide=${this.isWide}>
<span slot="header">
${this.hass.localize(
"ui.panel.config.automation.editor.actions.header"
)}
</span>
<span slot="introduction">
<p>
<ha-config-section .isWide=${this.isWide}>
<span slot="header">
${this.hass.localize(
"ui.panel.config.automation.editor.actions.introduction"
"ui.panel.config.automation.editor.actions.header"
)}
</p>
<a
href="https://home-assistant.io/docs/automation/action/"
target="_blank"
rel="noreferrer"
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.learn_more"
)}
</a>
</span>
<ha-automation-action
.actions=${this._config.action}
@value-changed=${this._actionChanged}
.hass=${this.hass}
></ha-automation-action>
</ha-config-section>
</span>
<span slot="introduction">
<p>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.introduction"
)}
</p>
<a
href="https://home-assistant.io/docs/automation/action/"
target="_blank"
rel="noreferrer"
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.learn_more"
)}
</a>
</span>
<ha-automation-action
.actions=${this._config.action}
@value-changed=${this._actionChanged}
.hass=${this.hass}
></ha-automation-action>
</ha-config-section>
</div>
`
: ""}
<ha-fab
@ -251,19 +265,19 @@ export class HaAutomationEditor extends LitElement {
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
const oldAutomation = changedProps.get("automation") as AutomationEntity;
const oldAutomationId = changedProps.get("automationId");
if (
changedProps.has("automation") &&
this.automation &&
changedProps.has("automationId") &&
this.automationId &&
this.hass &&
// Only refresh config if we picked a new automation. If same ID, don't fetch it.
(!oldAutomation ||
oldAutomation.attributes.id !== this.automation.attributes.id)
oldAutomationId !== this.automationId
) {
this._setEntityId();
this.hass
.callApi<AutomationConfig>(
"GET",
`config/automation/config/${this.automation.attributes.id}`
`config/automation/config/${this.automationId}`
)
.then(
(config) => {
@ -290,13 +304,12 @@ export class HaAutomationEditor extends LitElement {
"err_no",
resp.status_code
),
});
history.back();
}).then(() => history.back());
}
);
}
if (changedProps.has("creatingNew") && this.creatingNew && this.hass) {
if (changedProps.has("automationId") && !this.automationId && this.hass) {
const initData = getAutomationEditorInitData();
this._dirty = !!initData;
this._config = {
@ -310,6 +323,21 @@ export class HaAutomationEditor extends LitElement {
...initData,
};
}
if (
changedProps.has("automations") &&
this.automationId &&
!this._entityId
) {
this._setEntityId();
}
}
private _setEntityId() {
const automation = this.automations.find(
(entity: AutomationEntity) => entity.attributes.id === this.automationId
);
this._entityId = automation?.entity_id;
}
private _valueChanged(ev: CustomEvent) {
@ -348,8 +376,8 @@ export class HaAutomationEditor extends LitElement {
this._dirty = true;
}
private _excuteAutomation() {
triggerAutomation(this.hass, this.automation.entity_id);
private _excuteAutomation(ev: Event) {
triggerAutomation(this.hass, (ev.target as any).stateObj.entity_id);
}
private _backTapped(): void {
@ -379,14 +407,12 @@ export class HaAutomationEditor extends LitElement {
}
private async _delete() {
await deleteAutomation(this.hass, this.automation.attributes.id!);
await deleteAutomation(this.hass, this.automationId);
history.back();
}
private _saveAutomation(): void {
const id = this.creatingNew
? "" + Date.now()
: this.automation.attributes.id;
const id = this.automationId || String(Date.now());
this.hass!.callApi(
"POST",
"config/automation/config/" + id,
@ -395,7 +421,7 @@ export class HaAutomationEditor extends LitElement {
() => {
this._dirty = false;
if (this.creatingNew) {
if (!this.automationId) {
navigate(this, `/config/automation/edit/${id}`, true);
}
},

View File

@ -10,6 +10,7 @@ import {
import { HomeAssistant } from "../../../types";
import "./ha-automation-editor";
import "./ha-automation-picker";
import { debounce } from "../../../common/util/debounce";
@customElement("ha-config-automation")
class HaConfigAutomation extends HassRouterPage {
@ -23,6 +24,13 @@ class HaConfigAutomation extends HassRouterPage {
@property() public automations: AutomationEntity[] = [];
private _debouncedUpdateAutomations = debounce((pageEl) => {
const newAutomations = this._getAutomations(this.hass.states);
if (!this._equal(newAutomations, pageEl.automations)) {
pageEl.automations = newAutomations;
}
}, 10);
protected routerOptions: RouterOptions = {
defaultPage: "dashboard",
routes: {
@ -36,19 +44,15 @@ class HaConfigAutomation extends HassRouterPage {
},
};
private _computeAutomations = memoizeOne((states: HassEntities) => {
const automations: AutomationEntity[] = [];
Object.values(states).forEach((state) => {
if (
computeStateDomain(state) === "automation" &&
!state.attributes.hidden
) {
automations.push(state as AutomationEntity);
}
});
return automations;
});
private _getAutomations = memoizeOne(
(states: HassEntities): AutomationEntity[] => {
return Object.values(states).filter(
(entity) =>
computeStateDomain(entity) === "automation" &&
!entity.attributes.hidden
) as AutomationEntity[];
}
);
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
@ -63,25 +67,28 @@ class HaConfigAutomation extends HassRouterPage {
pageEl.showAdvanced = this.showAdvanced;
if (this.hass) {
pageEl.automations = this._computeAutomations(this.hass.states);
if (!pageEl.automations || !changedProps) {
pageEl.automations = this._getAutomations(this.hass.states);
} else if (changedProps && changedProps.has("hass")) {
this._debouncedUpdateAutomations(pageEl);
}
}
if (
(!changedProps || changedProps.has("route")) &&
this._currentPage === "edit"
) {
pageEl.creatingNew = undefined;
const automationId = this.routeTail.path.substr(1);
pageEl.creatingNew = automationId === "new";
pageEl.automation =
automationId === "new"
? undefined
: pageEl.automations.find(
(entity: AutomationEntity) =>
entity.attributes.id === automationId
);
pageEl.automationId = automationId === "new" ? null : automationId;
}
}
private _equal(a: AutomationEntity[], b: AutomationEntity[]): boolean {
if (a.length !== b.length) {
return false;
}
return a.every((automation, index) => automation === b[index]);
}
}
declare global {