Improve rendering person card (#10419)
This commit is contained in:
parent
09ef72647e
commit
4a7a81ffdb
@ -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";
|
||||
|
||||
@ -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"
|
||||
></div>`;
|
||||
}
|
||||
const initials = computeInitials(this.person.name);
|
||||
const initials = computeUserInitials(this.person.name);
|
||||
return html`<div
|
||||
class="initials ${classMap({ long: initials!.length > 2 })}"
|
||||
>
|
||||
|
||||
@ -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"
|
||||
></div>`;
|
||||
}
|
||||
const initials = computeInitials(this.user.name);
|
||||
const initials = computeUserInitials(this.user.name);
|
||||
return html`<div
|
||||
class="initials ${classMap({ long: initials!.length > 2 })}"
|
||||
>
|
||||
|
||||
@ -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("")
|
||||
);
|
||||
};
|
||||
|
||||
@ -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 {
|
||||
</div>
|
||||
`;
|
||||
} else if (this._config.show_name) {
|
||||
footer = html`<div class="footer">${name}</div>`;
|
||||
footer = html`<div class="footer single">${name}</div>`;
|
||||
} else if (this._config.show_state) {
|
||||
footer = html`<div class="footer state">${entityState}</div>`;
|
||||
footer = html`<div class="footer single">${entityState}</div>`;
|
||||
}
|
||||
|
||||
return html`
|
||||
@ -163,9 +161,6 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
|
||||
? "0"
|
||||
: undefined
|
||||
)}
|
||||
class=${classMap({
|
||||
clickable: !UNAVAILABLE_STATES.includes(stateObj.state),
|
||||
})}
|
||||
></hui-image>
|
||||
${footer}
|
||||
</ha-card>
|
||||
@ -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;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user