mirror of
https://github.com/home-assistant/frontend.git
synced 2025-10-17 07:39:42 +00:00
Add support for button card, glance card and entities card
This commit is contained in:
@@ -9,13 +9,14 @@ import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import { computeCssColor } from "../../../common/color/compute-color";
|
||||
import { DOMAINS_TOGGLE } from "../../../common/const";
|
||||
import { transform } from "../../../common/decorators/transform";
|
||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import { stateActive } from "../../../common/entity/state_active";
|
||||
import {
|
||||
stateColorBrightness,
|
||||
stateColorCss,
|
||||
@@ -40,6 +41,7 @@ import type { FrontendLocaleData } from "../../../data/translation";
|
||||
import type { Themes } from "../../../data/ws-themes";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { computeLovelaceEntityName } from "../common/entity/compute-lovelace-entity-name";
|
||||
import { findEntities } from "../common/find-entities";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { createEntityNotFoundWarning } from "../components/hui-warning";
|
||||
@@ -49,8 +51,6 @@ import type {
|
||||
LovelaceGridOptions,
|
||||
} from "../types";
|
||||
import type { ButtonCardConfig } from "./types";
|
||||
import { computeCssColor } from "../../../common/color/compute-color";
|
||||
import { stateActive } from "../../../common/entity/state_active";
|
||||
|
||||
export const getEntityDefaultButtonAction = (entityId?: string) =>
|
||||
entityId && DOMAINS_TOGGLE.has(computeDomain(entityId))
|
||||
@@ -183,9 +183,11 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
|
||||
`;
|
||||
}
|
||||
|
||||
const name = this._config.show_name
|
||||
? this._config.name || (stateObj ? computeStateName(stateObj) : "")
|
||||
: "";
|
||||
const name = computeLovelaceEntityName(
|
||||
this.hass,
|
||||
stateObj,
|
||||
this._config.name
|
||||
);
|
||||
|
||||
return html`
|
||||
<ha-card
|
||||
@@ -195,8 +197,7 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
role="button"
|
||||
aria-label=${this._config.name ||
|
||||
(stateObj ? computeStateName(stateObj) : "")}
|
||||
aria-label=${name}
|
||||
tabindex=${ifDefined(
|
||||
hasAction(this._config.tap_action) ? "0" : undefined
|
||||
)}
|
||||
|
@@ -5,7 +5,6 @@ import { classMap } from "lit/directives/class-map";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import "../../../components/entity/state-badge";
|
||||
import "../../../components/ha-card";
|
||||
import "../../../components/ha-icon";
|
||||
@@ -19,6 +18,7 @@ import type {
|
||||
import { SENSOR_DEVICE_CLASS_TIMESTAMP } from "../../../data/sensor";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { computeLovelaceEntityName } from "../common/entity/compute-lovelace-entity-name";
|
||||
import { findEntities } from "../common/find-entities";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
import { hasAction, hasAnyAction } from "../common/has-action";
|
||||
@@ -252,7 +252,11 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
</div>`;
|
||||
}
|
||||
|
||||
const name = entityConf.name ?? computeStateName(stateObj);
|
||||
const name = computeLovelaceEntityName(
|
||||
this.hass!,
|
||||
stateObj,
|
||||
entityConf.name
|
||||
);
|
||||
|
||||
return html`
|
||||
<div
|
||||
@@ -269,9 +273,9 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
: undefined
|
||||
)}
|
||||
>
|
||||
${this._config!.show_name
|
||||
? html` <div class="name" .title=${name}>${name}</div> `
|
||||
: ""}
|
||||
${this._config!.show_name && name
|
||||
? html`<div class="name" .title=${name}>${name}</div>`
|
||||
: nothing}
|
||||
${this._config!.show_icon
|
||||
? html`
|
||||
<state-badge
|
||||
|
@@ -4,6 +4,7 @@ import {
|
||||
type EntityNameItem,
|
||||
} from "../../../../common/entity/compute_entity_name_display";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import { ensureArray } from "../../../../common/array/ensure-array";
|
||||
|
||||
/**
|
||||
* Computes the display name for an entity in Lovelace (cards and badges).
|
||||
@@ -15,9 +16,21 @@ import type { HomeAssistant } from "../../../../types";
|
||||
*/
|
||||
export const computeLovelaceEntityName = (
|
||||
hass: HomeAssistant,
|
||||
stateObj: HassEntity,
|
||||
stateObj: HassEntity | undefined,
|
||||
nameConfig: string | EntityNameItem | EntityNameItem[] | undefined
|
||||
): string =>
|
||||
typeof nameConfig === "string"
|
||||
? nameConfig
|
||||
: hass.formatEntityName(stateObj, nameConfig || DEFAULT_ENTITY_NAME);
|
||||
): string => {
|
||||
if (typeof nameConfig === "string") {
|
||||
return nameConfig;
|
||||
}
|
||||
const config = ensureArray(nameConfig || DEFAULT_ENTITY_NAME);
|
||||
if (stateObj) {
|
||||
return hass.formatEntityName(stateObj, config);
|
||||
}
|
||||
const textParts = config
|
||||
.filter((item) => item.type === "text")
|
||||
.map((item) => ("text" in item ? item.text : ""));
|
||||
if (textParts.length) {
|
||||
return textParts.join(" ");
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
@@ -45,14 +45,13 @@ export class HuiEntityEditor extends LitElement {
|
||||
this.hass.devices
|
||||
);
|
||||
|
||||
const name = this.hass.formatEntityName(
|
||||
stateObj,
|
||||
useDeviceName ? { type: "device" } : { type: "entity" }
|
||||
);
|
||||
|
||||
const isRTL = computeRTL(this.hass);
|
||||
|
||||
const primary = item.name || name || item.entity;
|
||||
const primary =
|
||||
this.hass.formatEntityName(
|
||||
stateObj,
|
||||
useDeviceName ? { type: "device" } : { type: "entity" }
|
||||
) || item.entity;
|
||||
|
||||
const secondary = this.hass.formatEntityName(
|
||||
stateObj,
|
||||
|
@@ -4,19 +4,19 @@ import { customElement, property } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { DOMAINS_INPUT_ROW } from "../../../common/const";
|
||||
import { stopPropagation } from "../../../common/dom/stop_propagation";
|
||||
import { toggleAttribute } from "../../../common/dom/toggle_attribute";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import "../../../components/entity/state-badge";
|
||||
import "../../../components/ha-relative-time";
|
||||
import type { ActionHandlerEvent } from "../../../data/lovelace/action_handler";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { EntitiesCardEntityConfig } from "../cards/types";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { computeLovelaceEntityName } from "../common/entity/compute-lovelace-entity-name";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
import { hasAction, hasAnyAction } from "../common/has-action";
|
||||
import { createEntityNotFoundWarning } from "./hui-warning";
|
||||
import { stopPropagation } from "../../../common/dom/stop_propagation";
|
||||
|
||||
@customElement("hui-generic-entity-row")
|
||||
export class HuiGenericEntityRow extends LitElement {
|
||||
@@ -59,7 +59,11 @@ export class HuiGenericEntityRow extends LitElement {
|
||||
const pointer = hasAnyAction(this.config);
|
||||
|
||||
const hasSecondary = this.secondaryText || this.config.secondary_info;
|
||||
const name = this.config.name ?? computeStateName(stateObj);
|
||||
const name = computeLovelaceEntityName(
|
||||
this.hass,
|
||||
stateObj,
|
||||
this.config.name
|
||||
);
|
||||
|
||||
return html`
|
||||
<div
|
||||
@@ -87,7 +91,7 @@ export class HuiGenericEntityRow extends LitElement {
|
||||
class="info ${classMap({ "text-content": !hasSecondary })}"
|
||||
.title=${name}
|
||||
>
|
||||
${this.config.name || computeStateName(stateObj)}
|
||||
${name}
|
||||
${hasSecondary
|
||||
? html`
|
||||
<div class="secondary">
|
||||
|
@@ -5,6 +5,7 @@ import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { assert, assign, boolean, object, optional, string } from "superstruct";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { DEFAULT_ENTITY_NAME } from "../../../../common/entity/compute_entity_name_display";
|
||||
import "../../../../components/ha-form/ha-form";
|
||||
import type {
|
||||
HaFormSchema,
|
||||
@@ -16,13 +17,14 @@ import type { ButtonCardConfig } from "../../cards/types";
|
||||
import type { LovelaceCardEditor } from "../../types";
|
||||
import { actionConfigStruct } from "../structs/action-struct";
|
||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||
import { entityNameStruct } from "../structs/entity-name-struct";
|
||||
import { configElementStyle } from "./config-elements-style";
|
||||
|
||||
const cardConfigStruct = assign(
|
||||
baseLovelaceCardConfig,
|
||||
object({
|
||||
entity: optional(string()),
|
||||
name: optional(string()),
|
||||
name: optional(entityNameStruct),
|
||||
show_name: optional(boolean()),
|
||||
icon: optional(string()),
|
||||
show_icon: optional(boolean()),
|
||||
@@ -68,7 +70,13 @@ export class HuiButtonCardEditor
|
||||
(entityId: string | undefined) =>
|
||||
[
|
||||
{ name: "entity", selector: { entity: {} } },
|
||||
{ name: "name", selector: { text: {} } },
|
||||
{
|
||||
name: "name",
|
||||
selector: {
|
||||
entity_name: { default_name: DEFAULT_ENTITY_NAME },
|
||||
},
|
||||
context: { entity: "entity" },
|
||||
},
|
||||
{
|
||||
name: "",
|
||||
type: "grid",
|
||||
|
@@ -6,11 +6,15 @@ import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { computeDomain } from "../../../../common/entity/compute_domain";
|
||||
import type { LocalizeFunc } from "../../../../common/translations/localize";
|
||||
import "../../../../components/ha-form/ha-form";
|
||||
import type { SchemaUnion } from "../../../../components/ha-form/types";
|
||||
import type {
|
||||
HaFormSchema,
|
||||
SchemaUnion,
|
||||
} from "../../../../components/ha-form/types";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type { EntitiesCardEntityConfig } from "../../cards/types";
|
||||
import type { LovelaceRowEditor } from "../../types";
|
||||
import { entitiesConfigStruct } from "../structs/entities-struct";
|
||||
import { DEFAULT_ENTITY_NAME } from "../../../../common/entity/compute_entity_name_display";
|
||||
|
||||
const SECONDARY_INFO_VALUES = {
|
||||
none: {},
|
||||
@@ -45,11 +49,19 @@ export class HuiGenericEntityRowEditor
|
||||
|
||||
return [
|
||||
{ name: "entity", required: true, selector: { entity: {} } },
|
||||
{
|
||||
name: "name",
|
||||
selector: {
|
||||
entity_name: {
|
||||
default_name: DEFAULT_ENTITY_NAME,
|
||||
},
|
||||
},
|
||||
context: { entity: "entity" },
|
||||
},
|
||||
{
|
||||
type: "grid",
|
||||
name: "",
|
||||
schema: [
|
||||
{ name: "name", selector: { text: {} } },
|
||||
{
|
||||
name: "icon",
|
||||
selector: {
|
||||
@@ -81,7 +93,7 @@ export class HuiGenericEntityRowEditor
|
||||
},
|
||||
},
|
||||
},
|
||||
] as const;
|
||||
] as const satisfies HaFormSchema[];
|
||||
});
|
||||
|
||||
protected render() {
|
||||
|
@@ -11,20 +11,24 @@ import {
|
||||
string,
|
||||
union,
|
||||
} from "superstruct";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import "../../../../components/ha-form/ha-form";
|
||||
import "../hui-sub-element-editor";
|
||||
import type { EditDetailElementEvent, SubElementEditorConfig } from "../types";
|
||||
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||
import type { SchemaUnion } from "../../../../components/ha-form/types";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { DEFAULT_ENTITY_NAME } from "../../../../common/entity/compute_entity_name_display";
|
||||
import "../../../../components/ha-form/ha-form";
|
||||
import type {
|
||||
HaFormSchema,
|
||||
SchemaUnion,
|
||||
} from "../../../../components/ha-form/types";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type { ConfigEntity, GlanceCardConfig } from "../../cards/types";
|
||||
import "../../components/hui-entity-editor";
|
||||
import type { EntityConfig } from "../../entity-rows/types";
|
||||
import type { LovelaceCardEditor } from "../../types";
|
||||
import "../hui-sub-element-editor";
|
||||
import { processEditorEntities } from "../process-editor-entities";
|
||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||
import { entitiesConfigStruct } from "../structs/entities-struct";
|
||||
import type { EntityConfig } from "../../entity-rows/types";
|
||||
import type { EditDetailElementEvent, SubElementEditorConfig } from "../types";
|
||||
|
||||
const cardConfigStruct = assign(
|
||||
baseLovelaceCardConfig,
|
||||
@@ -42,11 +46,15 @@ const cardConfigStruct = assign(
|
||||
|
||||
const SUB_SCHEMA = [
|
||||
{ name: "entity", selector: { entity: {} }, required: true },
|
||||
{
|
||||
name: "name",
|
||||
selector: { entity_name: { default_name: DEFAULT_ENTITY_NAME } },
|
||||
context: { entity: "entity" },
|
||||
},
|
||||
{
|
||||
type: "grid",
|
||||
name: "",
|
||||
schema: [
|
||||
{ name: "name", selector: { text: {} } },
|
||||
{
|
||||
name: "icon",
|
||||
selector: {
|
||||
@@ -81,7 +89,7 @@ const SUB_SCHEMA = [
|
||||
},
|
||||
})),
|
||||
},
|
||||
] as const;
|
||||
] as const satisfies HaFormSchema[];
|
||||
|
||||
const SCHEMA = [
|
||||
{ name: "title", selector: { text: {} } },
|
||||
@@ -104,7 +112,7 @@ const SCHEMA = [
|
||||
],
|
||||
},
|
||||
{ name: "state_color", selector: { boolean: {} } },
|
||||
] as const;
|
||||
] as const satisfies HaFormSchema[];
|
||||
|
||||
@customElement("hui-glance-card-editor")
|
||||
export class HuiGlanceCardEditor
|
||||
|
@@ -1,14 +1,15 @@
|
||||
import { union, object, string, optional, boolean, enums } from "superstruct";
|
||||
import { boolean, enums, object, optional, string, union } from "superstruct";
|
||||
import { TIMESTAMP_RENDERING_FORMATS } from "../../components/types";
|
||||
import {
|
||||
actionConfigStruct,
|
||||
actionConfigStructConfirmation,
|
||||
} from "./action-struct";
|
||||
import { entityNameStruct } from "./entity-name-struct";
|
||||
|
||||
export const entitiesConfigStruct = union([
|
||||
object({
|
||||
entity: string(),
|
||||
name: optional(string()),
|
||||
name: optional(entityNameStruct),
|
||||
icon: optional(string()),
|
||||
image: optional(string()),
|
||||
secondary_info: optional(string()),
|
||||
|
Reference in New Issue
Block a user