mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-31 13:07:49 +00:00
Add "Add condition" button in the editor
This commit is contained in:
parent
873ce2b405
commit
3a03abbd3a
@ -3,6 +3,12 @@ import { HomeAssistant } from "../../../types";
|
|||||||
|
|
||||||
export type Condition = StateCondition | ResponsiveCondition;
|
export type Condition = StateCondition | ResponsiveCondition;
|
||||||
|
|
||||||
|
export type LegacyCondition = {
|
||||||
|
entity?: string;
|
||||||
|
state?: string;
|
||||||
|
state_not?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type StateCondition = {
|
export type StateCondition = {
|
||||||
condition: "state";
|
condition: "state";
|
||||||
entity?: string;
|
entity?: string;
|
||||||
@ -50,7 +56,7 @@ export function checkConditionsMet(
|
|||||||
|
|
||||||
function valideStateCondition(condition: StateCondition) {
|
function valideStateCondition(condition: StateCondition) {
|
||||||
return (
|
return (
|
||||||
!!condition.entity &&
|
condition.entity != null &&
|
||||||
(condition.state != null || condition.state_not != null)
|
(condition.state != null || condition.state_not != null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,36 @@
|
|||||||
import { mdiCodeBraces, mdiDelete, mdiListBoxOutline } from "@mdi/js";
|
import { mdiCodeBraces, mdiDelete, mdiListBoxOutline } from "@mdi/js";
|
||||||
import { LitElement, css, html, nothing } from "lit";
|
import { LitElement, css, html, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
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 "../../../components/ha-icon-button";
|
import "../../../../components/ha-icon-button";
|
||||||
import "../../../components/ha-yaml-editor";
|
import "../../../../components/ha-yaml-editor";
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../../types";
|
||||||
import "./types/ha-card-condition-responsive";
|
import { Condition, LegacyCondition } from "../../common/validate-condition";
|
||||||
import "./types/ha-card-condition-state";
|
import type { LovelaceConditionEditorConstructor } from "./types";
|
||||||
import { Condition } from "./validate-condition";
|
|
||||||
|
|
||||||
@customElement("ha-card-condition-editor")
|
@customElement("ha-card-condition-editor")
|
||||||
export default class HaCardConditionEditor extends LitElement {
|
export default class HaCardConditionEditor extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) condition!: Condition;
|
@property({ attribute: false }) condition!: Condition | LegacyCondition;
|
||||||
|
|
||||||
@state() public _yamlMode = false;
|
@state() public _yamlMode = false;
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
const condition = this.condition;
|
const condition: Condition = {
|
||||||
|
condition: "state",
|
||||||
|
...this.condition,
|
||||||
|
};
|
||||||
const element = customElements.get(
|
const element = customElements.get(
|
||||||
`ha-card-condition-${condition.condition}`
|
`ha-card-condition-${condition.condition}`
|
||||||
) as any | undefined;
|
) as LovelaceConditionEditorConstructor | undefined;
|
||||||
const supported = element !== undefined;
|
const supported = element !== undefined;
|
||||||
|
|
||||||
const valid =
|
const valid =
|
||||||
element &&
|
element &&
|
||||||
(!element.validateUIConfig || element.validateUIConfig(this.condition));
|
(!element.validateUIConfig || element.validateUIConfig(condition));
|
||||||
|
|
||||||
const yamlMode = this._yamlMode || !supported || !valid;
|
const yamlMode = this._yamlMode || !supported || !valid;
|
||||||
|
|
6
src/panels/lovelace/editor/conditions/types.ts
Normal file
6
src/panels/lovelace/editor/conditions/types.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { Condition } from "../../common/validate-condition";
|
||||||
|
|
||||||
|
export interface LovelaceConditionEditorConstructor {
|
||||||
|
defaultConfig?: Condition;
|
||||||
|
validateUIConfig?: (condition: Condition) => boolean;
|
||||||
|
}
|
@ -1,14 +1,14 @@
|
|||||||
import { html, LitElement } from "lit";
|
import { html, LitElement } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { getAllCombinations } from "../../../../common/array/combinations";
|
import { getAllCombinations } from "../../../../../common/array/combinations";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
import { LocalizeFunc } from "../../../../common/translations/localize";
|
import { LocalizeFunc } from "../../../../../common/translations/localize";
|
||||||
import "../../../../components/ha-form/ha-form";
|
import "../../../../../components/ha-form/ha-form";
|
||||||
import type { SchemaUnion } from "../../../../components/ha-form/types";
|
import type { SchemaUnion } from "../../../../../components/ha-form/types";
|
||||||
import { HaFormSchema } from "../../../../components/ha-form/types";
|
import { HaFormSchema } from "../../../../../components/ha-form/types";
|
||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../../../types";
|
||||||
import { ResponsiveCondition } from "../validate-condition";
|
import { ResponsiveCondition } from "../../../common/validate-condition";
|
||||||
|
|
||||||
const BREAKPOINT_VALUES = [0, 768, 1024, 1280, Infinity];
|
const BREAKPOINT_VALUES = [0, 768, 1024, 1280, Infinity];
|
||||||
const BREAKPOINTS = ["mobile", "tablet", "desktop", "wide"] as const;
|
const BREAKPOINTS = ["mobile", "tablet", "desktop", "wide"] as const;
|
@ -2,13 +2,13 @@ import { html, LitElement, PropertyValues } from "lit";
|
|||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { assert, literal, object, optional, string } from "superstruct";
|
import { assert, literal, object, optional, string } from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
import { LocalizeFunc } from "../../../../common/translations/localize";
|
import { LocalizeFunc } from "../../../../../common/translations/localize";
|
||||||
import "../../../../components/ha-form/ha-form";
|
import "../../../../../components/ha-form/ha-form";
|
||||||
import type { SchemaUnion } from "../../../../components/ha-form/types";
|
import type { SchemaUnion } from "../../../../../components/ha-form/types";
|
||||||
import { HaFormSchema } from "../../../../components/ha-form/types";
|
import { HaFormSchema } from "../../../../../components/ha-form/types";
|
||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../../../types";
|
||||||
import { StateCondition } from "../validate-condition";
|
import { StateCondition } from "../../../common/validate-condition";
|
||||||
|
|
||||||
const stateConditionStruct = object({
|
const stateConditionStruct = object({
|
||||||
condition: literal("state"),
|
condition: literal("state"),
|
||||||
@ -33,7 +33,7 @@ export class HaCardConditionState extends LitElement {
|
|||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
public static get defaultConfig(): StateCondition {
|
public static get defaultConfig(): StateCondition {
|
||||||
return { condition: "state", entity: "" };
|
return { condition: "state", entity: "", state: "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected willUpdate(changedProperties: PropertyValues): void {
|
protected willUpdate(changedProperties: PropertyValues): void {
|
@ -1,31 +1,48 @@
|
|||||||
import "@material/mwc-tab-bar/mwc-tab-bar";
|
import "@material/mwc-tab-bar/mwc-tab-bar";
|
||||||
import "@material/mwc-tab/mwc-tab";
|
import "@material/mwc-tab/mwc-tab";
|
||||||
import type { MDCTabBarActivatedEvent } from "@material/tab-bar";
|
import type { MDCTabBarActivatedEvent } from "@material/tab-bar";
|
||||||
import { mdiCodeBraces, mdiContentCopy, mdiListBoxOutline } from "@mdi/js";
|
import {
|
||||||
|
mdiCodeBraces,
|
||||||
|
mdiContentCopy,
|
||||||
|
mdiContentDuplicate,
|
||||||
|
mdiListBoxOutline,
|
||||||
|
mdiPlus,
|
||||||
|
} from "@mdi/js";
|
||||||
import deepClone from "deep-clone-simple";
|
import deepClone from "deep-clone-simple";
|
||||||
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
|
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { any, array, assert, assign, object, optional } from "superstruct";
|
import { any, array, assert, assign, object, optional } from "superstruct";
|
||||||
import { storage } from "../../../../common/decorators/storage";
|
import { storage } from "../../../../common/decorators/storage";
|
||||||
import { HASSDomEvent, fireEvent } from "../../../../common/dom/fire_event";
|
import { HASSDomEvent, fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
import { stopPropagation } from "../../../../common/dom/stop_propagation";
|
||||||
|
import "../../../../components/ha-button";
|
||||||
|
import "../../../../components/ha-list-item";
|
||||||
|
import "../../../../components/ha-menu-button";
|
||||||
|
import type { HaSelect } from "../../../../components/ha-select";
|
||||||
|
import "../../../../components/ha-svg-icon";
|
||||||
import type {
|
import type {
|
||||||
LovelaceCardConfig,
|
LovelaceCardConfig,
|
||||||
LovelaceConfig,
|
LovelaceConfig,
|
||||||
} from "../../../../data/lovelace";
|
} from "../../../../data/lovelace";
|
||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../../types";
|
||||||
import type { ConditionalCardConfig } from "../../cards/types";
|
import type { ConditionalCardConfig } from "../../cards/types";
|
||||||
import "../../common/ha-card-condition-editor";
|
import { Condition } from "../../common/validate-condition";
|
||||||
import type { LovelaceCardEditor } from "../../types";
|
import type { LovelaceCardEditor } from "../../types";
|
||||||
import "../card-editor/hui-card-element-editor";
|
import "../card-editor/hui-card-element-editor";
|
||||||
import type { HuiCardElementEditor } from "../card-editor/hui-card-element-editor";
|
import type { HuiCardElementEditor } from "../card-editor/hui-card-element-editor";
|
||||||
import "../card-editor/hui-card-picker";
|
import "../card-editor/hui-card-picker";
|
||||||
|
import "../conditions/ha-card-condition-editor";
|
||||||
|
import "../conditions/types/ha-card-condition-responsive";
|
||||||
|
import "../conditions/types/ha-card-condition-state";
|
||||||
|
import { LovelaceConditionEditorConstructor } from "../conditions/types";
|
||||||
import "../hui-element-editor";
|
import "../hui-element-editor";
|
||||||
import type { ConfigChangedEvent } from "../hui-element-editor";
|
import type { ConfigChangedEvent } from "../hui-element-editor";
|
||||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
import type { GUIModeChangedEvent } from "../types";
|
import type { GUIModeChangedEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
|
||||||
|
const UI_CONDITION: Condition["condition"][] = ["state", "responsive"];
|
||||||
|
|
||||||
const cardConfigStruct = assign(
|
const cardConfigStruct = assign(
|
||||||
baseLovelaceCardConfig,
|
baseLovelaceCardConfig,
|
||||||
object({
|
object({
|
||||||
@ -158,13 +175,35 @@ export class HuiConditionalCardEditor
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
<div class="condition">
|
<div>
|
||||||
<div class="content">
|
<ha-button-menu
|
||||||
<ha-entity-picker
|
@action=${this._addCondition}
|
||||||
.hass=${this.hass}
|
fixed
|
||||||
@change=${this._addCondition}
|
@closed=${stopPropagation}
|
||||||
></ha-entity-picker>
|
>
|
||||||
</div>
|
<ha-button
|
||||||
|
slot="trigger"
|
||||||
|
outlined
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.card.conditional.add_condition"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ha-svg-icon .path=${mdiPlus} slot="icon"></ha-svg-icon>
|
||||||
|
</ha-button>
|
||||||
|
${UI_CONDITION.map(
|
||||||
|
(condition) => html`
|
||||||
|
<ha-list-item .value=${condition} graphic="icon">
|
||||||
|
${this.hass!.localize(
|
||||||
|
`ui.panel.lovelace.editor.card.conditional.condition.${condition}.label`
|
||||||
|
) || condition}
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="graphic"
|
||||||
|
.path=${mdiContentDuplicate}
|
||||||
|
></ha-svg-icon>
|
||||||
|
</ha-list-item>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</ha-button-menu>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`}
|
`}
|
||||||
@ -233,19 +272,24 @@ export class HuiConditionalCardEditor
|
|||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _addCondition(ev: Event): void {
|
private _addCondition(ev: CustomEvent): void {
|
||||||
const target = ev.target! as any;
|
const condition = (ev.currentTarget as HaSelect).items[ev.detail.index]
|
||||||
if (target.value === "" || !this._config) {
|
.value as Condition["condition"];
|
||||||
|
if (!this._config) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const conditions = [...this._config.conditions];
|
const conditions = [...this._config.conditions];
|
||||||
conditions.push({
|
|
||||||
condition: "state",
|
const elClass = customElements.get(`ha-card-condition-${condition}`) as
|
||||||
entity: target.value,
|
| LovelaceConditionEditorConstructor
|
||||||
state: "",
|
| undefined;
|
||||||
});
|
|
||||||
|
conditions.push(
|
||||||
|
elClass?.defaultConfig
|
||||||
|
? { ...elClass.defaultConfig }
|
||||||
|
: { condition: condition }
|
||||||
|
);
|
||||||
this._config = { ...this._config, conditions };
|
this._config = { ...this._config, conditions };
|
||||||
target.value = "";
|
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,6 +326,9 @@ export class HuiConditionalCardEditor
|
|||||||
.condition .content {
|
.condition .content {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
ha-button-menu {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
.card {
|
.card {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
border: 1px solid var(--divider-color);
|
border: 1px solid var(--divider-color);
|
||||||
|
@ -4769,6 +4769,7 @@
|
|||||||
"current_state": "current",
|
"current_state": "current",
|
||||||
"condition_explanation": "The card will be shown when ALL conditions below are fulfilled.",
|
"condition_explanation": "The card will be shown when ALL conditions below are fulfilled.",
|
||||||
"change_type": "Change type",
|
"change_type": "Change type",
|
||||||
|
"add_condition": "Add condition",
|
||||||
"condition": {
|
"condition": {
|
||||||
"responsive": {
|
"responsive": {
|
||||||
"label": "Responsive",
|
"label": "Responsive",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user