Show non-editable automations in UI (#13900)

This commit is contained in:
Bram Kragten 2022-09-29 18:11:29 +02:00 committed by GitHub
parent 9f658c10c3
commit 0b76183acd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 455 additions and 44 deletions

View File

@ -1,5 +1,5 @@
/* eslint-disable lit/no-template-arrow */
import { LitElement, TemplateResult, html } from "lit";
import { LitElement, TemplateResult, html, css } from "lit";
import { customElement, state } from "lit/decorators";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import type { HomeAssistant } from "../../../../src/types";
@ -47,6 +47,8 @@ const SCHEMAS: { name: string; actions: Action[] }[] = [
class DemoHaAutomationEditorAction extends LitElement {
@state() private hass!: HomeAssistant;
@state() private _disabled = false;
private data: any = SCHEMAS.map((info) => info.actions);
constructor() {
@ -67,6 +69,15 @@ class DemoHaAutomationEditorAction extends LitElement {
this.requestUpdate();
};
return html`
<div class="options">
<ha-formfield label="Disabled">
<ha-switch
.name=${"disabled"}
.checked=${this._disabled}
@change=${this._handleOptionChange}
></ha-switch>
</ha-formfield>
</div>
${SCHEMAS.map(
(info, sampleIdx) => html`
<demo-black-white-row
@ -81,6 +92,7 @@ class DemoHaAutomationEditorAction extends LitElement {
.hass=${this.hass}
.actions=${this.data[sampleIdx]}
.sampleIdx=${sampleIdx}
.disabled=${this._disabled}
@value-changed=${valueChanged}
></ha-automation-action>
`
@ -90,6 +102,20 @@ class DemoHaAutomationEditorAction extends LitElement {
)}
`;
}
private _handleOptionChange(ev) {
this[`_${ev.target.name}`] = ev.target.checked;
}
static styles = css`
.options {
max-width: 800px;
margin: 16px auto;
}
.options ha-formfield {
margin-right: 16px;
}
`;
}
declare global {

View File

@ -1,5 +1,5 @@
/* eslint-disable lit/no-template-arrow */
import { LitElement, TemplateResult, html } from "lit";
import { LitElement, TemplateResult, html, css } from "lit";
import { customElement, state } from "lit/decorators";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import type { HomeAssistant } from "../../../../src/types";
@ -83,6 +83,8 @@ const SCHEMAS: { name: string; conditions: ConditionWithShorthand[] }[] = [
class DemoHaAutomationEditorCondition extends LitElement {
@state() private hass!: HomeAssistant;
@state() private _disabled = false;
private data: any = SCHEMAS.map((info) => info.conditions);
constructor() {
@ -103,6 +105,15 @@ class DemoHaAutomationEditorCondition extends LitElement {
this.requestUpdate();
};
return html`
<div class="options">
<ha-formfield label="Disabled">
<ha-switch
.name=${"disabled"}
.checked=${this._disabled}
@change=${this._handleOptionChange}
></ha-switch>
</ha-formfield>
</div>
${SCHEMAS.map(
(info, sampleIdx) => html`
<demo-black-white-row
@ -117,6 +128,7 @@ class DemoHaAutomationEditorCondition extends LitElement {
.hass=${this.hass}
.conditions=${this.data[sampleIdx]}
.sampleIdx=${sampleIdx}
.disabled=${this._disabled}
@value-changed=${valueChanged}
></ha-automation-condition>
`
@ -126,6 +138,20 @@ class DemoHaAutomationEditorCondition extends LitElement {
)}
`;
}
private _handleOptionChange(ev) {
this[`_${ev.target.name}`] = ev.target.checked;
}
static styles = css`
.options {
max-width: 800px;
margin: 16px auto;
}
.options ha-formfield {
margin-right: 16px;
}
`;
}
declare global {

View File

@ -1,5 +1,5 @@
/* eslint-disable lit/no-template-arrow */
import { LitElement, TemplateResult, html } from "lit";
import { LitElement, TemplateResult, html, css } from "lit";
import { customElement, state } from "lit/decorators";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import type { HomeAssistant } from "../../../../src/types";
@ -107,6 +107,8 @@ const SCHEMAS: { name: string; triggers: Trigger[] }[] = [
class DemoHaAutomationEditorTrigger extends LitElement {
@state() private hass!: HomeAssistant;
@state() private _disabled = false;
private data: any = SCHEMAS.map((info) => info.triggers);
constructor() {
@ -127,6 +129,15 @@ class DemoHaAutomationEditorTrigger extends LitElement {
this.requestUpdate();
};
return html`
<div class="options">
<ha-formfield label="Disabled">
<ha-switch
.name=${"disabled"}
.checked=${this._disabled}
@change=${this._handleOptionChange}
></ha-switch>
</ha-formfield>
</div>
${SCHEMAS.map(
(info, sampleIdx) => html`
<demo-black-white-row
@ -141,6 +152,7 @@ class DemoHaAutomationEditorTrigger extends LitElement {
.hass=${this.hass}
.triggers=${this.data[sampleIdx]}
.sampleIdx=${sampleIdx}
.disabled=${this._disabled}
@value-changed=${valueChanged}
></ha-automation-trigger>
`
@ -150,6 +162,20 @@ class DemoHaAutomationEditorTrigger extends LitElement {
)}
`;
}
private _handleOptionChange(ev) {
this[`_${ev.target.name}`] = ev.target.checked;
}
static styles = css`
.options {
max-width: 800px;
margin: 16px auto;
}
.options ha-formfield {
margin-right: 16px;
}
`;
}
declare global {

View File

@ -312,6 +312,7 @@ export class HaEntityPicker extends LitElement {
.filteredItems=${this._states}
.renderer=${rowRenderer}
.required=${this.required}
.disabled=${this.disabled}
@opened-changed=${this._openedChanged}
@value-changed=${this._valueChanged}
@filter-changed=${this._filterChanged}

View File

@ -55,12 +55,14 @@ export class HaServiceControl extends LitElement {
data?: Record<string, any>;
};
@state() private _value!: this["value"];
@property({ type: Boolean }) public disabled = false;
@property({ reflect: true, type: Boolean }) public narrow!: boolean;
@property({ type: Boolean }) public showAdvanced?: boolean;
@state() private _value!: this["value"];
@state() private _checkedKeys = new Set();
@state() private _manifest?: IntegrationManifest;
@ -227,6 +229,7 @@ export class HaServiceControl extends LitElement {
return html`<ha-service-picker
.hass=${this.hass}
.value=${this._value?.service}
.disabled=${this.disabled}
@value-changed=${this._serviceChanged}
></ha-service-picker>
<div class="description">
@ -273,6 +276,7 @@ export class HaServiceControl extends LitElement {
.selector=${serviceData.target
? { target: serviceData.target }
: { target: {} }}
.disabled=${this.disabled}
@value-changed=${this._targetChanged}
.value=${this._value?.target}
></ha-selector
@ -280,6 +284,7 @@ export class HaServiceControl extends LitElement {
: entityId
? html`<ha-entity-picker
.hass=${this.hass}
.disabled=${this.disabled}
.value=${this._value?.data?.entity_id}
.label=${entityId.description}
@value-changed=${this._entityPicked}
@ -291,6 +296,7 @@ export class HaServiceControl extends LitElement {
.hass=${this.hass}
.label=${this.hass.localize("ui.components.service-control.data")}
.name=${"data"}
.readOnly=${this.disabled}
.defaultValue=${this._value?.data}
@value-changed=${this._dataChanged}
></ha-yaml-editor>`
@ -311,16 +317,18 @@ export class HaServiceControl extends LitElement {
.checked=${this._checkedKeys.has(dataField.key) ||
(this._value?.data &&
this._value.data[dataField.key] !== undefined)}
.disabled=${this.disabled}
@change=${this._checkboxChanged}
slot="prefix"
></ha-checkbox>`}
<span slot="heading">${dataField.name || dataField.key}</span>
<span slot="description">${dataField?.description}</span>
<ha-selector
.disabled=${showOptional &&
!this._checkedKeys.has(dataField.key) &&
(!this._value?.data ||
this._value.data[dataField.key] === undefined)}
.disabled=${this.disabled ||
(showOptional &&
!this._checkedKeys.has(dataField.key) &&
(!this._value?.data ||
this._value.data[dataField.key] === undefined))}
.hass=${this.hass}
.selector=${dataField.selector}
.key=${dataField.key}

View File

@ -20,6 +20,8 @@ const rowRenderer: ComboBoxLitRenderer<{ service: string; name: string }> = (
class HaServicePicker extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public disabled = false;
@property() public value?: string;
@state() private _filter?: string;
@ -35,6 +37,7 @@ class HaServicePicker extends LitElement {
this._filter
)}
.value=${this.value}
.disabled=${this.disabled}
.renderer=${rowRenderer}
item-value-path="service"
item-label-path="name"

View File

@ -311,9 +311,18 @@ export const deleteAutomation = (hass: HomeAssistant, id: string) =>
let inititialAutomationEditorData: Partial<AutomationConfig> | undefined;
export const getAutomationConfig = (hass: HomeAssistant, id: string) =>
export const fetchAutomationFileConfig = (hass: HomeAssistant, id: string) =>
hass.callApi<AutomationConfig>("GET", `config/automation/config/${id}`);
export const getAutomationStateConfig = (
hass: HomeAssistant,
entity_id: string
) =>
hass.callWS<{ config: AutomationConfig }>({
type: "automation/config",
entity_id,
});
export const saveAutomationConfig = (
hass: HomeAssistant,
id: string,

View File

@ -100,6 +100,8 @@ export default class HaAutomationActionRow extends LitElement {
@property({ type: Boolean }) public narrow = false;
@property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public hideMenu = false;
@property({ type: Boolean }) public reOrderMode = false;
@ -179,7 +181,7 @@ export default class HaAutomationActionRow extends LitElement {
<ha-svg-icon slot="graphic" .path=${mdiPlay}></ha-svg-icon>
</mwc-list-item>
<mwc-list-item graphic="icon">
<mwc-list-item graphic="icon" .disabled=${this.disabled}>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.rename"
)}
@ -188,7 +190,7 @@ export default class HaAutomationActionRow extends LitElement {
.path=${mdiRenameBox}
></ha-svg-icon>
</mwc-list-item>
<mwc-list-item graphic="icon">
<mwc-list-item graphic="icon" .disabled=${this.disabled}>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.duplicate"
)}
@ -234,7 +236,7 @@ export default class HaAutomationActionRow extends LitElement {
<li divider role="separator"></li>
<mwc-list-item graphic="icon">
<mwc-list-item graphic="icon" .disabled=${this.disabled}>
${this.action.enabled === false
? this.hass.localize(
"ui.panel.config.automation.editor.actions.enable"
@ -249,7 +251,11 @@ export default class HaAutomationActionRow extends LitElement {
: mdiStopCircleOutline}
></ha-svg-icon>
</mwc-list-item>
<mwc-list-item class="warning" graphic="icon">
<mwc-list-item
class="warning"
graphic="icon"
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.delete"
)}
@ -302,6 +308,7 @@ export default class HaAutomationActionRow extends LitElement {
<ha-yaml-editor
.hass=${this.hass}
.defaultValue=${this.action}
.readOnly=${this.disabled}
@value-changed=${this._onYamlChange}
></ha-yaml-editor>
`
@ -312,6 +319,7 @@ export default class HaAutomationActionRow extends LitElement {
action: this.action,
narrow: this.narrow,
reOrderMode: this.reOrderMode,
disabled: this.disabled,
})}
</div>
`}

View File

@ -44,6 +44,8 @@ export default class HaAutomationAction extends LitElement {
@property({ type: Boolean }) public narrow = false;
@property({ type: Boolean }) public disabled = false;
@property() public actions!: Action[];
@property({ type: Boolean }) public reOrderMode = false;
@ -65,6 +67,7 @@ export default class HaAutomationAction extends LitElement {
.index=${idx}
.action=${action}
.narrow=${this.narrow}
.disabled=${this.disabled}
.hideMenu=${this.reOrderMode}
.reOrderMode=${this.reOrderMode}
@duplicate=${this._duplicateAction}
@ -102,10 +105,15 @@ export default class HaAutomationAction extends LitElement {
`
)}
</div>
<ha-button-menu fixed @action=${this._addAction}>
<ha-button-menu
fixed
@action=${this._addAction}
.disabled=${this.disabled}
>
<mwc-button
slot="trigger"
outlined
.disabled=${this.disabled}
.label=${this.hass.localize(
"ui.panel.config.automation.editor.actions.add"
)}

View File

@ -13,6 +13,8 @@ const includeDomains = ["scene"];
export class HaSceneAction extends LitElement implements ActionElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public disabled = false;
@property() public action!: SceneAction;
public static get defaultConfig(): SceneAction {
@ -41,6 +43,7 @@ export class HaSceneAction extends LitElement implements ActionElement {
"ui.panel.config.automation.editor.actions.type.activate_scene.scene"
)}
.value=${scene}
.disabled=${this.disabled}
@value-changed=${this._entityPicked}
.includeDomains=${includeDomains}
allow-custom-entity

View File

@ -14,6 +14,8 @@ import { ActionElement } from "../ha-automation-action-row";
export class HaChooseAction extends LitElement implements ActionElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public disabled = false;
@property() public action!: ChooseAction;
@property({ type: Boolean }) public reOrderMode = false;
@ -32,6 +34,7 @@ export class HaChooseAction extends LitElement implements ActionElement {
(option, idx) => html`<ha-card>
<ha-icon-button
.idx=${idx}
.disabled=${this.disabled}
@click=${this._removeOption}
.label=${this.hass.localize(
"ui.panel.config.automation.editor.actions.type.choose.remove_option"
@ -54,6 +57,7 @@ export class HaChooseAction extends LitElement implements ActionElement {
<ha-automation-condition
.conditions=${option.conditions}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
.hass=${this.hass}
.idx=${idx}
@value-changed=${this._conditionChanged}
@ -66,6 +70,7 @@ export class HaChooseAction extends LitElement implements ActionElement {
<ha-automation-action
.actions=${option.sequence || []}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
.hass=${this.hass}
.idx=${idx}
@value-changed=${this._actionChanged}
@ -78,6 +83,7 @@ export class HaChooseAction extends LitElement implements ActionElement {
.label=${this.hass.localize(
"ui.panel.config.automation.editor.actions.type.choose.add_option"
)}
.disabled=${this.disabled}
@click=${this._addOption}
>
<ha-svg-icon .path=${mdiPlus} slot="icon"></ha-svg-icon>
@ -92,12 +98,17 @@ export class HaChooseAction extends LitElement implements ActionElement {
<ha-automation-action
.actions=${action.default || []}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
@value-changed=${this._defaultChanged}
.hass=${this.hass}
></ha-automation-action>
`
: html` <div class="link-button-row">
<button class="link" @click=${this._addDefault}>
: html`<div class="link-button-row">
<button
class="link"
@click=${this._addDefault}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.type.choose.add_default"
)}

View File

@ -16,6 +16,8 @@ import type { ActionElement } from "../ha-automation-action-row";
export class HaConditionAction extends LitElement implements ActionElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public disabled = false;
@property() public action!: Condition;
public static get defaultConfig() {
@ -29,6 +31,7 @@ export class HaConditionAction extends LitElement implements ActionElement {
.label=${this.hass.localize(
"ui.panel.config.automation.editor.conditions.type_select"
)}
.disabled=${this.disabled}
.value=${this.action.condition}
naturalMenuWidth
@selected=${this._typeChanged}
@ -43,6 +46,7 @@ export class HaConditionAction extends LitElement implements ActionElement {
</ha-select>
<ha-automation-condition-editor
.condition=${this.action}
.disabled=${this.disabled}
.hass=${this.hass}
@value-changed=${this._conditionChanged}
></ha-automation-condition-editor>

View File

@ -13,6 +13,8 @@ import { createDurationData } from "../../../../../common/datetime/create_durati
export class HaDelayAction extends LitElement implements ActionElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public disabled = false;
@property({ attribute: false }) public action!: DelayAction;
@state() private _timeData?: HaDurationData;
@ -43,6 +45,7 @@ export class HaDelayAction extends LitElement implements ActionElement {
.label=${this.hass.localize(
`ui.panel.config.automation.editor.actions.type.delay.delay`
)}
.disabled=${this.disabled}
.data=${this._timeData}
enableMillisecond
@value-changed=${this._valueChanged}

View File

@ -17,6 +17,8 @@ import { HomeAssistant } from "../../../../../types";
export class HaDeviceAction extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public disabled = false;
@property({ type: Object }) public action!: DeviceAction;
@state() private _deviceId?: string;
@ -51,6 +53,7 @@ export class HaDeviceAction extends LitElement {
return html`
<ha-device-picker
.value=${deviceId}
.disabled=${this.disabled}
@value-changed=${this._devicePicked}
.hass=${this.hass}
label=${this.hass.localize(
@ -60,6 +63,7 @@ export class HaDeviceAction extends LitElement {
<ha-device-action-picker
.value=${this.action}
.deviceId=${deviceId}
.disabled=${this.disabled}
@value-changed=${this._deviceActionPicked}
.hass=${this.hass}
label=${this.hass.localize(
@ -72,6 +76,7 @@ export class HaDeviceAction extends LitElement {
.hass=${this.hass}
.data=${this._extraFieldsData(this.action, this._capabilities)}
.schema=${this._capabilities.extra_fields}
.disabled=${this.disabled}
.computeLabel=${this._extraFieldsComputeLabelCallback(
this.hass.localize
)}

View File

@ -14,6 +14,8 @@ import { ActionElement, handleChangeEvent } from "../ha-automation-action-row";
export class HaEventAction extends LitElement implements ActionElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public disabled = false;
@property() public action!: EventAction;
@query("ha-yaml-editor", true) private _yamlEditor?: HaYamlEditor;
@ -45,6 +47,7 @@ export class HaEventAction extends LitElement implements ActionElement {
"ui.panel.config.automation.editor.actions.type.event.event"
)}
.value=${event}
.disabled=${this.disabled}
@change=${this._eventChanged}
></ha-textfield>
<ha-yaml-editor
@ -53,6 +56,7 @@ export class HaEventAction extends LitElement implements ActionElement {
"ui.panel.config.automation.editor.actions.type.event.event_data"
)}
.name=${"event_data"}
.readOnly=${this.disabled}
.defaultValue=${event_data}
@value-changed=${this._dataChanged}
></ha-yaml-editor>

View File

@ -13,6 +13,8 @@ import type { ActionElement } from "../ha-automation-action-row";
export class HaIfAction extends LitElement implements ActionElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public disabled = false;
@property({ attribute: false }) public action!: IfAction;
@property({ type: Boolean }) public reOrderMode = false;
@ -38,6 +40,7 @@ export class HaIfAction extends LitElement implements ActionElement {
<ha-automation-condition
.conditions=${action.if}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
@value-changed=${this._ifChanged}
.hass=${this.hass}
></ha-automation-condition>
@ -50,6 +53,7 @@ export class HaIfAction extends LitElement implements ActionElement {
<ha-automation-action
.actions=${action.then}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
@value-changed=${this._thenChanged}
.hass=${this.hass}
></ha-automation-action>
@ -63,12 +67,17 @@ export class HaIfAction extends LitElement implements ActionElement {
<ha-automation-action
.actions=${action.else || []}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
@value-changed=${this._elseChanged}
.hass=${this.hass}
></ha-automation-action>
`
: html` <div class="link-button-row">
<button class="link" @click=${this._addElse}>
<button
class="link"
@click=${this._addElse}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.type.if.add_else"
)}

View File

@ -12,6 +12,8 @@ import type { ActionElement } from "../ha-automation-action-row";
export class HaParallelAction extends LitElement implements ActionElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public disabled = false;
@property({ attribute: false }) public action!: ParallelAction;
@property({ type: Boolean }) public reOrderMode = false;
@ -29,6 +31,7 @@ export class HaParallelAction extends LitElement implements ActionElement {
<ha-automation-action
.actions=${action.parallel}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
@value-changed=${this._actionsChanged}
.hass=${this.hass}
></ha-automation-action>

View File

@ -12,6 +12,8 @@ import { ActionElement } from "../ha-automation-action-row";
export class HaPlayMediaAction extends LitElement implements ActionElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public disabled = false;
@property({ attribute: false }) public action!: PlayMediaAction;
@property({ type: Boolean }) public narrow = false;
@ -38,6 +40,7 @@ export class HaPlayMediaAction extends LitElement implements ActionElement {
return html`
<ha-selector-media
.hass=${this.hass}
.disabled=${this.disabled}
.value=${this._getSelectorValue(this.action)}
@value-changed=${this._valueChanged}
></ha-selector-media>

View File

@ -23,6 +23,8 @@ const getType = (action) => OPTIONS.find((option) => option in action);
export class HaRepeatAction extends LitElement implements ActionElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public disabled = false;
@property({ attribute: false }) public action!: RepeatAction;
@property({ type: Boolean }) public reOrderMode = false;
@ -42,6 +44,7 @@ export class HaRepeatAction extends LitElement implements ActionElement {
"ui.panel.config.automation.editor.actions.type.repeat.type_select"
)}
.value=${type}
.disabled=${this.disabled}
@selected=${this._typeChanged}
>
${OPTIONS.map(
@ -63,6 +66,7 @@ export class HaRepeatAction extends LitElement implements ActionElement {
)}
name="count"
.value=${(action as CountRepeat).count || "0"}
.disabled=${this.disabled}
@change=${this._countChanged}
></ha-textfield>
`
@ -75,6 +79,7 @@ export class HaRepeatAction extends LitElement implements ActionElement {
<ha-automation-condition
.conditions=${(action as WhileRepeat).while || []}
.hass=${this.hass}
.disabled=${this.disabled}
@value-changed=${this._conditionChanged}
></ha-automation-condition>`
: type === "until"
@ -86,6 +91,7 @@ export class HaRepeatAction extends LitElement implements ActionElement {
<ha-automation-condition
.conditions=${(action as UntilRepeat).until || []}
.hass=${this.hass}
.disabled=${this.disabled}
@value-changed=${this._conditionChanged}
></ha-automation-condition>`
: ""}
@ -98,6 +104,7 @@ export class HaRepeatAction extends LitElement implements ActionElement {
<ha-automation-action
.actions=${action.sequence}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
@value-changed=${this._actionChanged}
.hass=${this.hass}
></ha-automation-action>

View File

@ -23,6 +23,8 @@ export class HaServiceAction extends LitElement implements ActionElement {
@property({ attribute: false }) public action!: ServiceAction;
@property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public narrow = false;
@state() private _action!: ServiceAction;
@ -66,6 +68,7 @@ export class HaServiceAction extends LitElement implements ActionElement {
.narrow=${this.narrow}
.hass=${this.hass}
.value=${this._action}
.disabled=${this.disabled}
.showAdvanced=${this.hass.userData?.showAdvanced}
@value-changed=${this._actionChanged}
></ha-service-control>

View File

@ -12,6 +12,8 @@ export class HaStopAction extends LitElement implements ActionElement {
@property() public action!: StopAction;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return { stop: "" };
}
@ -25,14 +27,17 @@ export class HaStopAction extends LitElement implements ActionElement {
"ui.panel.config.automation.editor.actions.type.stop.stop"
)}
.value=${stop}
.disabled=${this.disabled}
@change=${this._stopChanged}
></ha-textfield>
<ha-formfield
.disabled=${this.disabled}
.label=${this.hass.localize(
"ui.panel.config.automation.editor.actions.type.stop.error"
)}
>
<ha-switch
.disabled=${this.disabled}
.checked=${error ?? false}
@change=${this._errorChanged}
></ha-switch>

View File

@ -21,6 +21,8 @@ export class HaWaitForTriggerAction
@property({ attribute: false }) public action!: WaitForTriggerAction;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return { wait_for_trigger: [] };
}
@ -34,22 +36,26 @@ export class HaWaitForTriggerAction
"ui.panel.config.automation.editor.actions.type.wait_for_trigger.timeout"
)}
.data=${timeData}
.disabled=${this.disabled}
enableMillisecond
@value-changed=${this._timeoutChanged}
></ha-duration-input>
<ha-formfield
.disabled=${this.disabled}
.label=${this.hass.localize(
"ui.panel.config.automation.editor.actions.type.wait_for_trigger.continue_timeout"
)}
>
<ha-switch
.checked=${this.action.continue_on_timeout ?? true}
.disabled=${this.disabled}
@change=${this._continueChanged}
></ha-switch>
</ha-formfield>
<ha-automation-trigger
.triggers=${ensureArray(this.action.wait_for_trigger)}
.hass=${this.hass}
.disabled=${this.disabled}
.name=${"wait_for_trigger"}
@value-changed=${this._valueChanged}
></ha-automation-trigger>

View File

@ -32,6 +32,8 @@ export class HaWaitAction extends LitElement implements ActionElement {
@property({ attribute: false }) public action!: WaitAction;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return { wait_template: "", continue_on_timeout: true };
}
@ -42,6 +44,7 @@ export class HaWaitAction extends LitElement implements ActionElement {
.hass=${this.hass}
.data=${this.action}
.schema=${SCHEMA}
.disabled=${this.disabled}
.computeLabel=${this._computeLabelCallback}
></ha-form>
`;

View File

@ -27,6 +27,8 @@ export class HaBlueprintAutomationEditor extends LitElement {
@property() public isWide!: boolean;
@property({ type: Boolean }) public disabled = false;
@property({ reflect: true, type: Boolean }) public narrow!: boolean;
@property() public config!: BlueprintAutomationConfig;
@ -50,6 +52,14 @@ export class HaBlueprintAutomationEditor extends LitElement {
protected render() {
const blueprint = this._blueprint;
return html`
${this.disabled
? html`<ha-alert alert-type="warning">
${this.hass.localize("ui.panel.config.automation.editor.read_only")}
<mwc-button slot="action" @click=${this._duplicate}>
${this.hass.localize("ui.panel.config.automation.editor.migrate")}
</mwc-button>
</ha-alert>`
: ""}
${this.stateObj?.state === "off"
? html`
<ha-alert alert-type="info">
@ -85,6 +95,7 @@ export class HaBlueprintAutomationEditor extends LitElement {
)}
.blueprints=${this._blueprints}
.value=${this.config.use_blueprint.path}
.disabled=${this.disabled}
@value-changed=${this._blueprintChanged}
></ha-blueprint-picker>
`
@ -126,6 +137,7 @@ export class HaBlueprintAutomationEditor extends LitElement {
.value=${(this.config.use_blueprint.input &&
this.config.use_blueprint.input[key]) ??
value?.default}
.disabled=${this.disabled}
@value-changed=${this._inputChanged}
></ha-selector>`
: html`<ha-textfield
@ -134,6 +146,7 @@ export class HaBlueprintAutomationEditor extends LitElement {
.value=${(this.config.use_blueprint.input &&
this.config.use_blueprint.input[key]) ??
value?.default}
.disabled=${this.disabled}
@input=${this._inputChanged}
></ha-textfield>`}
</ha-settings-row>`
@ -205,6 +218,10 @@ export class HaBlueprintAutomationEditor extends LitElement {
});
}
private _duplicate() {
fireEvent(this, "duplicate");
}
static get styles(): CSSResultGroup {
return [
haStyle,

View File

@ -26,6 +26,8 @@ export default class HaAutomationConditionEditor extends LitElement {
@property({ attribute: false }) condition!: Condition;
@property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public yamlMode = false;
@property({ type: Boolean }) public reOrderMode = false;
@ -56,6 +58,7 @@ export default class HaAutomationConditionEditor extends LitElement {
.hass=${this.hass}
.defaultValue=${this.condition}
@value-changed=${this._onYamlChange}
.readOnly=${this.disabled}
></ha-yaml-editor>
`
: html`
@ -66,6 +69,7 @@ export default class HaAutomationConditionEditor extends LitElement {
hass: this.hass,
condition: condition,
reOrderMode: this.reOrderMode,
disabled: this.disabled,
}
)}
</div>

View File

@ -74,6 +74,8 @@ export default class HaAutomationConditionRow extends LitElement {
@property({ type: Boolean }) public reOrderMode = false;
@property({ type: Boolean }) public disabled = false;
@state() private _yamlMode = false;
@state() private _warnings?: string[];
@ -131,7 +133,7 @@ export default class HaAutomationConditionRow extends LitElement {
)}
<ha-svg-icon slot="graphic" .path=${mdiFlask}></ha-svg-icon>
</mwc-list-item>
<mwc-list-item graphic="icon">
<mwc-list-item graphic="icon" .disabled=${this.disabled}>
${this.hass.localize(
"ui.panel.config.automation.editor.conditions.rename"
)}
@ -140,7 +142,7 @@ export default class HaAutomationConditionRow extends LitElement {
.path=${mdiRenameBox}
></ha-svg-icon>
</mwc-list-item>
<mwc-list-item graphic="icon">
<mwc-list-item graphic="icon" .disabled=${this.disabled}>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.duplicate"
)}
@ -180,7 +182,7 @@ export default class HaAutomationConditionRow extends LitElement {
<li divider role="separator"></li>
<mwc-list-item graphic="icon">
<mwc-list-item graphic="icon" .disabled=${this.disabled}>
${this.condition.enabled === false
? this.hass.localize(
"ui.panel.config.automation.editor.actions.enable"
@ -195,7 +197,11 @@ export default class HaAutomationConditionRow extends LitElement {
: mdiStopCircleOutline}
></ha-svg-icon>
</mwc-list-item>
<mwc-list-item class="warning" graphic="icon">
<mwc-list-item
class="warning"
graphic="icon"
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.delete"
)}
@ -238,6 +244,7 @@ export default class HaAutomationConditionRow extends LitElement {
@ui-mode-not-available=${this._handleUiModeNotAvailable}
@value-changed=${this._handleChangeEvent}
.yamlMode=${this._yamlMode}
.disabled=${this.disabled}
.hass=${this.hass}
.condition=${this.condition}
.reOrderMode=${this.reOrderMode}

View File

@ -42,6 +42,8 @@ export default class HaAutomationCondition extends LitElement {
@property() public conditions!: Condition[];
@property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public reOrderMode = false;
private _focusLastConditionOnChange = false;
@ -111,6 +113,7 @@ export default class HaAutomationCondition extends LitElement {
.condition=${cond}
.hideMenu=${this.reOrderMode}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
@duplicate=${this._duplicateCondition}
@move-condition=${this._move}
@value-changed=${this._conditionChanged}
@ -147,10 +150,15 @@ export default class HaAutomationCondition extends LitElement {
`
)}
</div>
<ha-button-menu fixed @action=${this._addCondition}>
<ha-button-menu
fixed
@action=${this._addCondition}
.disabled=${this.disabled}
>
<mwc-button
slot="trigger"
outlined
.disabled=${this.disabled}
.label=${this.hass.localize(
"ui.panel.config.automation.editor.conditions.add"
)}

View File

@ -19,6 +19,8 @@ export class HaDeviceCondition extends LitElement {
@property({ type: Object }) public condition!: DeviceCondition;
@property({ type: Boolean }) public disabled = false;
@state() private _deviceId?: string;
@state() private _capabilities?: DeviceCapabilities;
@ -53,7 +55,8 @@ export class HaDeviceCondition extends LitElement {
.value=${deviceId}
@value-changed=${this._devicePicked}
.hass=${this.hass}
label=${this.hass.localize(
.disabled=${this.disabled}
.label=${this.hass.localize(
"ui.panel.config.automation.editor.conditions.type.device.label"
)}
></ha-device-picker>
@ -62,7 +65,8 @@ export class HaDeviceCondition extends LitElement {
.deviceId=${deviceId}
@value-changed=${this._deviceConditionPicked}
.hass=${this.hass}
label=${this.hass.localize(
.disabled=${this.disabled}
.label=${this.hass.localize(
"ui.panel.config.automation.editor.conditions.type.device.condition"
)}
></ha-device-condition-picker>
@ -72,6 +76,7 @@ export class HaDeviceCondition extends LitElement {
.hass=${this.hass}
.data=${this._extraFieldsData(this.condition, this._capabilities)}
.schema=${this._capabilities.extra_fields}
.disabled=${this.disabled}
.computeLabel=${this._extraFieldsComputeLabelCallback(
this.hass.localize
)}

View File

@ -12,6 +12,8 @@ export class HaLogicalCondition extends LitElement implements ConditionElement {
@property({ attribute: false }) public condition!: LogicalCondition;
@property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public reOrderMode = false;
public static get defaultConfig() {
@ -26,6 +28,7 @@ export class HaLogicalCondition extends LitElement implements ConditionElement {
.conditions=${this.condition.conditions || []}
@value-changed=${this._valueChanged}
.hass=${this.hass}
.disabled=${this.disabled}
.reOrderMode=${this.reOrderMode}
></ha-automation-condition>
`;

View File

@ -13,6 +13,8 @@ export default class HaNumericStateCondition extends LitElement {
@property({ attribute: false }) public condition!: NumericStateCondition;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return {
entity_id: "",
@ -132,6 +134,7 @@ export default class HaNumericStateCondition extends LitElement {
.hass=${this.hass}
.data=${this.condition}
.schema=${schema}
.disabled=${this.disabled}
@value-changed=${this._valueChanged}
.computeLabel=${this._computeLabelCallback}
></ha-form>

View File

@ -26,6 +26,8 @@ export class HaStateCondition extends LitElement implements ConditionElement {
@property({ attribute: false }) public condition!: StateCondition;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return { entity_id: "", state: "" };
}
@ -100,6 +102,7 @@ export class HaStateCondition extends LitElement implements ConditionElement {
.hass=${this.hass}
.data=${data}
.schema=${schema}
.disabled=${this.disabled}
@value-changed=${this._valueChanged}
.computeLabel=${this._computeLabelCallback}
></ha-form>

View File

@ -15,6 +15,8 @@ export class HaSunCondition extends LitElement implements ConditionElement {
@property({ attribute: false }) public condition!: SunCondition;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return {};
}
@ -72,6 +74,7 @@ export class HaSunCondition extends LitElement implements ConditionElement {
.schema=${schema}
.data=${this.condition}
.hass=${this.hass}
.disabled=${this.disabled}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>

View File

@ -11,6 +11,8 @@ export class HaTemplateCondition extends LitElement {
@property({ attribute: false }) public condition!: TemplateCondition;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return { value_template: "" };
}
@ -29,6 +31,7 @@ export class HaTemplateCondition extends LitElement {
mode="jinja2"
.hass=${this.hass}
.value=${value_template}
.readOnly=${this.disabled}
autocomplete-entities
@value-changed=${this._valueChanged}
dir="ltr"

View File

@ -21,6 +21,8 @@ export class HaTimeCondition extends LitElement implements ConditionElement {
@state() private _inputModeAfter?: boolean;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return {};
}
@ -123,6 +125,7 @@ export class HaTimeCondition extends LitElement implements ConditionElement {
.hass=${this.hass}
.data=${data}
.schema=${schema}
.disabled=${this.disabled}
@value-changed=${this._valueChanged}
.computeLabel=${this._computeLabelCallback}
></ha-form>

View File

@ -18,6 +18,8 @@ export class HaTriggerCondition extends LitElement {
@property({ attribute: false }) public condition!: TriggerCondition;
@property({ type: Boolean }) public disabled = false;
@state() private _triggers: Trigger[] = [];
private _unsub?: UnsubscribeFunc;
@ -55,6 +57,7 @@ export class HaTriggerCondition extends LitElement {
"ui.panel.config.automation.editor.conditions.type.trigger.id"
)}
.value=${id}
.disabled=${this.disabled}
@selected=${this._triggerPicked}
>
${this._triggers.map(

View File

@ -20,6 +20,8 @@ export class HaZoneCondition extends LitElement {
@property({ attribute: false }) public condition!: ZoneCondition;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return {
entity_id: "",
@ -37,6 +39,7 @@ export class HaZoneCondition extends LitElement {
.value=${entity_id}
@value-changed=${this._entityPicked}
.hass=${this.hass}
.disabled=${this.disabled}
allow-custom-entity
.entityFilter=${zoneAndLocationFilter}
></ha-entity-picker>
@ -47,6 +50,7 @@ export class HaZoneCondition extends LitElement {
.value=${zone}
@value-changed=${this._zonePicked}
.hass=${this.hass}
.disabled=${this.disabled}
allow-custom-entity
.includeDomains=${includeDomains}
></ha-entity-picker>

View File

@ -43,7 +43,8 @@ import {
AutomationConfig,
AutomationEntity,
deleteAutomation,
getAutomationConfig,
getAutomationStateConfig,
fetchAutomationFileConfig,
getAutomationEditorInitData,
saveAutomationConfig,
showAutomationEditor,
@ -86,6 +87,8 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
@property() public automationId: string | null = null;
@property() public entityId: string | null = null;
@property() public automations!: AutomationEntity[];
@property() public isWide?: boolean;
@ -104,6 +107,8 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
@state() private _mode: "gui" | "yaml" = "gui";
@state() private _readOnly = false;
@query("ha-yaml-editor", true) private _yamlEditor?: HaYamlEditor;
@query("manual-automation-editor")
@ -198,7 +203,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
<mwc-list-item
graphic="icon"
@click=${this._promptAutomationMode}
.disabled=${this._mode === "yaml"}
.disabled=${this._readOnly || this._mode === "yaml"}
>
${this.hass.localize(
"ui.panel.config.automation.editor.change_mode"
@ -214,7 +219,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
? html`<mwc-list-item
graphic="icon"
@click=${this._toggleReOrderMode}
.disabled=${this._mode === "yaml"}
.disabled=${this._readOnly || this._mode === "yaml"}
>
${this.hass.localize(
"ui.panel.config.automation.editor.re_order"
@ -224,11 +229,15 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
: ""}
<mwc-list-item
.disabled=${!this.automationId}
.disabled=${!this._readOnly && !this.automationId}
graphic="icon"
@click=${this._duplicate}
>
${this.hass.localize("ui.panel.config.automation.picker.duplicate")}
${this.hass.localize(
this._readOnly
? "ui.panel.config.automation.editor.migrate"
: "ui.panel.config.automation.editor.duplicate"
)}
<ha-svg-icon
slot="graphic"
.path=${mdiContentDuplicate}
@ -314,7 +323,9 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
.isWide=${this.isWide}
.stateObj=${stateObj}
.config=${this._config}
.disabled=${Boolean(this._readOnly)}
@value-changed=${this._valueChanged}
@duplicate=${this._duplicate}
></blueprint-automation-editor>
`
: html`
@ -324,11 +335,25 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
.isWide=${this.isWide}
.stateObj=${stateObj}
.config=${this._config}
.disabled=${Boolean(this._readOnly)}
@value-changed=${this._valueChanged}
@duplicate=${this._duplicate}
></manual-automation-editor>
`
: this._mode === "yaml"
? html`
${this._readOnly
? html`<ha-alert alert-type="warning">
${this.hass.localize(
"ui.panel.config.automation.editor.read_only"
)}
<mwc-button slot="action" @click=${this._duplicate}>
${this.hass.localize(
"ui.panel.config.automation.editor.migrate"
)}
</mwc-button>
</ha-alert>`
: ""}
${stateObj?.state === "off"
? html`
<ha-alert alert-type="info">
@ -346,6 +371,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
<ha-yaml-editor
.hass=${this.hass}
.defaultValue=${this._preprocessYaml()}
.readOnly=${this._readOnly}
@value-changed=${this._yamlChanged}
></ha-yaml-editor>
<ha-card outlined>
@ -390,7 +416,12 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
this._loadConfig();
}
if (changedProps.has("automationId") && !this.automationId && this.hass) {
if (
changedProps.has("automationId") &&
!this.automationId &&
!this.entityId &&
this.hass
) {
const initData = getAutomationEditorInitData();
let baseConfig: Partial<AutomationConfig> = { description: "" };
if (!initData || !("use_blueprint" in initData)) {
@ -407,9 +438,19 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
...initData,
} as AutomationConfig;
this._entityId = undefined;
this._readOnly = false;
this._dirty = true;
}
if (changedProps.has("entityId") && this.entityId) {
getAutomationStateConfig(this.hass, this.entityId).then((c) => {
this._config = c.config;
});
this._entityId = this.entityId;
this._dirty = false;
this._readOnly = true;
}
if (
changedProps.has("automations") &&
this.automationId &&
@ -434,7 +475,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
private async _loadConfig() {
try {
const config = await getAutomationConfig(
const config = await fetchAutomationFileConfig(
this.hass,
this.automationId as string
);
@ -448,8 +489,19 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
}
}
this._dirty = false;
this._readOnly = false;
this._config = config;
} catch (err: any) {
const entity = Object.values(this.hass.entities).find(
(ent) =>
ent.platform === "automation" && ent.unique_id === this.automationId
);
if (entity) {
navigate(`/config/automation/show/${entity.entity_id}`, {
replace: true,
});
return;
}
await showAlertDialog(this, {
text:
err.status_code === 404
@ -468,6 +520,9 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
private _valueChanged(ev: CustomEvent<{ value: AutomationConfig }>) {
ev.stopPropagation();
if (this._readOnly) {
return;
}
this._config = ev.detail.value;
this._dirty = true;
this._errors = undefined;
@ -563,12 +618,17 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
};
private async _duplicate() {
const result = await this.confirmUnsavedChanged();
const result = this._readOnly
? await showConfirmationDialog(this, {
title: "Migrate automation?",
text: "You can migrate this automation, so it can be edited from the UI. After it is migrated and you have saved it, you will have to manually delete your old automation from your configuration. Do you want to migrate this automation?",
})
: await this.confirmUnsavedChanged();
if (result) {
showAutomationEditor({
...this._config,
id: undefined,
alias: undefined,
alias: this._readOnly ? this._config?.alias : undefined,
});
}
}

View File

@ -34,7 +34,7 @@ import {
AutomationEntity,
deleteAutomation,
duplicateAutomation,
getAutomationConfig,
fetchAutomationFileConfig,
triggerAutomationActions,
} from "../../../data/automation";
import {
@ -376,7 +376,7 @@ class HaAutomationPicker extends LitElement {
private async duplicate(automation) {
try {
const config = await getAutomationConfig(
const config = await fetchAutomationFileConfig(
this.hass,
automation.attributes.id
);
@ -424,6 +424,8 @@ class HaAutomationPicker extends LitElement {
if (automation?.attributes.id) {
navigate(`/config/automation/edit/${automation.attributes.id}`);
} else {
navigate(`/config/automation/show/${ev.detail.id}`);
}
}

View File

@ -49,6 +49,9 @@ class HaConfigAutomation extends HassRouterPage {
edit: {
tag: "ha-automation-editor",
},
show: {
tag: "ha-automation-editor",
},
trace: {
tag: "ha-automation-trace",
load: () => import("./ha-automation-trace"),
@ -84,13 +87,22 @@ class HaConfigAutomation extends HassRouterPage {
this._debouncedUpdateAutomations(pageEl);
}
}
if (
(!changedProps || changedProps.has("route")) &&
this._currentPage === "show"
) {
const automationId = decodeURIComponent(this.routeTail.path.substr(1));
pageEl.automationId = null;
pageEl.entityId = automationId === "new" ? null : automationId;
return;
}
if (
(!changedProps || changedProps.has("route")) &&
this._currentPage !== "dashboard"
) {
const automationId = decodeURIComponent(this.routeTail.path.substr(1));
pageEl.automationId = automationId === "new" ? null : automationId;
pageEl.entityId = null;
}
}
}

View File

@ -28,6 +28,8 @@ export class HaManualAutomationEditor extends LitElement {
@property({ type: Boolean }) public narrow!: boolean;
@property({ type: Boolean }) public disabled = false;
@property({ attribute: false }) public config!: ManualAutomationConfig;
@property({ attribute: false }) public stateObj?: HassEntity;
@ -37,6 +39,14 @@ export class HaManualAutomationEditor extends LitElement {
protected render() {
return html`
${this.disabled
? html`<ha-alert alert-type="warning">
${this.hass.localize("ui.panel.config.automation.editor.read_only")}
<mwc-button slot="action" @click=${this._duplicate}>
${this.hass.localize("ui.panel.config.automation.editor.migrate")}
</mwc-button>
</ha-alert>`
: ""}
${this.stateObj?.state === "off"
? html`
<ha-alert alert-type="info">
@ -100,6 +110,7 @@ export class HaManualAutomationEditor extends LitElement {
@value-changed=${this._triggerChanged}
.hass=${this.hass}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
></ha-automation-trigger>
<div class="header">
@ -129,6 +140,7 @@ export class HaManualAutomationEditor extends LitElement {
@value-changed=${this._conditionChanged}
.hass=${this.hass}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
></ha-automation-condition>
<div class="header">
@ -161,6 +173,7 @@ export class HaManualAutomationEditor extends LitElement {
.hass=${this.hass}
.narrow=${this.narrow}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
></ha-automation-action>
`;
}
@ -202,6 +215,10 @@ export class HaManualAutomationEditor extends LitElement {
});
}
private _duplicate() {
fireEvent(this, "duplicate");
}
static get styles(): CSSResultGroup {
return [
haStyle,

View File

@ -89,6 +89,8 @@ export default class HaAutomationTriggerRow extends LitElement {
@property({ type: Boolean }) public hideMenu = false;
@property({ type: Boolean }) public disabled = false;
@state() private _warnings?: string[];
@state() private _yamlMode = false;
@ -148,7 +150,7 @@ export default class HaAutomationTriggerRow extends LitElement {
.path=${mdiDotsVertical}
></ha-icon-button>
<mwc-list-item graphic="icon">
<mwc-list-item graphic="icon" .disabled=${this.disabled}>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.rename"
)}
@ -157,7 +159,7 @@ export default class HaAutomationTriggerRow extends LitElement {
.path=${mdiRenameBox}
></ha-svg-icon>
</mwc-list-item>
<mwc-list-item graphic="icon">
<mwc-list-item graphic="icon" .disabled=${this.disabled}>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.duplicate"
)}
@ -167,7 +169,7 @@ export default class HaAutomationTriggerRow extends LitElement {
></ha-svg-icon>
</mwc-list-item>
<mwc-list-item graphic="icon">
<mwc-list-item graphic="icon" .disabled=${this.disabled}>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.edit_id"
)}
@ -207,7 +209,7 @@ export default class HaAutomationTriggerRow extends LitElement {
<li divider role="separator"></li>
<mwc-list-item graphic="icon">
<mwc-list-item graphic="icon" .disabled=${this.disabled}>
${this.trigger.enabled === false
? this.hass.localize(
"ui.panel.config.automation.editor.actions.enable"
@ -222,7 +224,11 @@ export default class HaAutomationTriggerRow extends LitElement {
: mdiStopCircleOutline}
></ha-svg-icon>
</mwc-list-item>
<mwc-list-item class="warning" graphic="icon">
<mwc-list-item
class="warning"
graphic="icon"
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.delete"
)}
@ -273,6 +279,7 @@ export default class HaAutomationTriggerRow extends LitElement {
<ha-yaml-editor
.hass=${this.hass}
.defaultValue=${this.trigger}
.readOnly=${this.disabled}
@value-changed=${this._onYamlChange}
></ha-yaml-editor>
`
@ -292,7 +299,11 @@ export default class HaAutomationTriggerRow extends LitElement {
<div @ui-mode-not-available=${this._handleUiModeNotAvailable}>
${dynamicElement(
`ha-automation-trigger-${this.trigger.platform}`,
{ hass: this.hass, trigger: this.trigger }
{
hass: this.hass,
trigger: this.trigger,
disabled: this.disabled,
}
)}
</div>
`}

View File

@ -45,6 +45,8 @@ export default class HaAutomationTrigger extends LitElement {
@property({ type: Boolean }) public reOrderMode = false;
@property({ type: Boolean }) public disabled = false;
private _focusLastTriggerOnChange = false;
private _triggerKeys = new WeakMap<Trigger, string>();
@ -65,6 +67,7 @@ export default class HaAutomationTrigger extends LitElement {
@duplicate=${this._duplicateTrigger}
@value-changed=${this._triggerChanged}
.hass=${this.hass}
.disabled=${this.disabled}
>
${this.reOrderMode
? html`
@ -97,13 +100,14 @@ export default class HaAutomationTrigger extends LitElement {
`
)}
</div>
<ha-button-menu @action=${this._addTrigger}>
<ha-button-menu @action=${this._addTrigger} .disabled=${this.disabled}>
<mwc-button
slot="trigger"
outlined
.label=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.add"
)}
.disabled=${this.disabled}
>
<ha-svg-icon .path=${mdiPlus} slot="icon"></ha-svg-icon>
</mwc-button>

View File

@ -17,6 +17,8 @@ export class HaCalendarTrigger extends LitElement implements TriggerElement {
@property({ attribute: false }) public trigger!: CalendarTrigger;
@property({ type: Boolean }) public disabled = false;
private _schema = memoizeOne(
(localize: LocalizeFunc) =>
[
@ -97,6 +99,7 @@ export class HaCalendarTrigger extends LitElement implements TriggerElement {
.schema=${schema}
.data=${data}
.hass=${this.hass}
.disabled=${this.disabled}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>

View File

@ -19,6 +19,8 @@ export class HaDeviceTrigger extends LitElement {
@property({ type: Object }) public trigger!: DeviceTrigger;
@property({ type: Boolean }) public disabled = false;
@state() private _deviceId?: string;
@state() private _capabilities?: DeviceCapabilities;
@ -53,6 +55,7 @@ export class HaDeviceTrigger extends LitElement {
.value=${deviceId}
@value-changed=${this._devicePicked}
.hass=${this.hass}
.disabled=${this.disabled}
label=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.type.device.label"
)}
@ -62,6 +65,7 @@ export class HaDeviceTrigger extends LitElement {
.deviceId=${deviceId}
@value-changed=${this._deviceTriggerPicked}
.hass=${this.hass}
.disabled=${this.disabled}
label=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.type.device.trigger"
)}
@ -72,6 +76,7 @@ export class HaDeviceTrigger extends LitElement {
.hass=${this.hass}
.data=${this._extraFieldsData(this.trigger, this._capabilities)}
.schema=${this._capabilities.extra_fields}
.disabled=${this.disabled}
.computeLabel=${this._extraFieldsComputeLabelCallback(
this.hass.localize
)}

View File

@ -17,6 +17,8 @@ export class HaEventTrigger extends LitElement implements TriggerElement {
@property() public trigger!: EventTrigger;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return { event_type: "" };
}
@ -30,6 +32,7 @@ export class HaEventTrigger extends LitElement implements TriggerElement {
)}
name="event_type"
.value=${event_type}
.disabled=${this.disabled}
@change=${this._valueChanged}
></ha-textfield>
<ha-yaml-editor
@ -38,6 +41,7 @@ export class HaEventTrigger extends LitElement implements TriggerElement {
"ui.panel.config.automation.editor.triggers.type.event.event_data"
)}
.name=${"event_data"}
.readOnly=${this.disabled}
.defaultValue=${event_data}
@value-changed=${this._dataChanged}
></ha-yaml-editor>
@ -53,6 +57,7 @@ export class HaEventTrigger extends LitElement implements TriggerElement {
"ui.panel.config.automation.editor.triggers.type.event.context_user_pick"
)}
.hass=${this.hass}
.disabled=${this.disabled}
.value=${this._wrapUsersInArray(context?.user_id)}
@value-changed=${this._usersChanged}
></ha-users-picker>

View File

@ -14,6 +14,8 @@ export class HaGeolocationTrigger extends LitElement {
@property({ attribute: false }) public trigger!: GeoLocationTrigger;
@property({ type: Boolean }) public disabled = false;
private _schema = memoizeOne(
(localize: LocalizeFunc) =>
[
@ -55,6 +57,7 @@ export class HaGeolocationTrigger extends LitElement {
.schema=${this._schema(this.hass.localize)}
.data=${this.trigger}
.hass=${this.hass}
.disabled=${this.disabled}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>

View File

@ -14,6 +14,8 @@ export class HaHassTrigger extends LitElement {
@property({ attribute: false }) public trigger!: HassTrigger;
@property({ type: Boolean }) public disabled = false;
private _schema = memoizeOne(
(localize: LocalizeFunc) =>
[
@ -51,6 +53,7 @@ export class HaHassTrigger extends LitElement {
.schema=${this._schema(this.hass.localize)}
.data=${this.trigger}
.hass=${this.hass}
.disabled=${this.disabled}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>

View File

@ -18,6 +18,8 @@ export class HaMQTTTrigger extends LitElement implements TriggerElement {
@property({ attribute: false }) public trigger!: MqttTrigger;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return { topic: "" };
}
@ -28,6 +30,7 @@ export class HaMQTTTrigger extends LitElement implements TriggerElement {
.schema=${SCHEMA}
.data=${this.trigger}
.hass=${this.hass}
.disabled=${this.disabled}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>

View File

@ -15,6 +15,8 @@ export class HaNumericStateTrigger extends LitElement {
@property({ attribute: false }) public trigger!: NumericStateTrigger;
@property({ type: Boolean }) public disabled = false;
private _schema = memoizeOne(
(entityId) =>
[
@ -152,6 +154,7 @@ export class HaNumericStateTrigger extends LitElement {
.hass=${this.hass}
.data=${data}
.schema=${schema}
.disabled=${this.disabled}
@value-changed=${this._valueChanged}
.computeLabel=${this._computeLabelCallback}
></ha-form>

View File

@ -41,6 +41,8 @@ export class HaStateTrigger extends LitElement implements TriggerElement {
@property({ attribute: false }) public trigger!: StateTrigger;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return { entity_id: [] };
}
@ -155,6 +157,7 @@ export class HaStateTrigger extends LitElement implements TriggerElement {
.schema=${schema}
@value-changed=${this._valueChanged}
.computeLabel=${this._computeLabelCallback}
.disabled=${this.disabled}
></ha-form>
`;
}

View File

@ -15,6 +15,8 @@ export class HaSunTrigger extends LitElement implements TriggerElement {
@property({ attribute: false }) public trigger!: SunTrigger;
@property({ type: Boolean }) public disabled = false;
private _schema = memoizeOne(
(localize: LocalizeFunc) =>
[
@ -55,6 +57,7 @@ export class HaSunTrigger extends LitElement implements TriggerElement {
.schema=${schema}
.data=${this.trigger}
.hass=${this.hass}
.disabled=${this.disabled}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>

View File

@ -15,6 +15,8 @@ export class HaTagTrigger extends LitElement implements TriggerElement {
@property() public trigger!: TagTrigger;
@property({ type: Boolean }) public disabled = false;
@state() private _tags?: Tag[];
public static get defaultConfig() {
@ -35,7 +37,7 @@ export class HaTagTrigger extends LitElement implements TriggerElement {
.label=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.type.tag.label"
)}
.disabled=${this._tags.length === 0}
.disabled=${this.disabled || this._tags.length === 0}
.value=${this.trigger.tag_id}
@selected=${this._tagChanged}
>

View File

@ -11,6 +11,8 @@ export class HaTemplateTrigger extends LitElement {
@property({ attribute: false }) public trigger!: TemplateTrigger;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return { value_template: "" };
}
@ -29,6 +31,7 @@ export class HaTemplateTrigger extends LitElement {
mode="jinja2"
.hass=${this.hass}
.value=${value_template}
.readOnly=${this.disabled}
autocomplete-entities
@value-changed=${this._valueChanged}
dir="ltr"

View File

@ -15,6 +15,8 @@ export class HaTimeTrigger extends LitElement implements TriggerElement {
@property({ attribute: false }) public trigger!: TimeTrigger;
@property({ type: Boolean }) public disabled = false;
@state() private _inputMode?: boolean;
public static get defaultConfig() {
@ -89,6 +91,7 @@ export class HaTimeTrigger extends LitElement implements TriggerElement {
.hass=${this.hass}
.data=${data}
.schema=${schema}
.disabled=${this.disabled}
@value-changed=${this._valueChanged}
.computeLabel=${this._computeLabelCallback}
></ha-form>

View File

@ -19,6 +19,8 @@ export class HaTimePatternTrigger extends LitElement implements TriggerElement {
@property({ attribute: false }) public trigger!: TimePatternTrigger;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return {};
}
@ -29,6 +31,7 @@ export class HaTimePatternTrigger extends LitElement implements TriggerElement {
.hass=${this.hass}
.schema=${SCHEMA}
.data=${this.trigger}
.disabled=${this.disabled}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>

View File

@ -24,6 +24,8 @@ export class HaWebhookTrigger extends LitElement {
@property() public trigger!: WebhookTrigger;
@property({ type: Boolean }) public disabled = false;
@state() private _config?: AutomationConfig;
private _unsub?: UnsubscribeFunc;
@ -88,6 +90,7 @@ export class HaWebhookTrigger extends LitElement {
.helper=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.type.webhook.webhook_id_helper"
)}
.disabled=${this.disabled}
iconTrailing
.value=${webhookId || ""}
@input=${this._valueChanged}

View File

@ -22,6 +22,8 @@ export class HaZoneTrigger extends LitElement {
@property() public trigger!: ZoneTrigger;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return {
entity_id: "",
@ -38,6 +40,7 @@ export class HaZoneTrigger extends LitElement {
"ui.panel.config.automation.editor.triggers.type.zone.entity"
)}
.value=${entity_id}
.disabled=${this.disabled}
@value-changed=${this._entityPicked}
.hass=${this.hass}
allow-custom-entity
@ -48,6 +51,7 @@ export class HaZoneTrigger extends LitElement {
"ui.panel.config.automation.editor.triggers.type.zone.zone"
)}
.value=${zone}
.disabled=${this.disabled}
@value-changed=${this._zonePicked}
.hass=${this.hass}
allow-custom-entity
@ -59,6 +63,7 @@ export class HaZoneTrigger extends LitElement {
"ui.panel.config.automation.editor.triggers.type.zone.event"
)}
<ha-formfield
.disabled=${this.disabled}
.label=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.type.zone.enter"
)}
@ -66,11 +71,13 @@ export class HaZoneTrigger extends LitElement {
<ha-radio
name="event"
value="enter"
.disabled=${this.disabled}
.checked=${event === "enter"}
@change=${this._radioGroupPicked}
></ha-radio>
</ha-formfield>
<ha-formfield
.disabled=${this.disabled}
.label=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.type.zone.leave"
)}
@ -78,6 +85,7 @@ export class HaZoneTrigger extends LitElement {
<ha-radio
name="event"
value="leave"
.disabled=${this.disabled}
.checked=${event === "leave"}
@change=${this._radioGroupPicked}
></ha-radio>

View File

@ -1847,6 +1847,8 @@
"enable": "[%key:ui::common::enable%]",
"disable": "[%key:ui::common::disable%]",
"disabled": "Automation is disabled",
"read_only": "This automation can not be edited from the UI, because it is not stored in the automations.yaml file, or doesn't have an ID.",
"migrate": "Migrate",
"run": "[%key:ui::panel::config::automation::editor::actions::run%]",
"rename": "[%key:ui::panel::config::automation::editor::triggers::rename%]",
"show_trace": "Traces",