diff --git a/src/panels/lovelace/editor/conditions/ha-card-condition-editor.ts b/src/panels/lovelace/editor/conditions/ha-card-condition-editor.ts index bf1841d22d04..fb2433d4a604 100644 --- a/src/panels/lovelace/editor/conditions/ha-card-condition-editor.ts +++ b/src/panels/lovelace/editor/conditions/ha-card-condition-editor.ts @@ -1,23 +1,30 @@ import { preventDefault } from "@fullcalendar/core/internal"; 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 { customElement, property, state } from "lit/decorators"; +import { classMap } from "lit/directives/class-map"; import { dynamicElement } from "../../../../common/dom/dynamic-element-directive"; import { fireEvent } from "../../../../common/dom/fire_event"; import { stopPropagation } from "../../../../common/dom/stop_propagation"; import { handleStructError } from "../../../../common/structs/handle-errors"; +import "../../../../components/ha-alert"; import "../../../../components/ha-button-menu"; import "../../../../components/ha-expansion-panel"; import "../../../../components/ha-icon-button"; import "../../../../components/ha-list-item"; import "../../../../components/ha-svg-icon"; import "../../../../components/ha-yaml-editor"; -import "../../../../components/ha-alert"; +import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box"; import { haStyle } from "../../../../resources/styles"; import type { HomeAssistant } from "../../../../types"; 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"; @customElement("ha-card-condition-editor") @@ -34,6 +41,8 @@ export class HaCardConditionEditor extends LitElement { @state() _condition?: Condition; + @state() private _testingResult?: boolean; + private get _editor() { if (!this._condition) return undefined; return customElements.get( @@ -112,6 +121,13 @@ export class HaCardConditionEditor extends LitElement { > + + ${this.hass.localize( + "ui.panel.lovelace.editor.condition-editor.test" + )} + + + ${this.hass.localize( "ui.panel.lovelace.editor.edit_card.edit_ui" @@ -206,24 +222,75 @@ export class HaCardConditionEditor extends LitElement { } +
+ ${ + this._testingResult + ? this.hass.localize( + "ui.panel.lovelace.editor.condition-editor.testing_pass" + ) + : this.hass.localize( + "ui.panel.lovelace.editor.condition-editor.testing_error" + ) + } +
`; } - private _handleAction(ev: CustomEvent) { + private async _handleAction(ev: CustomEvent) { switch (ev.detail.index) { case 0: - this._yamlMode = false; + await this._testCondition(); break; case 1: - this._yamlMode = true; + this._yamlMode = false; break; case 2: + this._yamlMode = true; + break; + case 3: this._delete(); 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() { fireEvent(this, "value-changed", { value: null }); } @@ -274,6 +341,32 @@ export class HaCardConditionEditor extends LitElement { opacity: 0.5; 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); + } `, ]; } diff --git a/src/translations/en.json b/src/translations/en.json index 4b7444cb2de8..c254bbbc791e 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -4810,6 +4810,11 @@ "condition-editor": { "explanation": "The card will be shown when ALL conditions below are fulfilled.", "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": { "numeric_state": { "label": "Entity numeric state",