From a0dae802f2c3e49bb1fafd14805c017dde0e20ad Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 24 Apr 2020 13:36:51 +0200 Subject: [PATCH] Optimize automation editor (#5591) --- .../config/automation/ha-automation-editor.ts | 328 ++++++++++-------- .../config/automation/ha-config-automation.ts | 53 +-- 2 files changed, 207 insertions(+), 174 deletions(-) diff --git a/src/panels/config/automation/ha-automation-editor.ts b/src/panels/config/automation/ha-automation-editor.ts index fa7f671b90..0a4b17a997 100644 --- a/src/panels/config/automation/ha-automation-editor.ts +++ b/src/panels/config/automation/ha-automation-editor.ts @@ -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` this._backTapped()} .tabs=${configSections.automation} > - ${this.creatingNew + ${!this.automationId ? "" : html` `} - ${this._errors ? html`
${this._errors}
` : ""} ${this._config ? html` ${this.narrow ? html` ${this._config?.alias} ` : ""} - - ${!this.narrow - ? html` ${this._config.alias} ` +
+ ${this._errors + ? html`
${this._errors}
` : ""} - - ${this.hass.localize( - "ui.panel.config.automation.editor.introduction" - )} - - -
- - - -
- ${this.creatingNew - ? "" - : html` -
-
- - ${this.hass.localize( - "ui.panel.config.automation.editor.enable_disable" - )} + + ${!this.narrow + ? html` ${this._config.alias} ` + : ""} + + ${this.hass.localize( + "ui.panel.config.automation.editor.introduction" + )} + + +
+ + + +
+ ${stateObj + ? html` +
+
+ + ${this.hass.localize( + "ui.panel.config.automation.editor.enable_disable" + )} +
+ + ${this.hass.localize( + "ui.card.automation.trigger" + )} +
- - ${this.hass.localize("ui.card.automation.trigger")} - -
- `} - - + ` + : ""} + + - - - ${this.hass.localize( - "ui.panel.config.automation.editor.triggers.header" - )} - - -

+ + ${this.hass.localize( - "ui.panel.config.automation.editor.triggers.introduction" + "ui.panel.config.automation.editor.triggers.header" )} -

- - ${this.hass.localize( - "ui.panel.config.automation.editor.triggers.learn_more" - )} - -
- -
+ + +

+ ${this.hass.localize( + "ui.panel.config.automation.editor.triggers.introduction" + )} +

+ + ${this.hass.localize( + "ui.panel.config.automation.editor.triggers.learn_more" + )} + +
+ + - - - ${this.hass.localize( - "ui.panel.config.automation.editor.conditions.header" - )} - - -

+ + ${this.hass.localize( - "ui.panel.config.automation.editor.conditions.introduction" + "ui.panel.config.automation.editor.conditions.header" )} -

- - ${this.hass.localize( - "ui.panel.config.automation.editor.conditions.learn_more" - )} - -
- -
+ + +

+ ${this.hass.localize( + "ui.panel.config.automation.editor.conditions.introduction" + )} +

+ + ${this.hass.localize( + "ui.panel.config.automation.editor.conditions.learn_more" + )} + +
+ + - - - ${this.hass.localize( - "ui.panel.config.automation.editor.actions.header" - )} - - -

+ + ${this.hass.localize( - "ui.panel.config.automation.editor.actions.introduction" + "ui.panel.config.automation.editor.actions.header" )} -

- - ${this.hass.localize( - "ui.panel.config.automation.editor.actions.learn_more" - )} - -
- -
+ + +

+ ${this.hass.localize( + "ui.panel.config.automation.editor.actions.introduction" + )} +

+ + ${this.hass.localize( + "ui.panel.config.automation.editor.actions.learn_more" + )} + +
+ + +
` : ""} ( "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); } }, diff --git a/src/panels/config/automation/ha-config-automation.ts b/src/panels/config/automation/ha-config-automation.ts index 815c1b09af..c1f2b932a2 100644 --- a/src/panels/config/automation/ha-config-automation.ts +++ b/src/panels/config/automation/ha-config-automation.ts @@ -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 {