From d6dbbcb0de4cce06c6d67f57721f16612c40ed91 Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Mon, 6 Sep 2021 10:27:29 +0200 Subject: [PATCH] Use dynamic struct validation for entities card rows (#9962) --- src/common/structs/is-custom-type.ts | 2 +- .../hui-entities-card-editor.ts | 69 ++++++++++++++----- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/common/structs/is-custom-type.ts b/src/common/structs/is-custom-type.ts index 9b90eb517f..dd5de2f637 100644 --- a/src/common/structs/is-custom-type.ts +++ b/src/common/structs/is-custom-type.ts @@ -1,6 +1,6 @@ import { refine, string } from "superstruct"; -const isCustomType = (value: string) => value.startsWith("custom:"); +export const isCustomType = (value: string) => value.startsWith("custom:"); export const customType = () => refine(string(), "custom element type", isCustomType); diff --git a/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts index d3d7c18eb4..5787f21a1a 100644 --- a/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts @@ -8,8 +8,9 @@ import { any, array, assert, - boolean, assign, + boolean, + dynamic, literal, number, object, @@ -19,7 +20,10 @@ import { union, } from "superstruct"; import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event"; -import { customType } from "../../../../common/structs/is-custom-type"; +import { + customType, + isCustomType, +} from "../../../../common/structs/is-custom-type"; import { entityId } from "../../../../common/structs/is-entity-id"; import { computeRTLDirection } from "../../../../common/util/compute_rtl"; import "../../../../components/entity/state-badge"; @@ -38,6 +42,7 @@ import "../hui-entities-card-row-editor"; import "../hui-sub-element-editor"; import { processEditorEntities } from "../process-editor-entities"; import { actionConfigStruct } from "../structs/action-struct"; +import { baseLovelaceCardConfig } from "../structs/base-card-struct"; import { entitiesConfigStruct } from "../structs/entities-struct"; import { EditorTarget, @@ -45,7 +50,6 @@ import { SubElementEditorConfig, } from "../types"; import { configElementStyle } from "./config-elements-style"; -import { baseLovelaceCardConfig } from "../structs/base-card-struct"; const buttonEntitiesRowConfigStruct = object({ type: literal("button"), @@ -142,24 +146,53 @@ const textEntitiesRowConfigStruct = object({ icon: optional(string()), }); -const customRowConfigStruct = type({ +const customEntitiesRowConfigStruct = type({ type: customType(), }); -const entitiesRowConfigStruct = union([ - entitiesConfigStruct, - buttonEntitiesRowConfigStruct, - castEntitiesRowConfigStruct, - conditionalEntitiesRowConfigStruct, - dividerEntitiesRowConfigStruct, - sectionEntitiesRowConfigStruct, - webLinkEntitiesRowConfigStruct, - buttonsEntitiesRowConfigStruct, - attributeEntitiesRowConfigStruct, - callServiceEntitiesRowConfigStruct, - textEntitiesRowConfigStruct, - customRowConfigStruct, -]); +const entitiesRowConfigStruct = dynamic((value) => { + if (value && typeof value === "object" && "type" in value) { + if (isCustomType((value as LovelaceRowConfig).type!)) { + return customEntitiesRowConfigStruct; + } + + switch ((value as LovelaceRowConfig).type!) { + case "attribute": { + return attributeEntitiesRowConfigStruct; + } + case "button": { + return buttonEntitiesRowConfigStruct; + } + case "buttons": { + return buttonsEntitiesRowConfigStruct; + } + case "call-service": { + return callServiceEntitiesRowConfigStruct; + } + case "cast": { + return castEntitiesRowConfigStruct; + } + case "conditional": { + return conditionalEntitiesRowConfigStruct; + } + case "divider": { + return dividerEntitiesRowConfigStruct; + } + case "section": { + return sectionEntitiesRowConfigStruct; + } + case "text": { + return textEntitiesRowConfigStruct; + } + case "weblink": { + return webLinkEntitiesRowConfigStruct; + } + } + } + + // No "type" property => has to be the default entity row config struct + return entitiesConfigStruct; +}); const cardConfigStruct = assign( baseLovelaceCardConfig,