diff --git a/src/common/empty_image_base64.ts b/src/common/empty_image_base64.ts index 2eb8cb22f..5c63dca0d 100644 --- a/src/common/empty_image_base64.ts +++ b/src/common/empty_image_base64.ts @@ -1,2 +1,3 @@ /** An empty image which can be set as src of an img element. */ -export default "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; +export const emptyImageBase64 = + "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; diff --git a/src/components/user/ha-person-badge.ts b/src/components/user/ha-person-badge.ts index 9074ea7c9..043402599 100644 --- a/src/components/user/ha-person-badge.ts +++ b/src/components/user/ha-person-badge.ts @@ -3,7 +3,7 @@ import { customElement, property } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { styleMap } from "lit/directives/style-map"; import { Person } from "../../data/person"; -import { computeInitials } from "./ha-user-badge"; +import { computeUserInitials } from "../../data/user"; @customElement("ha-person-badge") class PersonBadge extends LitElement { @@ -22,7 +22,7 @@ class PersonBadge extends LitElement { class="picture" >`; } - const initials = computeInitials(this.person.name); + const initials = computeUserInitials(this.person.name); return html`
diff --git a/src/components/user/ha-user-badge.ts b/src/components/user/ha-user-badge.ts index dc1692c35..eb589b467 100644 --- a/src/components/user/ha-user-badge.ts +++ b/src/components/user/ha-user-badge.ts @@ -10,25 +10,9 @@ import { customElement, property, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { styleMap } from "lit/directives/style-map"; import { computeStateDomain } from "../../common/entity/compute_state_domain"; -import { User } from "../../data/user"; +import { computeUserInitials, User } from "../../data/user"; import { CurrentUser, HomeAssistant } from "../../types"; -export const computeInitials = (name: string) => { - if (!name) { - return "?"; - } - return ( - name - .trim() - // Split by space and take first 3 words - .split(" ") - .slice(0, 3) - // Of each word, take first letter - .map((s) => s.substr(0, 1)) - .join("") - ); -}; - @customElement("ha-user-badge") class UserBadge extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -75,7 +59,7 @@ class UserBadge extends LitElement { class="picture" >
`; } - const initials = computeInitials(this.user.name); + const initials = computeUserInitials(this.user.name); return html`
diff --git a/src/data/user.ts b/src/data/user.ts index 5fe1f4f25..7b108b3e7 100644 --- a/src/data/user.ts +++ b/src/data/user.ts @@ -57,3 +57,19 @@ export const deleteUser = async (hass: HomeAssistant, userId: string) => type: "config/auth/delete", user_id: userId, }); + +export const computeUserInitials = (name: string) => { + if (!name) { + return "?"; + } + return ( + name + .trim() + // Split by space and take first 3 words + .split(" ") + .slice(0, 3) + // Of each word, take first letter + .map((s) => s.substr(0, 1)) + .join("") + ); +}; diff --git a/src/panels/lovelace/cards/hui-picture-entity-card.ts b/src/panels/lovelace/cards/hui-picture-entity-card.ts index 2e079a46a..087e5e506 100644 --- a/src/panels/lovelace/cards/hui-picture-entity-card.ts +++ b/src/panels/lovelace/cards/hui-picture-entity-card.ts @@ -7,14 +7,12 @@ import { TemplateResult, } from "lit"; import { customElement, property, state } from "lit/decorators"; -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 { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { computeStateName } from "../../../common/entity/compute_state_name"; import "../../../components/ha-card"; -import { UNAVAILABLE_STATES } from "../../../data/entity"; import { ActionHandlerEvent } from "../../../data/lovelace"; import { HomeAssistant } from "../../../types"; import { actionHandler } from "../common/directives/action-handler-directive"; @@ -135,9 +133,9 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
`; } else if (this._config.show_name) { - footer = html``; + footer = html``; } else if (this._config.show_state) { - footer = html``; + footer = html``; } return html` @@ -163,9 +161,6 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard { ? "0" : undefined )} - class=${classMap({ - clickable: !UNAVAILABLE_STATES.includes(stateObj.state), - })} > ${footer} @@ -182,7 +177,7 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard { box-sizing: border-box; } - hui-image.clickable { + hui-image { cursor: pointer; } @@ -212,8 +207,8 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard { justify-content: space-between; } - .state { - text-align: right; + .single { + text-align: center; } `; } diff --git a/src/panels/lovelace/common/generate-lovelace-config.ts b/src/panels/lovelace/common/generate-lovelace-config.ts index aa61c01a7..0561b1c9d 100644 --- a/src/panels/lovelace/common/generate-lovelace-config.ts +++ b/src/panels/lovelace/common/generate-lovelace-config.ts @@ -16,6 +16,7 @@ import type { EntityRegistryEntry } from "../../../data/entity_registry"; import { domainToName } from "../../../data/integration"; import { LovelaceCardConfig, LovelaceViewConfig } from "../../../data/lovelace"; import { SENSOR_DEVICE_CLASS_BATTERY } from "../../../data/sensor"; +import { computeUserInitials } from "../../../data/user"; import { AlarmPanelCardConfig, EntitiesCardConfig, @@ -232,6 +233,62 @@ export const generateViewConfig = ( let cards: LovelaceCardConfig[] = []; + if ("person" in ungroupedEntitites) { + const personCards: LovelaceCardConfig[] = []; + + if (ungroupedEntitites.person.length === 1) { + cards.push({ + type: "entities", + entities: ungroupedEntitites.person, + }); + } else { + let backgroundColor: string | undefined; + let foregroundColor = ""; + + for (const personEntityId of ungroupedEntitites.person) { + const stateObj = entities[personEntityId]; + + let image = stateObj.attributes.entity_picture; + + if (!image) { + if (backgroundColor === undefined) { + const computedStyle = getComputedStyle(document.body); + backgroundColor = encodeURIComponent( + computedStyle.getPropertyValue("--light-primary-color").trim() + ); + foregroundColor = encodeURIComponent( + ( + computedStyle.getPropertyValue("--text-light-primary-color") || + computedStyle.getPropertyValue("--primary-text-color") + ).trim() + ); + } + const initials = computeUserInitials( + stateObj.attributes.friendly_name || "" + ); + image = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 50' width='50' height='50' style='background-color:${backgroundColor}'%3E%3Cg%3E%3Ctext font-family='roboto' x='50%25' y='50%25' text-anchor='middle' stroke='${foregroundColor}' font-size='1.3em' dy='.3em'%3E${initials}%3C/text%3E%3C/g%3E%3C/svg%3E`; + } + + personCards.push({ + type: "picture-entity", + entity: personEntityId, + aspect_ratio: "1", + show_name: false, + image, + }); + } + + cards.push({ + type: "grid", + square: true, + columns: 3, + cards: personCards, + }); + } + + delete ungroupedEntitites.person; + } + splitted.groups.forEach((groupEntity) => { cards = cards.concat( computeCards( diff --git a/src/panels/lovelace/components/hui-image.ts b/src/panels/lovelace/components/hui-image.ts index d92a04790..23510d29d 100644 --- a/src/panels/lovelace/components/hui-image.ts +++ b/src/panels/lovelace/components/hui-image.ts @@ -192,7 +192,7 @@ export class HuiImage extends LitElement { : undefined, backgroundImage: useRatio && this._loadedImageSrc - ? `url(${this._loadedImageSrc})` + ? `url("${this._loadedImageSrc}")` : undefined, filter: this._loadState === LoadState.Loaded || this.cameraView === "live"