Use getStubConfig for picture-elements (and more fixes) (#21579)

This commit is contained in:
karwosts 2024-08-05 08:05:31 -07:00 committed by GitHub
parent 51b6d7758d
commit 0adee7d189
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 170 additions and 19 deletions

View File

@ -12,7 +12,7 @@ export function createStyledHuiElement(
if (elementConfig.style) {
Object.keys(elementConfig.style).forEach((prop) => {
element.style.setProperty(prop, elementConfig.style[prop]);
element.style.setProperty(prop, elementConfig.style![prop]);
});
}

View File

@ -35,7 +35,7 @@ export const createPictureElementElement = (config: LovelaceElementConfig) =>
export const getPictureElementClass = (type: string) =>
getLovelaceElementClass(
type,
type === "action-button" ? "service-button" : type,
"element",
ALWAYS_LOADED_TYPES,
LAZY_LOAD_TYPES

View File

@ -106,12 +106,23 @@ export class HuiConditionalElementEditor
private _elementsChanged(ev: CustomEvent): void {
ev.stopPropagation();
const oldLength = this._config?.elements?.length || 0;
const config = {
...this._config,
elements: ev.detail.elements as LovelaceElementConfig[],
} as LovelaceCardConfig;
fireEvent(this, "config-changed", { config });
const newLength = ev.detail.elements?.length || 0;
if (newLength === oldLength + 1) {
const index = newLength - 1;
this._subElementEditorConfig = {
index,
type: "element",
elementConfig: { ...ev.detail.elements[index] },
};
}
}
private _handleSubElementChanged(ev: CustomEvent): void {

View File

@ -138,12 +138,23 @@ export class HuiPictureElementsCardEditor
private _elementsChanged(ev: CustomEvent): void {
ev.stopPropagation();
const oldLength = this._config?.elements?.length || 0;
const config = {
...this._config,
elements: ev.detail.elements as LovelaceElementConfig[],
} as LovelaceCardConfig;
fireEvent(this, "config-changed", { config });
const newLength = ev.detail.elements?.length || 0;
if (newLength === oldLength + 1) {
const index = newLength - 1;
this._subElementEditorConfig = {
index,
type: "element",
elementConfig: { ...ev.detail.elements[index] },
};
}
}
private _handleSubElementChanged(ev: CustomEvent): void {

View File

@ -0,0 +1,30 @@
import { LovelaceElementConfig } from "../elements/types";
import { HomeAssistant } from "../../../types";
import { getPictureElementClass } from "../create-element/create-picture-element";
export const getElementStubConfig = async (
hass: HomeAssistant,
type: string,
entities: string[],
entitiesFallback: string[]
): Promise<LovelaceElementConfig> => {
let elementConfig: LovelaceElementConfig = { type };
if (type !== "conditional") {
elementConfig.style = { left: "50%", top: "50%" };
}
const elClass = await getPictureElementClass(type);
if (elClass && elClass.getStubConfig) {
const classStubConfig = await elClass.getStubConfig(
hass,
entities,
entitiesFallback
);
elementConfig = { ...elementConfig, ...classStubConfig };
}
return elementConfig;
};

View File

@ -1,3 +1,4 @@
import deepClone from "deep-clone-simple";
import { mdiClose, mdiPencil, mdiContentDuplicate } from "@mdi/js";
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
import { customElement, property, query } from "lit/decorators";
@ -9,6 +10,7 @@ import { HomeAssistant } from "../../../types";
import "../../../components/ha-select";
import type { HaSelect } from "../../../components/ha-select";
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
import { getElementStubConfig } from "./get-element-stub-config";
import {
ConditionalElementConfig,
IconElementConfig,
@ -171,17 +173,14 @@ export class HuiPictureElementsCardRowEditor extends LitElement {
if (value === "") {
return;
}
const newElements = this.elements!.concat({
type: value! as string,
...(value !== "conditional"
? {
style: {
top: "50%",
left: "50%",
},
}
: {}),
} as LovelaceElementConfig);
const newElements = this.elements!.concat(
await getElementStubConfig(
this.hass!,
value,
Object.keys(this.hass!.entities),
[]
)
);
fireEvent(this, "elements-changed", { elements: newElements });
this._select.select(-1);
}
@ -225,7 +224,7 @@ export class HuiPictureElementsCardRowEditor extends LitElement {
private _duplicateRow(ev: CustomEvent): void {
const index = (ev.currentTarget as any).index;
const newElements = [...this.elements!, this.elements![index]];
const newElements = [...this.elements!, deepClone(this.elements![index])];
fireEvent(this, "elements-changed", { elements: newElements });
}

View File

@ -53,9 +53,19 @@ export class HuiSubElementEditor extends LitElement {
@click=${this._goBack}
></ha-icon-button-prev>
<span slot="title"
>${this.hass.localize(
`ui.panel.lovelace.editor.sub-element-editor.types.${this.config?.type}`
)}</span
>${this.config?.type === "element"
? this.hass.localize(
`ui.panel.lovelace.editor.sub-element-editor.types.element_type`,
{
type:
this.hass.localize(
`ui.panel.lovelace.editor.card.picture-elements.element_types.${this.config?.elementConfig?.type}`
) || this.config?.elementConfig?.type,
}
)
: this.hass.localize(
`ui.panel.lovelace.editor.sub-element-editor.types.${this.config?.type}`
)}</span
>
</div>
<ha-icon-button

View File

@ -18,6 +18,10 @@ export class HuiIconElement extends LitElement implements LovelaceElement {
return document.createElement("hui-icon-element-editor");
}
public static getStubConfig(): IconElementConfig {
return { type: "icon", icon: "mdi:alert-circle" };
}
public hass?: HomeAssistant;
@state() private _config?: IconElementConfig;

View File

@ -17,6 +17,14 @@ export class HuiServiceButtonElement
return document.createElement("hui-service-button-element-editor");
}
public static getStubConfig(hass: HomeAssistant): ServiceButtonElementConfig {
return {
type: "action-button",
action: "homeassistant.turn_on",
title: hass.localize("ui.card.common.turn_on"),
};
}
public hass?: HomeAssistant;
@state() private _config?: ServiceButtonElementConfig;

View File

@ -1,6 +1,8 @@
import type { HassEntity } from "home-assistant-js-websocket";
import { LitElement, PropertyValues, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { findEntities } from "../common/find-entities";
import { computeStateName } from "../../../common/entity/compute_state_name";
import "../../../components/entity/ha-state-label-badge";
import { ActionHandlerEvent } from "../../../data/lovelace/action_handler";
@ -8,6 +10,7 @@ import { HomeAssistant } from "../../../types";
import { actionHandler } from "../common/directives/action-handler-directive";
import { handleAction } from "../common/handle-action";
import { hasAction } from "../common/has-action";
import { isUnavailableState } from "../../../data/entity";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import "../components/hui-warning-element";
@ -26,6 +29,27 @@ export class HuiStateBadgeElement
return document.createElement("hui-state-badge-element-editor");
}
public static getStubConfig(
hass: HomeAssistant,
entities: string[],
entitiesFallback: string[]
): StateBadgeElementConfig {
const includeDomains = ["light", "switch", "sensor"];
const maxEntities = 1;
const entityFilter = (stateObj: HassEntity): boolean =>
!isUnavailableState(stateObj.state);
const foundEntities = findEntities(
hass,
maxEntities,
entities,
entitiesFallback,
includeDomains,
entityFilter
);
return { type: "state-badge", entity: foundEntities[0] || "" };
}
@property({ attribute: false }) public hass?: HomeAssistant;
@state() private _config?: StateBadgeElementConfig;

View File

@ -1,3 +1,4 @@
import type { HassEntity } from "home-assistant-js-websocket";
import {
css,
CSSResultGroup,
@ -8,12 +9,14 @@ import {
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { findEntities } from "../common/find-entities";
import "../../../components/entity/state-badge";
import { HomeAssistant } from "../../../types";
import { computeTooltip } from "../common/compute-tooltip";
import { actionHandler } from "../common/directives/action-handler-directive";
import { handleAction } from "../common/handle-action";
import { hasAction } from "../common/has-action";
import { isUnavailableState } from "../../../data/entity";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import "../components/hui-warning-element";
@ -30,6 +33,27 @@ export class HuiStateIconElement extends LitElement implements LovelaceElement {
return document.createElement("hui-state-icon-element-editor");
}
public static getStubConfig(
hass: HomeAssistant,
entities: string[],
entitiesFallback: string[]
): StateIconElementConfig {
const includeDomains = ["light", "switch", "sensor"];
const maxEntities = 1;
const entityFilter = (stateObj: HassEntity): boolean =>
!isUnavailableState(stateObj.state);
const foundEntities = findEntities(
hass,
maxEntities,
entities,
entitiesFallback,
includeDomains,
entityFilter
);
return { type: "state-icon", entity: foundEntities[0] || "" };
}
@property({ attribute: false }) public hass?: HomeAssistant;
@state() private _config?: StateIconElementConfig;

View File

@ -1,3 +1,4 @@
import type { HassEntity } from "home-assistant-js-websocket";
import {
CSSResultGroup,
LitElement,
@ -8,12 +9,14 @@ import {
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { findEntities } from "../common/find-entities";
import { ActionHandlerEvent } from "../../../data/lovelace/action_handler";
import { HomeAssistant } from "../../../types";
import { computeTooltip } from "../common/compute-tooltip";
import { actionHandler } from "../common/directives/action-handler-directive";
import { handleAction } from "../common/handle-action";
import { hasAction } from "../common/has-action";
import { isUnavailableState } from "../../../data/entity";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import "../components/hui-warning-element";
@ -29,6 +32,27 @@ class HuiStateLabelElement extends LitElement implements LovelaceElement {
return document.createElement("hui-state-label-element-editor");
}
public static getStubConfig(
hass: HomeAssistant,
entities: string[],
entitiesFallback: string[]
): StateLabelElementConfig {
const includeDomains = ["light", "switch", "sensor"];
const maxEntities = 1;
const entityFilter = (stateObj: HassEntity): boolean =>
!isUnavailableState(stateObj.state);
const foundEntities = findEntities(
hass,
maxEntities,
entities,
entitiesFallback,
includeDomains,
entityFilter
);
return { type: "state-label", entity: foundEntities[0] || "" };
}
@property({ attribute: false }) public hass?: HomeAssistant;
@state() private _config?: StateLabelElementConfig;

View File

@ -6,7 +6,7 @@ import { HuiImage } from "../components/hui-image";
interface LovelaceElementConfigBase {
type: string;
style: Record<string, string>;
style?: Record<string, string>;
}
export type LovelaceElementConfig =

View File

@ -109,6 +109,11 @@ export interface LovelaceRowConstructor extends Constructor<LovelaceRow> {
export interface LovelaceElementConstructor
extends Constructor<LovelaceElement> {
getConfigElement?: () => LovelacePictureElementEditor;
getStubConfig?: (
hass: HomeAssistant,
entities: string[],
entitiesFallback: string[]
) => LovelaceElementConfig;
}
export interface LovelaceHeaderFooter extends HTMLElement {

View File

@ -6323,7 +6323,8 @@
"footer": "Footer editor",
"row": "Entity row editor",
"feature": "Feature editor",
"element": "Element editor"
"element": "Element editor",
"element_type": "{type} element editor"
}
}
},