mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-30 12:46:35 +00:00
WIP
This commit is contained in:
parent
b20d489bdd
commit
d74fe9f012
138
src/components/ha-automation-row.ts
Normal file
138
src/components/ha-automation-row.ts
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
import type { TemplateResult } from "lit";
|
||||||
|
import { css, html, LitElement } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import "./ha-svg-icon";
|
||||||
|
|
||||||
|
@customElement("ha-automation-row")
|
||||||
|
export class HaAutomationRow extends LitElement {
|
||||||
|
@property() header?: string;
|
||||||
|
|
||||||
|
@property() secondary?: string;
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<div class="top">
|
||||||
|
<div
|
||||||
|
id="summary"
|
||||||
|
@click=${this._toggleContainer}
|
||||||
|
@keydown=${this._toggleContainer}
|
||||||
|
role="button"
|
||||||
|
>
|
||||||
|
<slot name="leading-icon"></slot>
|
||||||
|
<slot name="header">
|
||||||
|
<div class="header">
|
||||||
|
${this.header}
|
||||||
|
<slot class="secondary" name="secondary">${this.secondary}</slot>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
<slot name="icons"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _toggleContainer(ev): Promise<void> {
|
||||||
|
if (ev.defaultPrevented) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ev.type === "keydown" && ev.key !== "Enter" && ev.key !== " ") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
this.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = css`
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: var(--ha-card-border-radius, 12px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.top.expanded {
|
||||||
|
border-bottom-left-radius: 0px;
|
||||||
|
border-bottom-right-radius: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top.focused {
|
||||||
|
background: var(--input-fill-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([outlined]) {
|
||||||
|
box-shadow: none;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: var(--outline-color);
|
||||||
|
border-radius: var(--ha-card-border-radius, 12px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-icon {
|
||||||
|
transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
direction: var(--direction);
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-inline-start: 8px;
|
||||||
|
margin-inline-end: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([left-chevron]) .summary-icon,
|
||||||
|
::slotted([slot="leading-icon"]) {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-inline-start: 0;
|
||||||
|
margin-inline-end: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summary {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
padding: var(--expansion-panel-summary-padding, 0 8px);
|
||||||
|
min-height: 48px;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
font-weight: var(--ha-font-weight-medium);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
#summary.noCollapse {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-icon.expanded {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header,
|
||||||
|
::slotted([slot="header"]) {
|
||||||
|
flex: 1;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding: var(--expansion-panel-content-padding, 0 8px);
|
||||||
|
overflow: hidden;
|
||||||
|
transition: height 300ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container.expanded {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary {
|
||||||
|
display: block;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
font-size: var(--ha-font-size-s);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-automation-row": HaAutomationRow;
|
||||||
|
}
|
||||||
|
}
|
@ -55,7 +55,11 @@ class HassSubpage extends LitElement {
|
|||||||
<div class="main-title"><slot name="header">${this.header}</slot></div>
|
<div class="main-title"><slot name="header">${this.header}</slot></div>
|
||||||
<slot name="toolbar-icon"></slot>
|
<slot name="toolbar-icon"></slot>
|
||||||
</div>
|
</div>
|
||||||
<div class="content ha-scrollbar" @scroll=${this._saveScrollPos}>
|
<div
|
||||||
|
class="content ha-scrollbar"
|
||||||
|
@scroll=${this._saveScrollPos}
|
||||||
|
@scroll-to=${this._scrollTo}
|
||||||
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
<div id="fab">
|
<div id="fab">
|
||||||
@ -69,6 +73,15 @@ class HassSubpage extends LitElement {
|
|||||||
this._savedScrollPos = (e.target as HTMLDivElement).scrollTop;
|
this._savedScrollPos = (e.target as HTMLDivElement).scrollTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _scrollTo(e: CustomEvent<{ up: number }>): void {
|
||||||
|
this.renderRoot
|
||||||
|
.querySelector(".content")!
|
||||||
|
.scrollTo(
|
||||||
|
0,
|
||||||
|
e.detail.up + this.renderRoot.querySelector(".content")?.scrollTop
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private _backTapped(): void {
|
private _backTapped(): void {
|
||||||
if (this.backCallback) {
|
if (this.backCallback) {
|
||||||
this.backCallback();
|
this.backCallback();
|
||||||
|
@ -203,7 +203,7 @@ export default class HaAutomationActionRow extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: nothing}
|
: nothing}
|
||||||
<ha-expansion-panel left-chevron>
|
<ha-automation-row>
|
||||||
${type === "service" && "action" in this.action && this.action.action
|
${type === "service" && "action" in this.action && this.action.action
|
||||||
? html`
|
? html`
|
||||||
<ha-service-icon
|
<ha-service-icon
|
||||||
@ -328,16 +328,6 @@ export default class HaAutomationActionRow extends LitElement {
|
|||||||
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
|
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
|
||||||
></ha-md-menu-item>
|
></ha-md-menu-item>
|
||||||
|
|
||||||
<ha-md-menu-item
|
|
||||||
.clickAction=${this._toggleYamlMode}
|
|
||||||
.disabled=${!this._uiModeAvailable}
|
|
||||||
>
|
|
||||||
${this.hass.localize(
|
|
||||||
`ui.panel.config.automation.editor.edit_${!yamlMode ? "yaml" : "ui"}`
|
|
||||||
)}
|
|
||||||
<ha-svg-icon slot="start" .path=${mdiPlaylistEdit}></ha-svg-icon>
|
|
||||||
</ha-md-menu-item>
|
|
||||||
|
|
||||||
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
||||||
|
|
||||||
<ha-md-menu-item
|
<ha-md-menu-item
|
||||||
@ -430,7 +420,7 @@ export default class HaAutomationActionRow extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
`}
|
`}
|
||||||
</div>
|
</div>
|
||||||
</ha-expansion-panel>
|
</ha-automation-row>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -676,8 +666,8 @@ export default class HaAutomationActionRow extends LitElement {
|
|||||||
}
|
}
|
||||||
:host([highlight]) ha-card {
|
:host([highlight]) ha-card {
|
||||||
--shadow-default: var(--ha-card-box-shadow, 0 0 0 0 transparent);
|
--shadow-default: var(--ha-card-box-shadow, 0 0 0 0 transparent);
|
||||||
--shadow-focus: 0 0 0 1px var(--state-inactive-color);
|
--shadow-focus: 0 0 0 1px var(--primary-color);
|
||||||
border-color: var(--state-inactive-color);
|
border-color: var(--primary-color);
|
||||||
box-shadow: var(--shadow-default), var(--shadow-focus);
|
box-shadow: var(--shadow-default), var(--shadow-focus);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
@ -93,6 +93,7 @@ export default class HaAutomationAction extends LitElement {
|
|||||||
@move-down=${this._moveDown}
|
@move-down=${this._moveDown}
|
||||||
@move-up=${this._moveUp}
|
@move-up=${this._moveUp}
|
||||||
@value-changed=${this._actionChanged}
|
@value-changed=${this._actionChanged}
|
||||||
|
@click=${this._actionClicked}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
?highlight=${this.highlightedActions?.includes(action)}
|
?highlight=${this.highlightedActions?.includes(action)}
|
||||||
>
|
>
|
||||||
@ -102,8 +103,74 @@ export default class HaAutomationAction extends LitElement {
|
|||||||
<ha-svg-icon .path=${mdiDrag}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiDrag}></ha-svg-icon>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: nothing}
|
: nothing} </ha-automation-action-row
|
||||||
</ha-automation-action-row>
|
>${Object.keys(action)[0] === "choose"
|
||||||
|
? html`<div
|
||||||
|
style="padding-left: 24px; border-left: 1px solid var(--primary-color);"
|
||||||
|
>
|
||||||
|
<ha-card outlined
|
||||||
|
><ha-automation-row>
|
||||||
|
<h3
|
||||||
|
slot="header"
|
||||||
|
style=" margin: 0;
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: inherit;"
|
||||||
|
>
|
||||||
|
Option 1:
|
||||||
|
</h3>
|
||||||
|
</ha-automation-row></ha-card
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="padding-left: 24px; border-left: 1px solid var(--primary-color); margin-top: 8px;"
|
||||||
|
>
|
||||||
|
<ha-automation-condition></ha-automation-condition>
|
||||||
|
<ha-button
|
||||||
|
outlined
|
||||||
|
style=" padding: 16px 0; padding-top: 8px;"
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
.label=${"Condition"}
|
||||||
|
>
|
||||||
|
<ha-svg-icon .path=${mdiPlus} slot="icon"></ha-svg-icon>
|
||||||
|
</ha-button>
|
||||||
|
<ha-card style=" padding: 0 16px;
|
||||||
|
padding-top: 8px;"
|
||||||
|
>Actions</br>
|
||||||
|
<ha-button
|
||||||
|
style=" padding: 16px 0;"
|
||||||
|
outlined
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
.label=${"Action"}
|
||||||
|
>
|
||||||
|
<ha-svg-icon
|
||||||
|
.path=${mdiPlus}
|
||||||
|
slot="icon"
|
||||||
|
></ha-svg-icon> </ha-button
|
||||||
|
></ha-card>
|
||||||
|
</div>
|
||||||
|
<ha-button
|
||||||
|
outlined
|
||||||
|
style=" padding: 16px 0;"
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
.label=${"Option"}
|
||||||
|
>
|
||||||
|
<ha-svg-icon .path=${mdiPlus} slot="icon"></ha-svg-icon>
|
||||||
|
</ha-button>
|
||||||
|
<ha-card style=" padding: 0 16px;
|
||||||
|
padding-top: 8px;"
|
||||||
|
>Default actions</br>
|
||||||
|
<ha-button
|
||||||
|
style=" padding: 16px 0;"
|
||||||
|
outlined
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
.label=${"Action"}
|
||||||
|
>
|
||||||
|
<ha-svg-icon
|
||||||
|
.path=${mdiPlus}
|
||||||
|
slot="icon"
|
||||||
|
></ha-svg-icon></ha-button
|
||||||
|
></ha-card>
|
||||||
|
</div>`
|
||||||
|
: nothing}
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
@ -132,6 +199,15 @@ export default class HaAutomationAction extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _actionClicked(ev: MouseEvent) {
|
||||||
|
fireEvent(this, "element-selected", {
|
||||||
|
type: "action",
|
||||||
|
element: (ev.currentTarget as HaAutomationActionRow).action,
|
||||||
|
index: (ev.currentTarget as HaAutomationActionRow).index,
|
||||||
|
path: (ev.currentTarget as HaAutomationActionRow).path,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues) {
|
protected updated(changedProps: PropertyValues) {
|
||||||
super.updated(changedProps);
|
super.updated(changedProps);
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ export default class HaAutomationConditionRow extends LitElement {
|
|||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
|
|
||||||
<ha-expansion-panel left-chevron>
|
<ha-automation-row>
|
||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
slot="leading-icon"
|
slot="leading-icon"
|
||||||
class="condition-icon"
|
class="condition-icon"
|
||||||
@ -225,16 +225,6 @@ export default class HaAutomationConditionRow extends LitElement {
|
|||||||
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
|
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
|
||||||
></ha-md-menu-item>
|
></ha-md-menu-item>
|
||||||
|
|
||||||
<ha-md-menu-item
|
|
||||||
.clickAction=${this._toggleYamlMode}
|
|
||||||
.disabled=${this._warnings}
|
|
||||||
>
|
|
||||||
${this.hass.localize(
|
|
||||||
`ui.panel.config.automation.editor.edit_${!this._yamlMode ? "yaml" : "ui"}`
|
|
||||||
)}
|
|
||||||
<ha-svg-icon slot="start" .path=${mdiPlaylistEdit}></ha-svg-icon>
|
|
||||||
</ha-md-menu-item>
|
|
||||||
|
|
||||||
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
||||||
|
|
||||||
<ha-md-menu-item
|
<ha-md-menu-item
|
||||||
@ -297,16 +287,8 @@ export default class HaAutomationConditionRow extends LitElement {
|
|||||||
)}
|
)}
|
||||||
</ha-alert>`
|
</ha-alert>`
|
||||||
: ""}
|
: ""}
|
||||||
<ha-automation-condition-editor
|
|
||||||
@ui-mode-not-available=${this._handleUiModeNotAvailable}
|
|
||||||
@value-changed=${this._handleChangeEvent}
|
|
||||||
.yamlMode=${this._yamlMode}
|
|
||||||
.disabled=${this.disabled}
|
|
||||||
.hass=${this.hass}
|
|
||||||
.condition=${this.condition}
|
|
||||||
></ha-automation-condition-editor>
|
|
||||||
</div>
|
</div>
|
||||||
</ha-expansion-panel>
|
</ha-automation-row>
|
||||||
<div
|
<div
|
||||||
class="testing ${classMap({
|
class="testing ${classMap({
|
||||||
active: this._testing,
|
active: this._testing,
|
||||||
@ -589,8 +571,8 @@ export default class HaAutomationConditionRow extends LitElement {
|
|||||||
}
|
}
|
||||||
:host([highlight]) ha-card {
|
:host([highlight]) ha-card {
|
||||||
--shadow-default: var(--ha-card-box-shadow, 0 0 0 0 transparent);
|
--shadow-default: var(--ha-card-box-shadow, 0 0 0 0 transparent);
|
||||||
--shadow-focus: 0 0 0 1px var(--state-inactive-color);
|
--shadow-focus: 0 0 0 1px var(--primary-color);
|
||||||
border-color: var(--state-inactive-color);
|
border-color: var(--primary-color);
|
||||||
box-shadow: var(--shadow-default), var(--shadow-focus);
|
box-shadow: var(--shadow-default), var(--shadow-focus);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
@ -142,6 +142,7 @@ export default class HaAutomationCondition extends LitElement {
|
|||||||
@move-down=${this._moveDown}
|
@move-down=${this._moveDown}
|
||||||
@move-up=${this._moveUp}
|
@move-up=${this._moveUp}
|
||||||
@value-changed=${this._conditionChanged}
|
@value-changed=${this._conditionChanged}
|
||||||
|
@click=${this._conditionClicked}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
?highlight=${this.highlightedConditions?.includes(cond)}
|
?highlight=${this.highlightedConditions?.includes(cond)}
|
||||||
>
|
>
|
||||||
@ -181,6 +182,15 @@ export default class HaAutomationCondition extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _conditionClicked(ev: MouseEvent) {
|
||||||
|
fireEvent(this, "element-selected", {
|
||||||
|
type: "condition",
|
||||||
|
element: (ev.currentTarget as HaAutomationConditionRow).condition,
|
||||||
|
index: (ev.currentTarget as HaAutomationConditionRow).index,
|
||||||
|
path: (ev.currentTarget as HaAutomationConditionRow).path,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private _addConditionDialog() {
|
private _addConditionDialog() {
|
||||||
showAddAutomationElementDialog(this, {
|
showAddAutomationElementDialog(this, {
|
||||||
type: "condition",
|
type: "condition",
|
||||||
|
@ -1092,7 +1092,6 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
manual-automation-editor,
|
|
||||||
blueprint-automation-editor,
|
blueprint-automation-editor,
|
||||||
:not(.yaml-mode) > ha-alert {
|
:not(.yaml-mode) > ha-alert {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@ -1100,6 +1099,12 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
|
|||||||
padding: 28px 20px 0;
|
padding: 28px 20px 0;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
manual-automation-editor {
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 1540px;
|
||||||
|
padding: 28px 20px 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
ha-yaml-editor {
|
ha-yaml-editor {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
--actions-border-radius: 0;
|
--actions-border-radius: 0;
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
import "@material/mwc-button/mwc-button";
|
||||||
import { mdiHelpCircle } from "@mdi/js";
|
import {
|
||||||
|
mdiClose,
|
||||||
|
mdiDotsVertical,
|
||||||
|
mdiHelpCircle,
|
||||||
|
mdiIdentifier,
|
||||||
|
mdiPlaylistEdit,
|
||||||
|
} from "@mdi/js";
|
||||||
import type { HassEntity } from "home-assistant-js-websocket";
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
import type { CSSResultGroup, PropertyValues } from "lit";
|
import type { CSSResultGroup, PropertyValues } from "lit";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
@ -49,6 +55,51 @@ import { constructUrlCurrentPath } from "../../../common/url/construct-url";
|
|||||||
import { canOverrideAlphanumericInput } from "../../../common/dom/can-override-input";
|
import { canOverrideAlphanumericInput } from "../../../common/dom/can-override-input";
|
||||||
import { showToast } from "../../../util/toast";
|
import { showToast } from "../../../util/toast";
|
||||||
import { showPasteReplaceDialog } from "./paste-replace-dialog/show-dialog-paste-replace";
|
import { showPasteReplaceDialog } from "./paste-replace-dialog/show-dialog-paste-replace";
|
||||||
|
import "@shoelace-style/shoelace/dist/components/split-panel/split-panel";
|
||||||
|
import "@shoelace-style/shoelace/dist/components/drawer/drawer";
|
||||||
|
import { dynamicElement } from "../../../common/dom/dynamic-element-directive";
|
||||||
|
import { classMap } from "lit/directives/class-map";
|
||||||
|
import { getType } from "./action/ha-automation-action-row";
|
||||||
|
import { storage } from "../../../common/decorators/storage";
|
||||||
|
import { nextRender } from "../../../common/util/render-status";
|
||||||
|
import {
|
||||||
|
DIRECTION_ALL,
|
||||||
|
DIRECTION_VERTICAL,
|
||||||
|
Manager,
|
||||||
|
Pan,
|
||||||
|
Swipe,
|
||||||
|
} from "@egjs/hammerjs";
|
||||||
|
|
||||||
|
function findNestedItem(
|
||||||
|
obj: any,
|
||||||
|
path: ItemPath,
|
||||||
|
createNonExistingPath?: boolean
|
||||||
|
): any {
|
||||||
|
return path.reduce((ac, p, index, array) => {
|
||||||
|
if (ac === undefined) return undefined;
|
||||||
|
if (!ac[p] && createNonExistingPath) {
|
||||||
|
const nextP = array[index + 1];
|
||||||
|
// Create object or array depending on next path
|
||||||
|
if (nextP === undefined || typeof nextP === "number") {
|
||||||
|
ac[p] = [];
|
||||||
|
} else {
|
||||||
|
ac[p] = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ac[p];
|
||||||
|
}, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateNestedItem(obj: any, path: ItemPath, newValue): any {
|
||||||
|
const lastKey = path.pop()!;
|
||||||
|
const parent = findNestedItem(obj, path);
|
||||||
|
parent[lastKey] = newValue
|
||||||
|
? newValue
|
||||||
|
: Array.isArray(parent[lastKey])
|
||||||
|
? [...parent[lastKey]]
|
||||||
|
: [parent[lastKey]];
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
const baseConfigStruct = object({
|
const baseConfigStruct = object({
|
||||||
alias: optional(string()),
|
alias: optional(string()),
|
||||||
@ -85,6 +136,14 @@ export class HaManualAutomationEditor extends LitElement {
|
|||||||
|
|
||||||
@state() private _pastedConfig?: ManualAutomationConfig;
|
@state() private _pastedConfig?: ManualAutomationConfig;
|
||||||
|
|
||||||
|
@state() private _selectedElement?: any;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
@storage({ key: "automationSidebarPosition" })
|
||||||
|
private _sidebarWidth = 99999;
|
||||||
|
|
||||||
|
@state() private _yamlMode = false;
|
||||||
|
|
||||||
private _previousConfig?: ManualAutomationConfig;
|
private _previousConfig?: ManualAutomationConfig;
|
||||||
|
|
||||||
public connectedCallback() {
|
public connectedCallback() {
|
||||||
@ -114,6 +173,13 @@ export class HaManualAutomationEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected updated(changedProps: PropertyValues): void {
|
||||||
|
super.updated(changedProps);
|
||||||
|
if (changedProps.has("narrow") && this.narrow && this._selectedElement) {
|
||||||
|
this.renderRoot.querySelector("sl-drawer").show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _clearParam(param: string) {
|
private _clearParam(param: string) {
|
||||||
window.history.replaceState(
|
window.history.replaceState(
|
||||||
null,
|
null,
|
||||||
@ -123,151 +189,411 @@ export class HaManualAutomationEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html`
|
const selectedElement = this._selectedElement?.element;
|
||||||
${this.stateObj?.state === "off"
|
const selectedElementType = this._selectedElement?.type;
|
||||||
? html`
|
const path = this._selectedElement?.path || [];
|
||||||
<ha-alert alert-type="info">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.disabled"
|
|
||||||
)}
|
|
||||||
<mwc-button slot="action" @click=${this._enable}>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.enable"
|
|
||||||
)}
|
|
||||||
</mwc-button>
|
|
||||||
</ha-alert>
|
|
||||||
`
|
|
||||||
: nothing}
|
|
||||||
${this.config.description
|
|
||||||
? html`<ha-markdown
|
|
||||||
class="description"
|
|
||||||
breaks
|
|
||||||
.content=${this.config.description}
|
|
||||||
></ha-markdown>`
|
|
||||||
: nothing}
|
|
||||||
<div class="header">
|
|
||||||
<h2 id="triggers-heading" class="name">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.triggers.header"
|
|
||||||
)}
|
|
||||||
</h2>
|
|
||||||
<a
|
|
||||||
href=${documentationUrl(this.hass, "/docs/automation/trigger/")}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
>
|
|
||||||
<ha-icon-button
|
|
||||||
.path=${mdiHelpCircle}
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.triggers.learn_more"
|
|
||||||
)}
|
|
||||||
></ha-icon-button>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
${!ensureArray(this.config.triggers)?.length
|
|
||||||
? html`<p>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.triggers.description"
|
|
||||||
)}
|
|
||||||
</p>`
|
|
||||||
: nothing}
|
|
||||||
|
|
||||||
<ha-automation-trigger
|
const type = "";
|
||||||
role="region"
|
const supported = true;
|
||||||
aria-labelledby="triggers-heading"
|
const yamlMode = this._yamlMode;
|
||||||
.triggers=${this.config.triggers || []}
|
|
||||||
.highlightedTriggers=${this._pastedConfig?.triggers || []}
|
|
||||||
.path=${["triggers"]}
|
|
||||||
@value-changed=${this._triggerChanged}
|
|
||||||
.hass=${this.hass}
|
|
||||||
.disabled=${this.disabled}
|
|
||||||
></ha-automation-trigger>
|
|
||||||
|
|
||||||
<div class="header">
|
const sidePanel = this._selectedElement
|
||||||
<h2 id="conditions-heading" class="name">
|
? html`<ha-dialog-header>
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.conditions.header"
|
|
||||||
)}
|
|
||||||
<span class="small"
|
|
||||||
>(${this.hass.localize("ui.common.optional")})</span
|
|
||||||
>
|
|
||||||
</h2>
|
|
||||||
<a
|
|
||||||
href=${documentationUrl(this.hass, "/docs/automation/condition/")}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
>
|
|
||||||
<ha-icon-button
|
|
||||||
.path=${mdiHelpCircle}
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.conditions.learn_more"
|
|
||||||
)}
|
|
||||||
></ha-icon-button>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
${!ensureArray(this.config.conditions)?.length
|
|
||||||
? html`<p>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.conditions.description",
|
|
||||||
{ user: this.hass.user?.name || "Alice" }
|
|
||||||
)}
|
|
||||||
</p>`
|
|
||||||
: nothing}
|
|
||||||
|
|
||||||
<ha-automation-condition
|
|
||||||
role="region"
|
|
||||||
aria-labelledby="conditions-heading"
|
|
||||||
.conditions=${this.config.conditions || []}
|
|
||||||
.highlightedConditions=${this._pastedConfig?.conditions || []}
|
|
||||||
.path=${["conditions"]}
|
|
||||||
@value-changed=${this._conditionChanged}
|
|
||||||
.hass=${this.hass}
|
|
||||||
.disabled=${this.disabled}
|
|
||||||
></ha-automation-condition>
|
|
||||||
|
|
||||||
<div class="header">
|
|
||||||
<h2 id="actions-heading" class="name">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.actions.header"
|
|
||||||
)}
|
|
||||||
</h2>
|
|
||||||
<div>
|
|
||||||
<a
|
|
||||||
href=${documentationUrl(this.hass, "/docs/automation/action/")}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
>
|
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
.path=${mdiHelpCircle}
|
slot="navigationIcon"
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize("ui.common.close")}
|
||||||
"ui.panel.config.automation.editor.actions.learn_more"
|
.path=${mdiClose}
|
||||||
)}
|
@click=${this._closeSidebar}
|
||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
</a>
|
<span slot="title">${`Edit ${selectedElementType}`}</span>
|
||||||
</div>
|
<ha-button-menu slot="actionItems" fixed>
|
||||||
</div>
|
<ha-icon-button
|
||||||
${!ensureArray(this.config.actions)?.length
|
.path=${mdiDotsVertical}
|
||||||
? html`<p>
|
slot="trigger"
|
||||||
${this.hass.localize(
|
></ha-icon-button>
|
||||||
"ui.panel.config.automation.editor.actions.description"
|
${selectedElementType === "trigger"
|
||||||
)}
|
? html`<ha-md-menu-item
|
||||||
</p>`
|
.clickAction=${this._showTriggerId}
|
||||||
: nothing}
|
.disabled=${this.disabled || type === "list"}
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.edit_id"
|
||||||
|
)}
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="start"
|
||||||
|
.path=${mdiIdentifier}
|
||||||
|
></ha-svg-icon>
|
||||||
|
</ha-md-menu-item>`
|
||||||
|
: nothing}
|
||||||
|
<ha-md-menu-item
|
||||||
|
@click=${this._toggleYamlMode}
|
||||||
|
.disabled=${!supported}
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
|
`ui.panel.config.automation.editor.edit_${!yamlMode ? "yaml" : "ui"}`
|
||||||
|
)}
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="start"
|
||||||
|
.path=${mdiPlaylistEdit}
|
||||||
|
></ha-svg-icon>
|
||||||
|
</ha-md-menu-item>
|
||||||
|
</ha-button-menu>
|
||||||
|
</ha-dialog-header>
|
||||||
|
<div
|
||||||
|
class=${classMap({
|
||||||
|
"card-content": true,
|
||||||
|
disabled:
|
||||||
|
"enabled" in this._selectedElement &&
|
||||||
|
this._selectedElement.enabled === false,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
${this._yamlMode
|
||||||
|
? html`<ha-yaml-editor
|
||||||
|
.hass=${this.hass}
|
||||||
|
.defaultValue=${selectedElement}
|
||||||
|
.readOnly=${this.disabled}
|
||||||
|
@value-changed=${this._onYamlChange}
|
||||||
|
></ha-yaml-editor>`
|
||||||
|
: selectedElementType === "trigger"
|
||||||
|
? html`<div
|
||||||
|
@ui-mode-not-available=${this._handleUiModeNotAvailable}
|
||||||
|
@value-changed=${this._onUiChanged}
|
||||||
|
.path=${path}
|
||||||
|
>
|
||||||
|
${dynamicElement(
|
||||||
|
`ha-automation-trigger-${selectedElement.trigger}`,
|
||||||
|
{
|
||||||
|
hass: this.hass,
|
||||||
|
trigger: selectedElement,
|
||||||
|
disabled: this.disabled,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</div>`
|
||||||
|
: selectedElementType === "condition"
|
||||||
|
? html`<ha-automation-condition-editor
|
||||||
|
@ui-mode-not-available=${this._handleUiModeNotAvailable}
|
||||||
|
@value-changed=${this._onUiChanged}
|
||||||
|
.path=${path}
|
||||||
|
.yamlMode=${this._yamlMode}
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
.hass=${this.hass}
|
||||||
|
.condition=${selectedElement}
|
||||||
|
></ha-automation-condition-editor>`
|
||||||
|
: selectedElementType === "action"
|
||||||
|
? html`<div
|
||||||
|
@ui-mode-not-available=${this._handleUiModeNotAvailable}
|
||||||
|
@value-changed=${this._onUiChanged}
|
||||||
|
.path=${path}
|
||||||
|
>
|
||||||
|
${dynamicElement(
|
||||||
|
`ha-automation-action-${getType(selectedElement)}`,
|
||||||
|
{
|
||||||
|
hass: this.hass,
|
||||||
|
action: selectedElement,
|
||||||
|
narrow: true,
|
||||||
|
disabled: this.disabled,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</div>`
|
||||||
|
: nothing}
|
||||||
|
</div>`
|
||||||
|
: nothing;
|
||||||
|
|
||||||
<ha-automation-action
|
return html`
|
||||||
role="region"
|
${this.narrow
|
||||||
aria-labelledby="actions-heading"
|
? html`<sl-drawer
|
||||||
.actions=${this.config.actions || []}
|
no-header
|
||||||
.highlightedActions=${this._pastedConfig?.actions || []}
|
placement="bottom"
|
||||||
.path=${["actions"]}
|
class="drawer-placement-bottom"
|
||||||
@value-changed=${this._actionChanged}
|
@sl-show=${this._drawerOpen}
|
||||||
.hass=${this.hass}
|
@sl-hide=${this._drawerClose}
|
||||||
.narrow=${this.narrow}
|
>
|
||||||
.disabled=${this.disabled}
|
${sidePanel}
|
||||||
></ha-automation-action>
|
</sl-drawer>`
|
||||||
|
: nothing}
|
||||||
|
<sl-split-panel
|
||||||
|
primary="start"
|
||||||
|
.positionInPixels=${selectedElement && !this.narrow
|
||||||
|
? this.clientWidth - 40 - this._sidebarWidth || 99999
|
||||||
|
: 0}
|
||||||
|
style=${selectedElement && !this.narrow
|
||||||
|
? "--min: 300px; --max: calc(100% - 300px); --divider-width: 32px;"
|
||||||
|
: "--min: 100%; --max: 100%;"}
|
||||||
|
@sl-reposition=${this._splitPanelRepositioned}
|
||||||
|
>
|
||||||
|
<div slot="start" style="overflow: auto; height: 100%">
|
||||||
|
${this.stateObj?.state === "off"
|
||||||
|
? html`
|
||||||
|
<ha-alert alert-type="info">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.disabled"
|
||||||
|
)}
|
||||||
|
<mwc-button slot="action" @click=${this._enable}>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.enable"
|
||||||
|
)}
|
||||||
|
</mwc-button>
|
||||||
|
</ha-alert>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
|
${this.config.description
|
||||||
|
? html`<ha-markdown
|
||||||
|
class="description"
|
||||||
|
breaks
|
||||||
|
.content=${this.config.description}
|
||||||
|
></ha-markdown>`
|
||||||
|
: nothing}
|
||||||
|
<div class="header">
|
||||||
|
<h2 id="triggers-heading" class="name">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.header"
|
||||||
|
)}
|
||||||
|
</h2>
|
||||||
|
<a
|
||||||
|
href=${documentationUrl(this.hass, "/docs/automation/trigger/")}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiHelpCircle}
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.learn_more"
|
||||||
|
)}
|
||||||
|
></ha-icon-button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
${!ensureArray(this.config.triggers)?.length
|
||||||
|
? html`<p>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.description"
|
||||||
|
)}
|
||||||
|
</p>`
|
||||||
|
: nothing}
|
||||||
|
|
||||||
|
<ha-automation-trigger
|
||||||
|
role="region"
|
||||||
|
aria-labelledby="triggers-heading"
|
||||||
|
.triggers=${this.config.triggers || []}
|
||||||
|
.highlightedTriggers=${this._pastedConfig?.triggers || [
|
||||||
|
selectedElement,
|
||||||
|
]}
|
||||||
|
.path=${["triggers"]}
|
||||||
|
@value-changed=${this._triggerChanged}
|
||||||
|
.hass=${this.hass}
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
@element-selected=${this._elementSelected}
|
||||||
|
></ha-automation-trigger>
|
||||||
|
|
||||||
|
<div class="header">
|
||||||
|
<h2 id="conditions-heading" class="name">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.conditions.header"
|
||||||
|
)}
|
||||||
|
<span class="small"
|
||||||
|
>(${this.hass.localize("ui.common.optional")})</span
|
||||||
|
>
|
||||||
|
</h2>
|
||||||
|
<a
|
||||||
|
href=${documentationUrl(this.hass, "/docs/automation/condition/")}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiHelpCircle}
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.conditions.learn_more"
|
||||||
|
)}
|
||||||
|
></ha-icon-button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
${!ensureArray(this.config.conditions)?.length
|
||||||
|
? html`<p>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.conditions.description",
|
||||||
|
{ user: this.hass.user?.name || "Alice" }
|
||||||
|
)}
|
||||||
|
</p>`
|
||||||
|
: nothing}
|
||||||
|
|
||||||
|
<ha-automation-condition
|
||||||
|
role="region"
|
||||||
|
aria-labelledby="conditions-heading"
|
||||||
|
.conditions=${this.config.conditions || []}
|
||||||
|
.highlightedConditions=${this._pastedConfig?.conditions || [
|
||||||
|
selectedElement,
|
||||||
|
]}
|
||||||
|
.path=${["conditions"]}
|
||||||
|
@value-changed=${this._conditionChanged}
|
||||||
|
.hass=${this.hass}
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
@element-selected=${this._elementSelected}
|
||||||
|
></ha-automation-condition>
|
||||||
|
|
||||||
|
<div class="header">
|
||||||
|
<h2 id="actions-heading" class="name">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.header"
|
||||||
|
)}
|
||||||
|
</h2>
|
||||||
|
<div>
|
||||||
|
<a
|
||||||
|
href=${documentationUrl(this.hass, "/docs/automation/action/")}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiHelpCircle}
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.learn_more"
|
||||||
|
)}
|
||||||
|
></ha-icon-button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
${!ensureArray(this.config.actions)?.length
|
||||||
|
? html`<p>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.description"
|
||||||
|
)}
|
||||||
|
</p>`
|
||||||
|
: nothing}
|
||||||
|
|
||||||
|
<ha-automation-action
|
||||||
|
role="region"
|
||||||
|
aria-labelledby="actions-heading"
|
||||||
|
.actions=${this.config.actions || []}
|
||||||
|
.highlightedActions=${this._pastedConfig?.actions || [
|
||||||
|
selectedElement,
|
||||||
|
]}
|
||||||
|
.path=${["actions"]}
|
||||||
|
@value-changed=${this._actionChanged}
|
||||||
|
.hass=${this.hass}
|
||||||
|
.narrow=${this.narrow}
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
@element-selected=${this._elementSelected}
|
||||||
|
></ha-automation-action>
|
||||||
|
</div>
|
||||||
|
${!this.narrow && selectedElement
|
||||||
|
? html`<ha-card
|
||||||
|
slot="end"
|
||||||
|
style="--ha-card-border-color: var(--primary-color); --ha-card-border-width: 2px;"
|
||||||
|
>
|
||||||
|
${sidePanel}
|
||||||
|
</ha-card>`
|
||||||
|
: nothing}
|
||||||
|
</sl-split-panel>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _onUiChanged(ev: CustomEvent): void {
|
||||||
|
ev.stopPropagation();
|
||||||
|
const path = ev.currentTarget?.path || [];
|
||||||
|
|
||||||
|
const newConfig = updateNestedItem(
|
||||||
|
{ ...this.config },
|
||||||
|
path,
|
||||||
|
ev.detail.value
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(newConfig);
|
||||||
|
|
||||||
|
fireEvent(this, "value-changed", { value: newConfig });
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _toggleYamlMode() {
|
||||||
|
this._yamlMode = !this._yamlMode;
|
||||||
|
if (this._yamlMode) {
|
||||||
|
await this.updateComplete;
|
||||||
|
// this.renderRoot.querySelector("ha-yaml-editor").positionInPixels = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _elementSelected(ev) {
|
||||||
|
console.log(ev);
|
||||||
|
this._selectedElement = ev.detail;
|
||||||
|
console.log("repo", this._sidebarWidth);
|
||||||
|
const target = ev.target;
|
||||||
|
await this.updateComplete;
|
||||||
|
this.renderRoot.querySelector("sl-split-panel").positionInPixels =
|
||||||
|
this.clientWidth - 40 - this._sidebarWidth;
|
||||||
|
if (this.narrow) {
|
||||||
|
this.renderRoot.querySelector("sl-drawer").show();
|
||||||
|
console.log(target);
|
||||||
|
this._targetEl = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _splitPanelRepositioned(ev: CustomEvent): void {
|
||||||
|
if (!this._selectedElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(ev);
|
||||||
|
console.log("reposition", ev.target.positionInPixels);
|
||||||
|
let sidebarWidth = ev.target.clientWidth - ev.target.positionInPixels;
|
||||||
|
if (this._oldClientWidth && this._oldClientWidth !== this.clientWidth) {
|
||||||
|
// If the client width has changed, we need to subtract the difference
|
||||||
|
sidebarWidth = sidebarWidth + (this._oldClientWidth - this.clientWidth);
|
||||||
|
}
|
||||||
|
this._oldClientWidth = this.clientWidth;
|
||||||
|
console.log(sidebarWidth);
|
||||||
|
console.log(this.clientWidth);
|
||||||
|
console.log(this.clientWidth - 40 - sidebarWidth);
|
||||||
|
// if (Math.abs(sidebarWidth - this._sidebarWidth) > 20) {
|
||||||
|
// this._sidebarWidth = sidebarWidth;
|
||||||
|
// }
|
||||||
|
this._sidebarWidth = sidebarWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _closeSidebar() {
|
||||||
|
if (this.narrow) {
|
||||||
|
this.renderRoot.querySelector("sl-drawer").hide();
|
||||||
|
}
|
||||||
|
this._selectedElement = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _drawerOpen() {
|
||||||
|
// this._oldScrollPosition = window.scrollY;
|
||||||
|
this.renderRoot.querySelector("div[slot='start']").style.paddingBottom =
|
||||||
|
"66vh";
|
||||||
|
await nextRender();
|
||||||
|
fireEvent(this, "scroll-to", {
|
||||||
|
up: this._targetEl.getBoundingClientRect().top,
|
||||||
|
});
|
||||||
|
this._setupListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setupListeners() {
|
||||||
|
const mc = new Manager(this.renderRoot.querySelector("ha-dialog-header"), {
|
||||||
|
touchAction: "pan-y",
|
||||||
|
});
|
||||||
|
|
||||||
|
mc.add(
|
||||||
|
new Swipe({
|
||||||
|
direction: DIRECTION_VERTICAL,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
mc.on("swipeup", (e) => {
|
||||||
|
console.log("up", e);
|
||||||
|
this.toggleAttribute("big-drawer", true);
|
||||||
|
});
|
||||||
|
|
||||||
|
mc.on("swipedown", (e) => {
|
||||||
|
console.log("down", e);
|
||||||
|
if (this.hasAttribute("big-drawer")) {
|
||||||
|
this.toggleAttribute("big-drawer", false);
|
||||||
|
} else {
|
||||||
|
this.renderRoot.querySelector("sl-drawer").hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._manager = mc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _drawerClose() {
|
||||||
|
this.renderRoot.querySelector("div[slot='start']").style.paddingBottom =
|
||||||
|
"0";
|
||||||
|
}
|
||||||
|
|
||||||
private _triggerChanged(ev: CustomEvent): void {
|
private _triggerChanged(ev: CustomEvent): void {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this.resetPastedConfig();
|
this.resetPastedConfig();
|
||||||
@ -552,6 +878,45 @@ export class HaManualAutomationEditor extends LitElement {
|
|||||||
font-weight: var(--ha-font-weight-normal);
|
font-weight: var(--ha-font-weight-normal);
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sl-split-panel {
|
||||||
|
height: calc(100vh - var(--header-height, 64px) - 28px - 20px - 1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
sl-drawer {
|
||||||
|
--sl-z-index-drawer: 9999;
|
||||||
|
--size: 66vh;
|
||||||
|
--sl-panel-background-color: var(--ha-card-background, white);
|
||||||
|
--sl-overlay-background-color: rgba(0, 0, 0, 0.32);
|
||||||
|
--sl-shadow-x-large: var(
|
||||||
|
--ha-card-box-shadow,
|
||||||
|
0px -1px 4px 1px rgba(0, 0, 0, 0.2),
|
||||||
|
0px 1px 1px 0px rgba(0, 0, 0, 0.14),
|
||||||
|
0px 1px 3px 0px rgba(0, 0, 0, 0.12)
|
||||||
|
);
|
||||||
|
--sl-panel-border-color: var(--ha-card-border-color, #e0e0e0);
|
||||||
|
}
|
||||||
|
:host([big-drawer]) sl-drawer {
|
||||||
|
--size: 90vh;
|
||||||
|
}
|
||||||
|
sl-drawer::part(panel) {
|
||||||
|
border-radius: 12px 12px 0 0;
|
||||||
|
border: 1px solid var(--ha-card-border-color, #e0e0e0);
|
||||||
|
}
|
||||||
|
sl-drawer .card-content {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
sl-drawer ha-dialog-header {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
background: var(--card-background-color);
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
.card-content {
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ import "./types/ha-automation-trigger-time";
|
|||||||
import "./types/ha-automation-trigger-time_pattern";
|
import "./types/ha-automation-trigger-time_pattern";
|
||||||
import "./types/ha-automation-trigger-webhook";
|
import "./types/ha-automation-trigger-webhook";
|
||||||
import "./types/ha-automation-trigger-zone";
|
import "./types/ha-automation-trigger-zone";
|
||||||
|
import "../../../../components/ha-automation-row";
|
||||||
|
|
||||||
export interface TriggerElement extends LitElement {
|
export interface TriggerElement extends LitElement {
|
||||||
trigger: Trigger;
|
trigger: Trigger;
|
||||||
@ -158,7 +159,7 @@ export default class HaAutomationTriggerRow extends LitElement {
|
|||||||
`
|
`
|
||||||
: nothing}
|
: nothing}
|
||||||
|
|
||||||
<ha-expansion-panel left-chevron>
|
<ha-automation-row>
|
||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
slot="leading-icon"
|
slot="leading-icon"
|
||||||
class="trigger-icon"
|
class="trigger-icon"
|
||||||
@ -193,16 +194,6 @@ export default class HaAutomationTriggerRow extends LitElement {
|
|||||||
<ha-svg-icon slot="start" .path=${mdiRenameBox}></ha-svg-icon>
|
<ha-svg-icon slot="start" .path=${mdiRenameBox}></ha-svg-icon>
|
||||||
</ha-md-menu-item>
|
</ha-md-menu-item>
|
||||||
|
|
||||||
<ha-md-menu-item
|
|
||||||
.clickAction=${this._showTriggerId}
|
|
||||||
.disabled=${this.disabled || type === "list"}
|
|
||||||
>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.triggers.edit_id"
|
|
||||||
)}
|
|
||||||
<ha-svg-icon slot="start" .path=${mdiIdentifier}></ha-svg-icon>
|
|
||||||
</ha-md-menu-item>
|
|
||||||
|
|
||||||
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
||||||
|
|
||||||
<ha-md-menu-item
|
<ha-md-menu-item
|
||||||
@ -256,16 +247,6 @@ export default class HaAutomationTriggerRow extends LitElement {
|
|||||||
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
|
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
|
||||||
></ha-md-menu-item>
|
></ha-md-menu-item>
|
||||||
|
|
||||||
<ha-md-menu-item
|
|
||||||
.clickAction=${this._toggleYamlMode}
|
|
||||||
.disabled=${!supported}
|
|
||||||
>
|
|
||||||
${this.hass.localize(
|
|
||||||
`ui.panel.config.automation.editor.edit_${!yamlMode ? "yaml" : "ui"}`
|
|
||||||
)}
|
|
||||||
<ha-svg-icon slot="start" .path=${mdiPlaylistEdit}></ha-svg-icon>
|
|
||||||
</ha-md-menu-item>
|
|
||||||
|
|
||||||
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
||||||
|
|
||||||
<ha-md-menu-item
|
<ha-md-menu-item
|
||||||
@ -302,77 +283,7 @@ export default class HaAutomationTriggerRow extends LitElement {
|
|||||||
></ha-svg-icon>
|
></ha-svg-icon>
|
||||||
</ha-md-menu-item>
|
</ha-md-menu-item>
|
||||||
</ha-md-button-menu>
|
</ha-md-button-menu>
|
||||||
|
</ha-automation-row>
|
||||||
<div
|
|
||||||
class=${classMap({
|
|
||||||
"card-content": true,
|
|
||||||
disabled:
|
|
||||||
"enabled" in this.trigger && this.trigger.enabled === false,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
${this._warnings
|
|
||||||
? html`<ha-alert
|
|
||||||
alert-type="warning"
|
|
||||||
.title=${this.hass.localize(
|
|
||||||
"ui.errors.config.editor_not_supported"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
${this._warnings.length && this._warnings[0] !== undefined
|
|
||||||
? html` <ul>
|
|
||||||
${this._warnings.map(
|
|
||||||
(warning) => html`<li>${warning}</li>`
|
|
||||||
)}
|
|
||||||
</ul>`
|
|
||||||
: ""}
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.errors.config.edit_in_yaml_supported"
|
|
||||||
)}
|
|
||||||
</ha-alert>`
|
|
||||||
: ""}
|
|
||||||
${yamlMode
|
|
||||||
? html`
|
|
||||||
${!supported
|
|
||||||
? html`
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.triggers.unsupported_platform",
|
|
||||||
{ platform: type }
|
|
||||||
)}
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
<ha-yaml-editor
|
|
||||||
.hass=${this.hass}
|
|
||||||
.defaultValue=${this.trigger}
|
|
||||||
.readOnly=${this.disabled}
|
|
||||||
@value-changed=${this._onYamlChange}
|
|
||||||
></ha-yaml-editor>
|
|
||||||
`
|
|
||||||
: html`
|
|
||||||
${showId && !isTriggerList(this.trigger)
|
|
||||||
? html`
|
|
||||||
<ha-textfield
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.editor.triggers.id"
|
|
||||||
)}
|
|
||||||
.value=${this.trigger.id || ""}
|
|
||||||
.disabled=${this.disabled}
|
|
||||||
@change=${this._idChanged}
|
|
||||||
>
|
|
||||||
</ha-textfield>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
<div
|
|
||||||
@ui-mode-not-available=${this._handleUiModeNotAvailable}
|
|
||||||
@value-changed=${this._onUiChanged}
|
|
||||||
>
|
|
||||||
${dynamicElement(`ha-automation-trigger-${type}`, {
|
|
||||||
hass: this.hass,
|
|
||||||
trigger: this.trigger,
|
|
||||||
disabled: this.disabled,
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
`}
|
|
||||||
</div>
|
|
||||||
</ha-expansion-panel>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="triggered ${classMap({
|
class="triggered ${classMap({
|
||||||
@ -740,8 +651,8 @@ export default class HaAutomationTriggerRow extends LitElement {
|
|||||||
}
|
}
|
||||||
:host([highlight]) ha-card {
|
:host([highlight]) ha-card {
|
||||||
--shadow-default: var(--ha-card-box-shadow, 0 0 0 0 transparent);
|
--shadow-default: var(--ha-card-box-shadow, 0 0 0 0 transparent);
|
||||||
--shadow-focus: 0 0 0 1px var(--state-inactive-color);
|
--shadow-focus: 0 0 0 1px var(--primary-color);
|
||||||
border-color: var(--state-inactive-color);
|
border-color: var(--primary-color);
|
||||||
box-shadow: var(--shadow-default), var(--shadow-focus);
|
box-shadow: var(--shadow-default), var(--shadow-focus);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
@ -34,6 +34,8 @@ export default class HaAutomationTrigger extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public highlightedTriggers?: Trigger[];
|
@property({ attribute: false }) public highlightedTriggers?: Trigger[];
|
||||||
|
|
||||||
|
@property({ type: Array }) public path?: ItemPath;
|
||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
@state() private _showReorder = false;
|
@state() private _showReorder = false;
|
||||||
@ -89,10 +91,12 @@ export default class HaAutomationTrigger extends LitElement {
|
|||||||
.first=${idx === 0}
|
.first=${idx === 0}
|
||||||
.last=${idx === this.triggers.length - 1}
|
.last=${idx === this.triggers.length - 1}
|
||||||
.trigger=${trg}
|
.trigger=${trg}
|
||||||
|
.path=${[...(this.path ?? []), idx]}
|
||||||
@duplicate=${this._duplicateTrigger}
|
@duplicate=${this._duplicateTrigger}
|
||||||
@move-down=${this._moveDown}
|
@move-down=${this._moveDown}
|
||||||
@move-up=${this._moveUp}
|
@move-up=${this._moveUp}
|
||||||
@value-changed=${this._triggerChanged}
|
@value-changed=${this._triggerChanged}
|
||||||
|
@click=${this._triggerClicked}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
?highlight=${this.highlightedTriggers?.includes(trg)}
|
?highlight=${this.highlightedTriggers?.includes(trg)}
|
||||||
@ -136,6 +140,15 @@ export default class HaAutomationTrigger extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _triggerClicked(ev: MouseEvent) {
|
||||||
|
fireEvent(this, "element-selected", {
|
||||||
|
type: "trigger",
|
||||||
|
element: (ev.currentTarget as HaAutomationTriggerRow).trigger,
|
||||||
|
index: (ev.currentTarget as HaAutomationTriggerRow).index,
|
||||||
|
path: (ev.currentTarget as HaAutomationTriggerRow).path,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private _addTrigger = (value: string) => {
|
private _addTrigger = (value: string) => {
|
||||||
let triggers: Trigger[];
|
let triggers: Trigger[];
|
||||||
if (value === PASTE_VALUE) {
|
if (value === PASTE_VALUE) {
|
||||||
|
@ -156,7 +156,7 @@ class ZHADeviceCard extends SubscribeMixin(LitElement) {
|
|||||||
newName = name.replace(oldDeviceName, newDeviceName);
|
newName = name.replace(oldDeviceName, newDeviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newName !== undefined && !newEntityId) {
|
if (newName === undefined && !newEntityId) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,8 +355,8 @@ export default class HaScriptFieldRow extends LitElement {
|
|||||||
}
|
}
|
||||||
:host([highlight]) ha-card {
|
:host([highlight]) ha-card {
|
||||||
--shadow-default: var(--ha-card-box-shadow, 0 0 0 0 transparent);
|
--shadow-default: var(--ha-card-box-shadow, 0 0 0 0 transparent);
|
||||||
--shadow-focus: 0 0 0 1px var(--state-inactive-color);
|
--shadow-focus: 0 0 0 1px var(--primary-color);
|
||||||
border-color: var(--state-inactive-color);
|
border-color: var(--primary-color);
|
||||||
box-shadow: var(--shadow-default), var(--shadow-focus);
|
box-shadow: var(--shadow-default), var(--shadow-focus);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user