mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-19 15:26:36 +00:00
Optimize automation editor (#5591)
This commit is contained in:
parent
14330fbd93
commit
a0dae802f2
@ -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);
|
||||
}
|
||||
},
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user