From 4e51c7cf968cf27a935de2470e448203218b446d Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 25 Sep 2024 16:47:38 +0200 Subject: [PATCH] Use callback instead of changing nested config with sub editor (#22081) Use callback instead of changing nested config --- src/common/util/nested-object.ts | 17 ------------ .../hui-heading-card-editor.ts | 16 +++++++++++- .../hui-humidifier-card-editor.ts | 22 +++++++++++++--- .../hui-thermostat-card-editor.ts | 22 +++++++++++++--- .../config-elements/hui-tile-card-editor.ts | 22 +++++++++++++--- .../lovelace/editor/hui-element-editor.ts | 26 +++---------------- src/panels/lovelace/editor/types.ts | 9 ++++--- 7 files changed, 81 insertions(+), 53 deletions(-) delete mode 100644 src/common/util/nested-object.ts diff --git a/src/common/util/nested-object.ts b/src/common/util/nested-object.ts deleted file mode 100644 index 4489d8a51527..000000000000 --- a/src/common/util/nested-object.ts +++ /dev/null @@ -1,17 +0,0 @@ -export function updateNestedObject( - obj: T, - path: (number | string)[], - value: any -): T { - if (path.length === 0) return value; - const newObj = (Array.isArray(obj) ? [...obj] : { ...obj }) as T; - const key = path[0]; - newObj[key] = updateNestedObject(obj[key], path.slice(1), value); - return newObj; -} - -export function findNestedObject(obj: any, path: (number | string)[]) { - if (path.length === 0) return obj; - const key = path[0]; - return findNestedObject(obj[key], path.slice(1)); -} diff --git a/src/panels/lovelace/editor/config-elements/hui-heading-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-heading-card-editor.ts index ebaca29278e7..727a4223d790 100644 --- a/src/panels/lovelace/editor/config-elements/hui-heading-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-heading-card-editor.ts @@ -30,6 +30,7 @@ import { actionConfigStruct } from "../structs/action-struct"; import { baseLovelaceCardConfig } from "../structs/base-card-struct"; import { configElementStyle } from "./config-elements-style"; import "./hui-entities-editor"; +import { EditSubElementEvent } from "../types"; const actions: UiAction[] = ["navigate", "url", "perform-action", "none"]; @@ -176,9 +177,22 @@ export class HuiHeadingCardEditor private _editEntity(ev: HASSDomEvent<{ index: number }>): void { ev.stopPropagation(); + const index = ev.detail.index; + const config = this._config!.entities![index!]; + fireEvent(this, "edit-sub-element", { - path: ["entities", ev.detail.index], + config: config, + saveConfig: (newConfig) => this._updateEntity(index, newConfig), type: "heading-entity", + } as EditSubElementEvent); + } + + private _updateEntity(index: number, entity: HeadingEntityConfig) { + const entities = this._config!.entities!.concat(); + entities[index] = entity; + const config = { ...this._config!, entities }; + fireEvent(this, "config-changed", { + config: config, }); } diff --git a/src/panels/lovelace/editor/config-elements/hui-humidifier-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-humidifier-card-editor.ts index e8929822c785..7ce387121db8 100644 --- a/src/panels/lovelace/editor/config-elements/hui-humidifier-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-humidifier-card-editor.ts @@ -27,7 +27,7 @@ import { import type { HumidifierCardConfig } from "../../cards/types"; import type { LovelaceCardEditor } from "../../types"; import { baseLovelaceCardConfig } from "../structs/base-card-struct"; -import { EditDetailElementEvent } from "../types"; +import { EditDetailElementEvent, EditSubElementEvent } from "../types"; import { configElementStyle } from "./config-elements-style"; import "./hui-card-features-editor"; import type { FeatureType } from "./hui-card-features-editor"; @@ -145,12 +145,28 @@ export class HuiHumidifierCardEditor } private _editDetailElement(ev: HASSDomEvent): void { + const index = ev.detail.subElementConfig.index; + const config = this._config!.features![index!]; + fireEvent(this, "edit-sub-element", { - path: ["features", ev.detail.subElementConfig.index!], + config: config, + saveConfig: (newConfig) => this._updateFeature(index!, newConfig), context: { entity_id: this._config!.entity, - } as LovelaceCardFeatureContext, + }, type: "feature", + } as EditSubElementEvent< + LovelaceCardFeatureConfig, + LovelaceCardFeatureContext + >); + } + + private _updateFeature(index: number, feature: LovelaceCardFeatureConfig) { + const features = this._config!.features!.concat(); + features[index] = feature; + const config = { ...this._config!, features }; + fireEvent(this, "config-changed", { + config: config, }); } diff --git a/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts index 7e82001c55d9..1067ada35063 100644 --- a/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts @@ -27,7 +27,7 @@ import { import type { ThermostatCardConfig } from "../../cards/types"; import type { LovelaceCardEditor } from "../../types"; import { baseLovelaceCardConfig } from "../structs/base-card-struct"; -import { EditDetailElementEvent } from "../types"; +import { EditDetailElementEvent, EditSubElementEvent } from "../types"; import { configElementStyle } from "./config-elements-style"; import "./hui-card-features-editor"; import type { FeatureType } from "./hui-card-features-editor"; @@ -143,12 +143,28 @@ export class HuiThermostatCardEditor } private _editDetailElement(ev: HASSDomEvent): void { + const index = ev.detail.subElementConfig.index; + const config = this._config!.features![index!]; + fireEvent(this, "edit-sub-element", { - path: ["features", ev.detail.subElementConfig.index!], + config: config, + saveConfig: (newConfig) => this._updateFeature(index!, newConfig), context: { entity_id: this._config!.entity, - } as LovelaceCardFeatureContext, + }, type: "feature", + } as EditSubElementEvent< + LovelaceCardFeatureConfig, + LovelaceCardFeatureContext + >); + } + + private _updateFeature(index: number, feature: LovelaceCardFeatureConfig) { + const features = this._config!.features!.concat(); + features[index] = feature; + const config = { ...this._config!, features }; + fireEvent(this, "config-changed", { + config: config, }); } diff --git a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts index d9798182ccc6..004bba358bba 100644 --- a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts @@ -31,7 +31,7 @@ import type { TileCardConfig } from "../../cards/types"; import type { LovelaceCardEditor } from "../../types"; import { actionConfigStruct } from "../structs/action-struct"; import { baseLovelaceCardConfig } from "../structs/base-card-struct"; -import { EditDetailElementEvent } from "../types"; +import { EditDetailElementEvent, EditSubElementEvent } from "../types"; import { configElementStyle } from "./config-elements-style"; import "./hui-card-features-editor"; @@ -246,12 +246,28 @@ export class HuiTileCardEditor } private _editDetailElement(ev: HASSDomEvent): void { + const index = ev.detail.subElementConfig.index; + const config = this._config!.features![index!]; + fireEvent(this, "edit-sub-element", { - path: ["features", ev.detail.subElementConfig.index!], + config: config, + saveConfig: (newConfig) => this._updateFeature(index!, newConfig), context: { entity_id: this._config!.entity, - } as LovelaceCardFeatureContext, + }, type: "feature", + } as EditSubElementEvent< + LovelaceCardFeatureConfig, + LovelaceCardFeatureContext + >); + } + + private _updateFeature(index: number, feature: LovelaceCardFeatureConfig) { + const features = this._config!.features!.concat(); + features[index] = feature; + const config = { ...this._config!, features }; + fireEvent(this, "config-changed", { + config: config, }); } diff --git a/src/panels/lovelace/editor/hui-element-editor.ts b/src/panels/lovelace/editor/hui-element-editor.ts index 776ae00365d8..849d66bf9a9a 100644 --- a/src/panels/lovelace/editor/hui-element-editor.ts +++ b/src/panels/lovelace/editor/hui-element-editor.ts @@ -12,10 +12,6 @@ import { cache } from "lit/directives/cache"; import { fireEvent, HASSDomEvent } from "../../../common/dom/fire_event"; import { handleStructError } from "../../../common/structs/handle-errors"; import { deepEqual } from "../../../common/util/deep-equal"; -import { - findNestedObject, - updateNestedObject, -} from "../../../common/util/nested-object"; import "../../../components/ha-alert"; import "../../../components/ha-circular-progress"; import "../../../components/ha-yaml-editor"; @@ -197,14 +193,7 @@ export abstract class HuiElementEditor< elementConfig: value, }; - const config = updateNestedObject( - this._config, - this._subElementEditorConfig.path!, - value - ); - - this._config = config; - this._setConfig(); + this._subElementEditorConfig.saveElementConfig?.(value); } private _goBack(ev): void { @@ -215,22 +204,15 @@ export abstract class HuiElementEditor< private async _editSubElement( ev: HASSDomEvent ): Promise { - if (!ev.detail.path) { - return; - } ev.stopPropagation(); - const config = findNestedObject(this._config, ev.detail.path); - - if (!config) { - throw new Error("Failed to edit config"); - } await import("./hui-sub-element-editor"); this._subElementEditorConfig = { type: ev.detail.type, - path: ev.detail.path, - elementConfig: config, + elementConfig: ev.detail.config, + context: ev.detail.context, + saveElementConfig: ev.detail.saveConfig, }; } diff --git a/src/panels/lovelace/editor/types.ts b/src/panels/lovelace/editor/types.ts index f589e286c36b..a409f00729e2 100644 --- a/src/panels/lovelace/editor/types.ts +++ b/src/panels/lovelace/editor/types.ts @@ -92,21 +92,22 @@ export interface BadgePickTarget extends EventTarget { export interface SubElementEditorConfig { index?: number; - path?: (string | number)[]; elementConfig?: | LovelaceRowConfig | LovelaceHeaderFooterConfig | LovelaceCardFeatureConfig | LovelaceElementConfig | HeadingEntityConfig; + saveElementConfig?: (elementConfig: any) => void; context?: any; type: "header" | "footer" | "row" | "feature" | "element" | "heading-entity"; } -export interface EditSubElementEvent { - path: (string | number)[]; +export interface EditSubElementEvent { type: SubElementEditorConfig["type"]; - context?: any; + context?: C; + config: T; + saveConfig: (config: T) => void; } export interface EditDetailElementEvent {