mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Move sub element editor inside hui-element-editor. (#22079)
* Move sub element editor into hui-element-editor * Migrate feature editor * Migrate feature editor * Simplify context
This commit is contained in:
parent
765812331b
commit
cd631e8693
17
src/common/util/nested-object.ts
Normal file
17
src/common/util/nested-object.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
export function updateNestedObject<T = any>(
|
||||||
|
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));
|
||||||
|
}
|
@ -20,7 +20,7 @@ import {
|
|||||||
import "../../conditions/ha-card-conditions-editor";
|
import "../../conditions/ha-card-conditions-editor";
|
||||||
import "../../hui-picture-elements-card-row-editor";
|
import "../../hui-picture-elements-card-row-editor";
|
||||||
import { LovelaceCardConfig } from "../../../../../data/lovelace/config/card";
|
import { LovelaceCardConfig } from "../../../../../data/lovelace/config/card";
|
||||||
import { EditSubElementEvent, SubElementEditorConfig } from "../../types";
|
import { EditDetailElementEvent, SubElementEditorConfig } from "../../types";
|
||||||
import "../../hui-sub-element-editor";
|
import "../../hui-sub-element-editor";
|
||||||
import { SchemaUnion } from "../../../../../components/ha-form/types";
|
import { SchemaUnion } from "../../../../../components/ha-form/types";
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ export class HuiConditionalElementEditor
|
|||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _editDetailElement(ev: HASSDomEvent<EditSubElementEvent>): void {
|
private _editDetailElement(ev: HASSDomEvent<EditDetailElementEvent>): void {
|
||||||
this._subElementEditorConfig = ev.detail.subElementConfig;
|
this._subElementEditorConfig = ev.detail.subElementConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ import { buttonEntityConfigStruct } from "../structs/button-entity-struct";
|
|||||||
import { entitiesConfigStruct } from "../structs/entities-struct";
|
import { entitiesConfigStruct } from "../structs/entities-struct";
|
||||||
import {
|
import {
|
||||||
EditorTarget,
|
EditorTarget,
|
||||||
EditSubElementEvent,
|
EditDetailElementEvent,
|
||||||
SubElementEditorConfig,
|
SubElementEditorConfig,
|
||||||
} from "../types";
|
} from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
@ -401,7 +401,7 @@ export class HuiEntitiesCardEditor
|
|||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _editDetailElement(ev: HASSDomEvent<EditSubElementEvent>): void {
|
private _editDetailElement(ev: HASSDomEvent<EditDetailElementEvent>): void {
|
||||||
this._subElementEditorConfig = ev.detail.subElementConfig;
|
this._subElementEditorConfig = ev.detail.subElementConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { mdiGestureTap, mdiListBox } from "@mdi/js";
|
import { mdiGestureTap, mdiListBox } from "@mdi/js";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { cache } from "lit/directives/cache";
|
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import {
|
import {
|
||||||
any,
|
any,
|
||||||
@ -26,11 +25,9 @@ import type { HomeAssistant } from "../../../../types";
|
|||||||
import type { HeadingCardConfig, HeadingEntityConfig } from "../../cards/types";
|
import type { HeadingCardConfig, HeadingEntityConfig } from "../../cards/types";
|
||||||
import { UiAction } from "../../components/hui-action-editor";
|
import { UiAction } from "../../components/hui-action-editor";
|
||||||
import type { LovelaceCardEditor } from "../../types";
|
import type { LovelaceCardEditor } from "../../types";
|
||||||
import "../hui-sub-element-editor";
|
|
||||||
import { processEditorEntities } from "../process-editor-entities";
|
import { processEditorEntities } from "../process-editor-entities";
|
||||||
import { actionConfigStruct } from "../structs/action-struct";
|
import { actionConfigStruct } from "../structs/action-struct";
|
||||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
import { SubElementEditorConfig } from "../types";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import "./hui-entities-editor";
|
import "./hui-entities-editor";
|
||||||
|
|
||||||
@ -56,9 +53,6 @@ export class HuiHeadingCardEditor
|
|||||||
|
|
||||||
@state() private _config?: HeadingCardConfig;
|
@state() private _config?: HeadingCardConfig;
|
||||||
|
|
||||||
@state()
|
|
||||||
private _subElementEditorConfig?: SubElementEditorConfig;
|
|
||||||
|
|
||||||
public setConfig(config: HeadingCardConfig): void {
|
public setConfig(config: HeadingCardConfig): void {
|
||||||
assert(config, cardConfigStruct);
|
assert(config, cardConfigStruct);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
@ -108,35 +102,15 @@ export class HuiHeadingCardEditor
|
|||||||
] as const satisfies readonly HaFormSchema[]
|
] as const satisfies readonly HaFormSchema[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private _entities = memoizeOne((entities: HeadingCardConfig["entities"]) =>
|
||||||
|
processEditorEntities(entities || [])
|
||||||
|
);
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this.hass || !this._config) {
|
if (!this.hass || !this._config) {
|
||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cache(
|
|
||||||
this._subElementEditorConfig
|
|
||||||
? this._renderEntityForm()
|
|
||||||
: this._renderForm()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _renderEntityForm() {
|
|
||||||
return html`
|
|
||||||
<hui-sub-element-editor
|
|
||||||
.hass=${this.hass}
|
|
||||||
.config=${this._subElementEditorConfig}
|
|
||||||
@go-back=${this._goBack}
|
|
||||||
@config-changed=${this._subElementChanged}
|
|
||||||
>
|
|
||||||
</hui-sub-element-editor>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _entities = memoizeOne((entities: HeadingCardConfig["entities"]) =>
|
|
||||||
processEditorEntities(entities || [])
|
|
||||||
);
|
|
||||||
|
|
||||||
private _renderForm() {
|
|
||||||
const data = {
|
const data = {
|
||||||
...this._config!,
|
...this._config!,
|
||||||
};
|
};
|
||||||
@ -200,46 +174,12 @@ export class HuiHeadingCardEditor
|
|||||||
fireEvent(this, "config-changed", { config });
|
fireEvent(this, "config-changed", { config });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _subElementChanged(ev: CustomEvent): void {
|
|
||||||
ev.stopPropagation();
|
|
||||||
if (!this._config || !this.hass) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const value = ev.detail.config;
|
|
||||||
|
|
||||||
const newConfigEntities = this._config!.entities
|
|
||||||
? [...this._config!.entities]
|
|
||||||
: [];
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
newConfigEntities.splice(this._subElementEditorConfig!.index!, 1);
|
|
||||||
this._goBack();
|
|
||||||
} else {
|
|
||||||
newConfigEntities[this._subElementEditorConfig!.index!] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._config = { ...this._config!, entities: newConfigEntities };
|
|
||||||
|
|
||||||
this._subElementEditorConfig = {
|
|
||||||
...this._subElementEditorConfig!,
|
|
||||||
elementConfig: value,
|
|
||||||
};
|
|
||||||
|
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
|
||||||
}
|
|
||||||
|
|
||||||
private _editEntity(ev: HASSDomEvent<{ index: number }>): void {
|
private _editEntity(ev: HASSDomEvent<{ index: number }>): void {
|
||||||
const entities = this._entities(this._config!.entities);
|
ev.stopPropagation();
|
||||||
this._subElementEditorConfig = {
|
fireEvent(this, "edit-sub-element", {
|
||||||
elementConfig: entities[ev.detail.index],
|
path: ["entities", ev.detail.index],
|
||||||
index: ev.detail.index,
|
|
||||||
type: "heading-entity",
|
type: "heading-entity",
|
||||||
};
|
});
|
||||||
}
|
|
||||||
|
|
||||||
private _goBack(): void {
|
|
||||||
this._subElementEditorConfig = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeLabelCallback = (
|
private _computeLabelCallback = (
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { mdiListBox } from "@mdi/js";
|
import { mdiListBox } 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 { cache } from "lit/directives/cache";
|
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import {
|
import {
|
||||||
any,
|
any,
|
||||||
array,
|
array,
|
||||||
@ -28,9 +26,8 @@ import {
|
|||||||
} from "../../card-features/types";
|
} from "../../card-features/types";
|
||||||
import type { HumidifierCardConfig } from "../../cards/types";
|
import type { HumidifierCardConfig } from "../../cards/types";
|
||||||
import type { LovelaceCardEditor } from "../../types";
|
import type { LovelaceCardEditor } from "../../types";
|
||||||
import "../hui-sub-element-editor";
|
|
||||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
import { EditSubElementEvent, SubElementEditorConfig } from "../types";
|
import { EditDetailElementEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import "./hui-card-features-editor";
|
import "./hui-card-features-editor";
|
||||||
import type { FeatureType } from "./hui-card-features-editor";
|
import type { FeatureType } from "./hui-card-features-editor";
|
||||||
@ -82,44 +79,16 @@ export class HuiHumidifierCardEditor
|
|||||||
|
|
||||||
@state() private _config?: HumidifierCardConfig;
|
@state() private _config?: HumidifierCardConfig;
|
||||||
|
|
||||||
@state() private _subElementEditorConfig?: SubElementEditorConfig;
|
|
||||||
|
|
||||||
public setConfig(config: HumidifierCardConfig): void {
|
public setConfig(config: HumidifierCardConfig): void {
|
||||||
assert(config, cardConfigStruct);
|
assert(config, cardConfigStruct);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _context = memoizeOne(
|
|
||||||
(entity_id?: string): LovelaceCardFeatureContext => ({ entity_id })
|
|
||||||
);
|
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this.hass || !this._config) {
|
if (!this.hass || !this._config) {
|
||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cache(
|
|
||||||
this._subElementEditorConfig
|
|
||||||
? this._renderFeatureForm()
|
|
||||||
: this._renderForm()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _renderFeatureForm() {
|
|
||||||
const entityId = this._config!.entity;
|
|
||||||
return html`
|
|
||||||
<hui-sub-element-editor
|
|
||||||
.hass=${this.hass}
|
|
||||||
.config=${this._subElementEditorConfig}
|
|
||||||
.context=${this._context(entityId)}
|
|
||||||
@go-back=${this._goBack}
|
|
||||||
@config-changed=${this.subElementChanged}
|
|
||||||
>
|
|
||||||
</hui-sub-element-editor>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _renderForm() {
|
|
||||||
const entityId = this._config!.entity;
|
const entityId = this._config!.entity;
|
||||||
const stateObj = entityId ? this.hass!.states[entityId] : undefined;
|
const stateObj = entityId ? this.hass!.states[entityId] : undefined;
|
||||||
|
|
||||||
@ -175,41 +144,14 @@ export class HuiHumidifierCardEditor
|
|||||||
fireEvent(this, "config-changed", { config });
|
fireEvent(this, "config-changed", { config });
|
||||||
}
|
}
|
||||||
|
|
||||||
private subElementChanged(ev: CustomEvent): void {
|
private _editDetailElement(ev: HASSDomEvent<EditDetailElementEvent>): void {
|
||||||
ev.stopPropagation();
|
fireEvent(this, "edit-sub-element", {
|
||||||
if (!this._config || !this.hass) {
|
path: ["features", ev.detail.subElementConfig.index!],
|
||||||
return;
|
context: {
|
||||||
}
|
entity_id: this._config!.entity,
|
||||||
|
} as LovelaceCardFeatureContext,
|
||||||
const value = ev.detail.config;
|
type: "feature",
|
||||||
|
});
|
||||||
const newConfigFeatures = this._config!.features
|
|
||||||
? [...this._config!.features]
|
|
||||||
: [];
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
newConfigFeatures.splice(this._subElementEditorConfig!.index!, 1);
|
|
||||||
this._goBack();
|
|
||||||
} else {
|
|
||||||
newConfigFeatures[this._subElementEditorConfig!.index!] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._config = { ...this._config!, features: newConfigFeatures };
|
|
||||||
|
|
||||||
this._subElementEditorConfig = {
|
|
||||||
...this._subElementEditorConfig!,
|
|
||||||
elementConfig: value,
|
|
||||||
};
|
|
||||||
|
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
|
||||||
}
|
|
||||||
|
|
||||||
private _editDetailElement(ev: HASSDomEvent<EditSubElementEvent>): void {
|
|
||||||
this._subElementEditorConfig = ev.detail.subElementConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _goBack(): void {
|
|
||||||
this._subElementEditorConfig = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeLabelCallback = (schema: SchemaUnion<typeof SCHEMA>) => {
|
private _computeLabelCallback = (schema: SchemaUnion<typeof SCHEMA>) => {
|
||||||
|
@ -21,7 +21,7 @@ import type { PictureElementsCardConfig } from "../../cards/types";
|
|||||||
import type { LovelaceCardEditor } from "../../types";
|
import type { LovelaceCardEditor } from "../../types";
|
||||||
import "../hui-sub-element-editor";
|
import "../hui-sub-element-editor";
|
||||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
import { EditSubElementEvent, SubElementEditorConfig } from "../types";
|
import { EditDetailElementEvent, SubElementEditorConfig } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import "../hui-picture-elements-card-row-editor";
|
import "../hui-picture-elements-card-row-editor";
|
||||||
import { LovelaceElementConfig } from "../../elements/types";
|
import { LovelaceElementConfig } from "../../elements/types";
|
||||||
@ -186,7 +186,7 @@ export class HuiPictureElementsCardEditor
|
|||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _editDetailElement(ev: HASSDomEvent<EditSubElementEvent>): void {
|
private _editDetailElement(ev: HASSDomEvent<EditDetailElementEvent>): void {
|
||||||
this._subElementEditorConfig = ev.detail.subElementConfig;
|
this._subElementEditorConfig = ev.detail.subElementConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { mdiListBox } from "@mdi/js";
|
import { mdiListBox } 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 { cache } from "lit/directives/cache";
|
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import {
|
import {
|
||||||
any,
|
any,
|
||||||
array,
|
array,
|
||||||
@ -28,9 +26,8 @@ import {
|
|||||||
} from "../../card-features/types";
|
} from "../../card-features/types";
|
||||||
import type { ThermostatCardConfig } from "../../cards/types";
|
import type { ThermostatCardConfig } from "../../cards/types";
|
||||||
import type { LovelaceCardEditor } from "../../types";
|
import type { LovelaceCardEditor } from "../../types";
|
||||||
import "../hui-sub-element-editor";
|
|
||||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
import { EditSubElementEvent, SubElementEditorConfig } from "../types";
|
import { EditDetailElementEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import "./hui-card-features-editor";
|
import "./hui-card-features-editor";
|
||||||
import type { FeatureType } from "./hui-card-features-editor";
|
import type { FeatureType } from "./hui-card-features-editor";
|
||||||
@ -80,43 +77,16 @@ export class HuiThermostatCardEditor
|
|||||||
|
|
||||||
@state() private _config?: ThermostatCardConfig;
|
@state() private _config?: ThermostatCardConfig;
|
||||||
|
|
||||||
@state() private _subElementEditorConfig?: SubElementEditorConfig;
|
|
||||||
|
|
||||||
public setConfig(config: ThermostatCardConfig): void {
|
public setConfig(config: ThermostatCardConfig): void {
|
||||||
assert(config, cardConfigStruct);
|
assert(config, cardConfigStruct);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _context = memoizeOne(
|
|
||||||
(entity_id?: string): LovelaceCardFeatureContext => ({ entity_id })
|
|
||||||
);
|
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this.hass || !this._config) {
|
if (!this.hass || !this._config) {
|
||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cache(
|
|
||||||
this._subElementEditorConfig
|
|
||||||
? this._renderFeatureForm()
|
|
||||||
: this._renderForm()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _renderFeatureForm() {
|
|
||||||
return html`
|
|
||||||
<hui-sub-element-editor
|
|
||||||
.hass=${this.hass}
|
|
||||||
.config=${this._subElementEditorConfig}
|
|
||||||
.context=${this._context(this._config!.entity)}
|
|
||||||
@go-back=${this._goBack}
|
|
||||||
@config-changed=${this.subElementChanged}
|
|
||||||
>
|
|
||||||
</hui-sub-element-editor>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _renderForm() {
|
|
||||||
const entityId = this._config!.entity;
|
const entityId = this._config!.entity;
|
||||||
const stateObj = entityId ? this.hass!.states[entityId] : undefined;
|
const stateObj = entityId ? this.hass!.states[entityId] : undefined;
|
||||||
|
|
||||||
@ -172,41 +142,14 @@ export class HuiThermostatCardEditor
|
|||||||
fireEvent(this, "config-changed", { config });
|
fireEvent(this, "config-changed", { config });
|
||||||
}
|
}
|
||||||
|
|
||||||
private subElementChanged(ev: CustomEvent): void {
|
private _editDetailElement(ev: HASSDomEvent<EditDetailElementEvent>): void {
|
||||||
ev.stopPropagation();
|
fireEvent(this, "edit-sub-element", {
|
||||||
if (!this._config || !this.hass) {
|
path: ["features", ev.detail.subElementConfig.index!],
|
||||||
return;
|
context: {
|
||||||
}
|
entity_id: this._config!.entity,
|
||||||
|
} as LovelaceCardFeatureContext,
|
||||||
const value = ev.detail.config;
|
type: "feature",
|
||||||
|
});
|
||||||
const newConfigFeatures = this._config!.features
|
|
||||||
? [...this._config!.features]
|
|
||||||
: [];
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
newConfigFeatures.splice(this._subElementEditorConfig!.index!, 1);
|
|
||||||
this._goBack();
|
|
||||||
} else {
|
|
||||||
newConfigFeatures[this._subElementEditorConfig!.index!] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._config = { ...this._config!, features: newConfigFeatures };
|
|
||||||
|
|
||||||
this._subElementEditorConfig = {
|
|
||||||
...this._subElementEditorConfig!,
|
|
||||||
elementConfig: value,
|
|
||||||
};
|
|
||||||
|
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
|
||||||
}
|
|
||||||
|
|
||||||
private _editDetailElement(ev: HASSDomEvent<EditSubElementEvent>): void {
|
|
||||||
this._subElementEditorConfig = ev.detail.subElementConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _goBack(): void {
|
|
||||||
this._subElementEditorConfig = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeLabelCallback = (schema: SchemaUnion<typeof SCHEMA>) => {
|
private _computeLabelCallback = (schema: SchemaUnion<typeof SCHEMA>) => {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { mdiGestureTap, mdiListBox, mdiPalette } from "@mdi/js";
|
import { mdiGestureTap, mdiListBox, mdiPalette } 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 { cache } from "lit/directives/cache";
|
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import {
|
import {
|
||||||
any,
|
any,
|
||||||
@ -30,10 +29,9 @@ import {
|
|||||||
import { getEntityDefaultTileIconAction } from "../../cards/hui-tile-card";
|
import { getEntityDefaultTileIconAction } from "../../cards/hui-tile-card";
|
||||||
import type { TileCardConfig } from "../../cards/types";
|
import type { TileCardConfig } from "../../cards/types";
|
||||||
import type { LovelaceCardEditor } from "../../types";
|
import type { LovelaceCardEditor } from "../../types";
|
||||||
import "../hui-sub-element-editor";
|
|
||||||
import { actionConfigStruct } from "../structs/action-struct";
|
import { actionConfigStruct } from "../structs/action-struct";
|
||||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
import { EditSubElementEvent, SubElementEditorConfig } from "../types";
|
import { EditDetailElementEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import "./hui-card-features-editor";
|
import "./hui-card-features-editor";
|
||||||
|
|
||||||
@ -63,8 +61,6 @@ export class HuiTileCardEditor
|
|||||||
|
|
||||||
@state() private _config?: TileCardConfig;
|
@state() private _config?: TileCardConfig;
|
||||||
|
|
||||||
@state() private _subElementEditorConfig?: SubElementEditorConfig;
|
|
||||||
|
|
||||||
public setConfig(config: TileCardConfig): void {
|
public setConfig(config: TileCardConfig): void {
|
||||||
assert(config, cardConfigStruct);
|
assert(config, cardConfigStruct);
|
||||||
this._config = config;
|
this._config = config;
|
||||||
@ -165,36 +161,11 @@ export class HuiTileCardEditor
|
|||||||
] as const satisfies readonly HaFormSchema[]
|
] as const satisfies readonly HaFormSchema[]
|
||||||
);
|
);
|
||||||
|
|
||||||
private _context = memoizeOne(
|
|
||||||
(entity_id?: string): LovelaceCardFeatureContext => ({ entity_id })
|
|
||||||
);
|
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this.hass || !this._config) {
|
if (!this.hass || !this._config) {
|
||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cache(
|
|
||||||
this._subElementEditorConfig
|
|
||||||
? this._renderFeatureForm()
|
|
||||||
: this._renderForm()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _renderFeatureForm() {
|
|
||||||
return html`
|
|
||||||
<hui-sub-element-editor
|
|
||||||
.hass=${this.hass}
|
|
||||||
.config=${this._subElementEditorConfig}
|
|
||||||
.context=${this._context(this._config!.entity)}
|
|
||||||
@go-back=${this._goBack}
|
|
||||||
@config-changed=${this.subElementChanged}
|
|
||||||
>
|
|
||||||
</hui-sub-element-editor>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _renderForm() {
|
|
||||||
const entityId = this._config!.entity;
|
const entityId = this._config!.entity;
|
||||||
const stateObj = entityId ? this.hass!.states[entityId] : undefined;
|
const stateObj = entityId ? this.hass!.states[entityId] : undefined;
|
||||||
|
|
||||||
@ -274,41 +245,14 @@ export class HuiTileCardEditor
|
|||||||
fireEvent(this, "config-changed", { config });
|
fireEvent(this, "config-changed", { config });
|
||||||
}
|
}
|
||||||
|
|
||||||
private subElementChanged(ev: CustomEvent): void {
|
private _editDetailElement(ev: HASSDomEvent<EditDetailElementEvent>): void {
|
||||||
ev.stopPropagation();
|
fireEvent(this, "edit-sub-element", {
|
||||||
if (!this._config || !this.hass) {
|
path: ["features", ev.detail.subElementConfig.index!],
|
||||||
return;
|
context: {
|
||||||
}
|
entity_id: this._config!.entity,
|
||||||
|
} as LovelaceCardFeatureContext,
|
||||||
const value = ev.detail.config;
|
type: "feature",
|
||||||
|
});
|
||||||
const newConfigFeatures = this._config!.features
|
|
||||||
? [...this._config!.features]
|
|
||||||
: [];
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
newConfigFeatures.splice(this._subElementEditorConfig!.index!, 1);
|
|
||||||
this._goBack();
|
|
||||||
} else {
|
|
||||||
newConfigFeatures[this._subElementEditorConfig!.index!] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._config = { ...this._config!, features: newConfigFeatures };
|
|
||||||
|
|
||||||
this._subElementEditorConfig = {
|
|
||||||
...this._subElementEditorConfig!,
|
|
||||||
elementConfig: value,
|
|
||||||
};
|
|
||||||
|
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
|
||||||
}
|
|
||||||
|
|
||||||
private _editDetailElement(ev: HASSDomEvent<EditSubElementEvent>): void {
|
|
||||||
this._subElementEditorConfig = ev.detail.subElementConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _goBack(): void {
|
|
||||||
this._subElementEditorConfig = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeLabelCallback = (
|
private _computeLabelCallback = (
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
import {
|
import {
|
||||||
|
css,
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
nothing,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
css,
|
|
||||||
html,
|
|
||||||
nothing,
|
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { property, query, state } from "lit/decorators";
|
import { property, query, state } from "lit/decorators";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { cache } from "lit/directives/cache";
|
||||||
|
import { fireEvent, HASSDomEvent } from "../../../common/dom/fire_event";
|
||||||
import { handleStructError } from "../../../common/structs/handle-errors";
|
import { handleStructError } from "../../../common/structs/handle-errors";
|
||||||
import { deepEqual } from "../../../common/util/deep-equal";
|
import { deepEqual } from "../../../common/util/deep-equal";
|
||||||
|
import {
|
||||||
|
findNestedObject,
|
||||||
|
updateNestedObject,
|
||||||
|
} from "../../../common/util/nested-object";
|
||||||
import "../../../components/ha-alert";
|
import "../../../components/ha-alert";
|
||||||
import "../../../components/ha-circular-progress";
|
import "../../../components/ha-circular-progress";
|
||||||
import "../../../components/ha-yaml-editor";
|
import "../../../components/ha-yaml-editor";
|
||||||
@ -23,7 +28,12 @@ import type {
|
|||||||
} from "../types";
|
} from "../types";
|
||||||
import type { HuiFormEditor } from "./config-elements/hui-form-editor";
|
import type { HuiFormEditor } from "./config-elements/hui-form-editor";
|
||||||
import { GUISupportError } from "./gui-support-error";
|
import { GUISupportError } from "./gui-support-error";
|
||||||
import { EditSubElementEvent, GUIModeChangedEvent } from "./types";
|
import {
|
||||||
|
EditDetailElementEvent,
|
||||||
|
EditSubElementEvent,
|
||||||
|
GUIModeChangedEvent,
|
||||||
|
SubElementEditorConfig,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
export interface ConfigChangedEvent<T extends object = object> {
|
export interface ConfigChangedEvent<T extends object = object> {
|
||||||
config: T;
|
config: T;
|
||||||
@ -35,7 +45,8 @@ declare global {
|
|||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
"config-changed": ConfigChangedEvent;
|
"config-changed": ConfigChangedEvent;
|
||||||
"GUImode-changed": GUIModeChangedEvent;
|
"GUImode-changed": GUIModeChangedEvent;
|
||||||
"edit-detail-element": EditSubElementEvent;
|
"edit-detail-element": EditDetailElementEvent;
|
||||||
|
"edit-sub-element": EditSubElementEvent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +70,8 @@ export abstract class HuiElementEditor<
|
|||||||
|
|
||||||
@state() private _configElement?: LovelaceGenericElementEditor;
|
@state() private _configElement?: LovelaceGenericElementEditor;
|
||||||
|
|
||||||
|
@state() private _subElementEditorConfig?: SubElementEditorConfig;
|
||||||
|
|
||||||
@state() private _guiMode = true;
|
@state() private _guiMode = true;
|
||||||
|
|
||||||
// Error: Configuration broken - do not save
|
// Error: Configuration broken - do not save
|
||||||
@ -162,12 +175,71 @@ export abstract class HuiElementEditor<
|
|||||||
return html`${this._configElement}`;
|
return html`${this._configElement}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _renderSubElement() {
|
||||||
|
return html`
|
||||||
|
<hui-sub-element-editor
|
||||||
|
.hass=${this.hass}
|
||||||
|
.config=${this._subElementEditorConfig}
|
||||||
|
@go-back=${this._goBack}
|
||||||
|
@config-changed=${this._subElementChanged}
|
||||||
|
>
|
||||||
|
</hui-sub-element-editor>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _subElementChanged(ev: CustomEvent): void {
|
||||||
|
ev.stopPropagation();
|
||||||
|
|
||||||
|
const value = ev.detail.config;
|
||||||
|
|
||||||
|
this._subElementEditorConfig = {
|
||||||
|
...this._subElementEditorConfig!,
|
||||||
|
elementConfig: value,
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = updateNestedObject(
|
||||||
|
this._config,
|
||||||
|
this._subElementEditorConfig.path!,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
|
||||||
|
this._config = config;
|
||||||
|
this._setConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _goBack(ev): void {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this._subElementEditorConfig = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _editSubElement(
|
||||||
|
ev: HASSDomEvent<EditSubElementEvent>
|
||||||
|
): Promise<void> {
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
${this.GUImode
|
${this.GUImode
|
||||||
? html`
|
? html`
|
||||||
<div class="gui-editor">
|
<div class="gui-editor" @edit-sub-element=${this._editSubElement}>
|
||||||
${this._loading
|
${this._loading
|
||||||
? html`
|
? html`
|
||||||
<ha-circular-progress
|
<ha-circular-progress
|
||||||
@ -175,7 +247,11 @@ export abstract class HuiElementEditor<
|
|||||||
class="center margin-bot"
|
class="center margin-bot"
|
||||||
></ha-circular-progress>
|
></ha-circular-progress>
|
||||||
`
|
`
|
||||||
: this.renderConfigElement()}
|
: cache(
|
||||||
|
this._subElementEditorConfig
|
||||||
|
? this._renderSubElement()
|
||||||
|
: this.renderConfigElement()
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
|
@ -32,8 +32,6 @@ export class HuiSubElementEditor extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public config!: SubElementEditorConfig;
|
@property({ attribute: false }) public config!: SubElementEditorConfig;
|
||||||
|
|
||||||
@property({ attribute: false }) public context?: any;
|
|
||||||
|
|
||||||
@state() private _guiModeAvailable = true;
|
@state() private _guiModeAvailable = true;
|
||||||
|
|
||||||
@state() private _guiMode = true;
|
@state() private _guiMode = true;
|
||||||
@ -87,6 +85,7 @@ export class HuiSubElementEditor extends LitElement {
|
|||||||
|
|
||||||
private _renderEditor() {
|
private _renderEditor() {
|
||||||
const type = this.config.type;
|
const type = this.config.type;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "row":
|
case "row":
|
||||||
return html`
|
return html`
|
||||||
@ -94,7 +93,7 @@ export class HuiSubElementEditor extends LitElement {
|
|||||||
class="editor"
|
class="editor"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this.config.elementConfig}
|
.value=${this.config.elementConfig}
|
||||||
.context=${this.context}
|
.context=${this.config.context}
|
||||||
@config-changed=${this._handleConfigChanged}
|
@config-changed=${this._handleConfigChanged}
|
||||||
@GUImode-changed=${this._handleGUIModeChanged}
|
@GUImode-changed=${this._handleGUIModeChanged}
|
||||||
></hui-row-element-editor>
|
></hui-row-element-editor>
|
||||||
@ -106,7 +105,7 @@ export class HuiSubElementEditor extends LitElement {
|
|||||||
class="editor"
|
class="editor"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this.config.elementConfig}
|
.value=${this.config.elementConfig}
|
||||||
.context=${this.context}
|
.context=${this.config.context}
|
||||||
@config-changed=${this._handleConfigChanged}
|
@config-changed=${this._handleConfigChanged}
|
||||||
@GUImode-changed=${this._handleGUIModeChanged}
|
@GUImode-changed=${this._handleGUIModeChanged}
|
||||||
></hui-headerfooter-element-editor>
|
></hui-headerfooter-element-editor>
|
||||||
@ -117,7 +116,7 @@ export class HuiSubElementEditor extends LitElement {
|
|||||||
class="editor"
|
class="editor"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this.config.elementConfig}
|
.value=${this.config.elementConfig}
|
||||||
.context=${this.context}
|
.context=${this.config.context}
|
||||||
@config-changed=${this._handleConfigChanged}
|
@config-changed=${this._handleConfigChanged}
|
||||||
@GUImode-changed=${this._handleGUIModeChanged}
|
@GUImode-changed=${this._handleGUIModeChanged}
|
||||||
></hui-picture-element-element-editor>
|
></hui-picture-element-element-editor>
|
||||||
@ -128,7 +127,7 @@ export class HuiSubElementEditor extends LitElement {
|
|||||||
class="editor"
|
class="editor"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this.config.elementConfig}
|
.value=${this.config.elementConfig}
|
||||||
.context=${this.context}
|
.context=${this.config.context}
|
||||||
@config-changed=${this._handleConfigChanged}
|
@config-changed=${this._handleConfigChanged}
|
||||||
@GUImode-changed=${this._handleGUIModeChanged}
|
@GUImode-changed=${this._handleGUIModeChanged}
|
||||||
></hui-card-feature-element-editor>
|
></hui-card-feature-element-editor>
|
||||||
@ -139,7 +138,7 @@ export class HuiSubElementEditor extends LitElement {
|
|||||||
class="editor"
|
class="editor"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this.config.elementConfig}
|
.value=${this.config.elementConfig}
|
||||||
.context=${this.context}
|
.context=${this.config.context}
|
||||||
@config-changed=${this._handleConfigChanged}
|
@config-changed=${this._handleConfigChanged}
|
||||||
@GUImode-changed=${this._handleGUIModeChanged}
|
@GUImode-changed=${this._handleGUIModeChanged}
|
||||||
></hui-heading-entity-element-editor>
|
></hui-heading-entity-element-editor>
|
||||||
|
@ -92,15 +92,23 @@ export interface BadgePickTarget extends EventTarget {
|
|||||||
|
|
||||||
export interface SubElementEditorConfig {
|
export interface SubElementEditorConfig {
|
||||||
index?: number;
|
index?: number;
|
||||||
|
path?: (string | number)[];
|
||||||
elementConfig?:
|
elementConfig?:
|
||||||
| LovelaceRowConfig
|
| LovelaceRowConfig
|
||||||
| LovelaceHeaderFooterConfig
|
| LovelaceHeaderFooterConfig
|
||||||
| LovelaceCardFeatureConfig
|
| LovelaceCardFeatureConfig
|
||||||
| LovelaceElementConfig
|
| LovelaceElementConfig
|
||||||
| HeadingEntityConfig;
|
| HeadingEntityConfig;
|
||||||
|
context?: any;
|
||||||
type: "header" | "footer" | "row" | "feature" | "element" | "heading-entity";
|
type: "header" | "footer" | "row" | "feature" | "element" | "heading-entity";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EditSubElementEvent {
|
export interface EditSubElementEvent {
|
||||||
|
path: (string | number)[];
|
||||||
|
type: SubElementEditorConfig["type"];
|
||||||
|
context?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EditDetailElementEvent {
|
||||||
subElementConfig: SubElementEditorConfig;
|
subElementConfig: SubElementEditorConfig;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user