Add test button to conditional card (#18411)

This commit is contained in:
Paul Bottein 2023-11-01 15:25:56 +01:00 committed by GitHub
parent 08597d6e91
commit acb5a2b283
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 104 additions and 6 deletions

View File

@ -1,23 +1,30 @@
import { preventDefault } from "@fullcalendar/core/internal"; import { preventDefault } from "@fullcalendar/core/internal";
import { ActionDetail } from "@material/mwc-list"; import { ActionDetail } from "@material/mwc-list";
import { mdiCheck, mdiDelete, mdiDotsVertical } from "@mdi/js"; import { mdiCheck, mdiDelete, mdiDotsVertical, mdiFlask } from "@mdi/js";
import { LitElement, PropertyValues, css, html, nothing } from "lit"; import { LitElement, PropertyValues, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive"; import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { stopPropagation } from "../../../../common/dom/stop_propagation"; import { stopPropagation } from "../../../../common/dom/stop_propagation";
import { handleStructError } from "../../../../common/structs/handle-errors"; import { handleStructError } from "../../../../common/structs/handle-errors";
import "../../../../components/ha-alert";
import "../../../../components/ha-button-menu"; import "../../../../components/ha-button-menu";
import "../../../../components/ha-expansion-panel"; import "../../../../components/ha-expansion-panel";
import "../../../../components/ha-icon-button"; import "../../../../components/ha-icon-button";
import "../../../../components/ha-list-item"; import "../../../../components/ha-list-item";
import "../../../../components/ha-svg-icon"; import "../../../../components/ha-svg-icon";
import "../../../../components/ha-yaml-editor"; import "../../../../components/ha-yaml-editor";
import "../../../../components/ha-alert"; import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
import { haStyle } from "../../../../resources/styles"; import { haStyle } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import { ICON_CONDITION } from "../../common/icon-condition"; import { ICON_CONDITION } from "../../common/icon-condition";
import { Condition, LegacyCondition } from "../../common/validate-condition"; import {
Condition,
LegacyCondition,
checkConditionsMet,
validateConditionalConfig,
} from "../../common/validate-condition";
import type { LovelaceConditionEditorConstructor } from "./types"; import type { LovelaceConditionEditorConstructor } from "./types";
@customElement("ha-card-condition-editor") @customElement("ha-card-condition-editor")
@ -34,6 +41,8 @@ export class HaCardConditionEditor extends LitElement {
@state() _condition?: Condition; @state() _condition?: Condition;
@state() private _testingResult?: boolean;
private get _editor() { private get _editor() {
if (!this._condition) return undefined; if (!this._condition) return undefined;
return customElements.get( return customElements.get(
@ -112,6 +121,13 @@ export class HaCardConditionEditor extends LitElement {
> >
</ha-icon-button> </ha-icon-button>
<ha-list-item graphic="icon">
${this.hass.localize(
"ui.panel.lovelace.editor.condition-editor.test"
)}
<ha-svg-icon slot="graphic" .path=${mdiFlask}></ha-svg-icon>
</ha-list-item>
<ha-list-item graphic="icon" .disabled=${!this._uiAvailable}> <ha-list-item graphic="icon" .disabled=${!this._uiAvailable}>
${this.hass.localize( ${this.hass.localize(
"ui.panel.lovelace.editor.edit_card.edit_ui" "ui.panel.lovelace.editor.edit_card.edit_ui"
@ -206,24 +222,75 @@ export class HaCardConditionEditor extends LitElement {
} }
</div> </div>
</ha-expansion-panel> </ha-expansion-panel>
<div
class="testing ${classMap({
active: this._testingResult !== undefined,
pass: this._testingResult === true,
error: this._testingResult === false,
})}"
>
${
this._testingResult
? this.hass.localize(
"ui.panel.lovelace.editor.condition-editor.testing_pass"
)
: this.hass.localize(
"ui.panel.lovelace.editor.condition-editor.testing_error"
)
}
</div>
</ha-card> </ha-card>
`; `;
} }
private _handleAction(ev: CustomEvent<ActionDetail>) { private async _handleAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) { switch (ev.detail.index) {
case 0: case 0:
this._yamlMode = false; await this._testCondition();
break; break;
case 1: case 1:
this._yamlMode = true; this._yamlMode = false;
break; break;
case 2: case 2:
this._yamlMode = true;
break;
case 3:
this._delete(); this._delete();
break; break;
} }
} }
private _timeout?: number;
private async _testCondition() {
if (this._timeout) {
window.clearTimeout(this._timeout);
this._timeout = undefined;
}
this._testingResult = undefined;
const condition = this.condition;
const validateResult = validateConditionalConfig([this.condition]);
if (!validateResult) {
showAlertDialog(this, {
title: this.hass.localize(
"ui.panel.lovelace.editor.condition-editor.invalid_config_title"
),
text: this.hass.localize(
"ui.panel.lovelace.editor.condition-editor.invalid_config_text"
),
});
return;
}
this._testingResult = checkConditionsMet([condition], this.hass);
this._timeout = window.setTimeout(() => {
this._testingResult = undefined;
}, 2500);
}
private _delete() { private _delete() {
fireEvent(this, "value-changed", { value: null }); fireEvent(this, "value-changed", { value: null });
} }
@ -274,6 +341,32 @@ export class HaCardConditionEditor extends LitElement {
opacity: 0.5; opacity: 0.5;
pointer-events: none; pointer-events: none;
} }
.testing {
position: absolute;
top: 0px;
right: 0px;
left: 0px;
text-transform: uppercase;
font-weight: bold;
font-size: 14px;
background-color: var(--divider-color, #e0e0e0);
color: var(--text-primary-color);
max-height: 0px;
overflow: hidden;
transition: max-height 0.3s;
text-align: center;
border-top-right-radius: var(--ha-card-border-radius, 12px);
border-top-left-radius: var(--ha-card-border-radius, 12px);
}
.testing.active {
max-height: 100px;
}
.testing.error {
background-color: var(--accent-color);
}
.testing.pass {
background-color: var(--success-color);
}
`, `,
]; ];
} }

View File

@ -4814,6 +4814,11 @@
"condition-editor": { "condition-editor": {
"explanation": "The card will be shown when ALL conditions below are fulfilled.", "explanation": "The card will be shown when ALL conditions below are fulfilled.",
"add": "Add condition", "add": "Add condition",
"test": "[%key:ui::panel::config::automation::editor::conditions::test%]",
"testing_pass": "[%key:ui::panel::config::automation::editor::conditions::testing_pass%]",
"testing_error": "[%key:ui::panel::config::automation::editor::conditions::testing_error%]",
"invalid_config_title": "Invalid configuration",
"invalid_config_text": "The condition can not be tested because the configuration is not valid.",
"condition": { "condition": {
"numeric_state": { "numeric_state": {
"label": "Entity numeric state", "label": "Entity numeric state",