Add new config options for map entity markers (#17938)

This commit is contained in:
karwosts 2023-09-25 08:26:53 -07:00 committed by GitHub
parent 6b33b4e656
commit 579050bfc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 39 deletions

View File

@ -15,7 +15,7 @@ class HaEntityMarker extends LitElement {
protected render() {
return html`
<div
class="marker"
class="marker ${this.entityPicture ? "picture" : ""}"
style=${styleMap({ "border-color": this.entityColor })}
@click=${this._badgeTap}
>
@ -45,7 +45,6 @@ class HaEntityMarker extends LitElement {
justify-content: center;
align-items: center;
box-sizing: border-box;
overflow: hidden;
width: 48px;
height: 48px;
font-size: var(--ha-marker-font-size, 1.5em);
@ -54,6 +53,9 @@ class HaEntityMarker extends LitElement {
color: var(--primary-text-color);
background-color: var(--card-background-color);
}
.marker.picture {
overflow: hidden;
}
.entity-picture {
background-size: cover;
height: 100%;

View File

@ -37,6 +37,9 @@ export interface HaMapPaths {
export interface HaMapEntity {
entity_id: string;
color: string;
label_mode?: "name" | "state";
name?: string;
focus?: boolean;
}
@customElement("ha-map")
@ -71,6 +74,8 @@ export class HaMap extends ReactiveElement {
private _mapItems: Array<Marker | Circle> = [];
private _mapFocusItems: Array<Marker | Circle> = [];
private _mapZones: Array<Marker | Circle> = [];
private _mapPaths: Array<Polyline | CircleMarker> = [];
@ -168,7 +173,7 @@ export class HaMap extends ReactiveElement {
return;
}
if (!this._mapItems.length && !this.layers?.length) {
if (!this._mapFocusItems.length && !this.layers?.length) {
this.leafletMap.setView(
new this.Leaflet.LatLng(
this.hass.config.latitude,
@ -180,7 +185,9 @@ export class HaMap extends ReactiveElement {
}
let bounds = this.Leaflet.latLngBounds(
this._mapItems ? this._mapItems.map((item) => item.getLatLng()) : []
this._mapFocusItems
? this._mapFocusItems.map((item) => item.getLatLng())
: []
);
if (this.fitZones) {
@ -324,6 +331,7 @@ export class HaMap extends ReactiveElement {
if (this._mapItems.length) {
this._mapItems.forEach((marker) => marker.remove());
this._mapItems = [];
this._mapFocusItems = [];
}
if (this._mapZones.length) {
@ -353,7 +361,8 @@ export class HaMap extends ReactiveElement {
if (!stateObj) {
continue;
}
const title = computeStateName(stateObj);
const customTitle = typeof entity !== "string" ? entity.name : undefined;
const title = customTitle ?? computeStateName(stateObj);
const {
latitude,
longitude,
@ -413,17 +422,20 @@ export class HaMap extends ReactiveElement {
// DRAW ENTITY
// create icon
const entityName = title
.split(" ")
.map((part) => part[0])
.join("")
.substr(0, 3);
const entityName =
typeof entity !== "string" && entity.label_mode === "state"
? this.hass.formatEntityState(stateObj)
: customTitle ??
title
.split(" ")
.map((part) => part[0])
.join("")
.substr(0, 3);
// create marker with the icon
this._mapItems.push(
Leaflet.marker([latitude, longitude], {
icon: Leaflet.divIcon({
html: `
const marker = Leaflet.marker([latitude, longitude], {
icon: Leaflet.divIcon({
html: `
<ha-entity-marker
entity-id="${getEntityId(entity)}"
entity-name="${entityName}"
@ -437,12 +449,15 @@ export class HaMap extends ReactiveElement {
}
></ha-entity-marker>
`,
iconSize: [48, 48],
className: "",
}),
title: computeStateName(stateObj),
})
);
iconSize: [48, 48],
className: "",
}),
title: title,
});
this._mapItems.push(marker);
if (typeof entity === "string" || entity.focus !== false) {
this._mapFocusItems.push(marker);
}
// create circle around if entity has accuracy
if (gpsAccuracy) {

View File

@ -48,6 +48,11 @@ import { MapCardConfig } from "./types";
export const DEFAULT_HOURS_TO_SHOW = 0;
export const DEFAULT_ZOOM = 14;
interface MapEntityConfig extends EntityConfig {
label_mode?: "state" | "name";
focus?: boolean;
}
@customElement("hui-map-card")
class HuiMapCard extends LitElement implements LovelaceCard {
@property({ attribute: false }) public hass!: HomeAssistant;
@ -63,7 +68,7 @@ class HuiMapCard extends LitElement implements LovelaceCard {
@query("ha-map")
private _map?: HaMap;
private _configEntities?: string[];
private _configEntities?: MapEntityConfig[];
private _colorDict: Record<string, string> = {};
@ -94,11 +99,9 @@ class HuiMapCard extends LitElement implements LovelaceCard {
}
this._config = config;
this._configEntities = (
config.entities
? processConfigEntities<EntityConfig>(config.entities)
: []
).map((entity) => entity.entity);
this._configEntities = config.entities
? processConfigEntities<MapEntityConfig>(config.entities)
: [];
}
public getCardSize(): number {
@ -238,7 +241,7 @@ class HuiMapCard extends LitElement implements LovelaceCard {
this._stateHistory = combinedHistory;
},
this._config!.hours_to_show! ?? DEFAULT_HOURS_TO_SHOW,
this._configEntities!,
(this._configEntities || []).map((entity) => entity.entity)!,
false,
false,
false
@ -309,16 +312,14 @@ class HuiMapCard extends LitElement implements LovelaceCard {
(
states: HassEntities,
config: MapCardConfig,
configEntities?: string[]
configEntities?: MapEntityConfig[]
) => {
if (!states || !config) {
return undefined;
}
let entities = configEntities || [];
const geoEntities: string[] = [];
if (config.geo_location_sources) {
const geoEntities: string[] = [];
// Calculate visible geo location sources
const includesAll = config.geo_location_sources.includes("all");
for (const stateObj of Object.values(states)) {
@ -330,14 +331,21 @@ class HuiMapCard extends LitElement implements LovelaceCard {
geoEntities.push(stateObj.entity_id);
}
}
entities = [...entities, ...geoEntities];
}
return entities.map((entity) => ({
entity_id: entity,
color: this._getColor(entity),
}));
return [
...(configEntities || []).map((entityConf) => ({
entity_id: entityConf.entity,
color: this._getColor(entityConf.entity),
label_mode: entityConf.label_mode,
focus: entityConf.focus,
name: entityConf.name,
})),
...geoEntities.map((entity) => ({
entity_id: entity,
color: this._getColor(entity),
})),
];
}
);

View File

@ -9,6 +9,7 @@ import {
object,
optional,
string,
union,
} from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event";
import { hasLocation } from "../../../../common/entity/has_location";
@ -25,10 +26,19 @@ import { EntityConfig } from "../../entity-rows/types";
import { LovelaceCardEditor } from "../../types";
import { processEditorEntities } from "../process-editor-entities";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { entitiesConfigStruct } from "../structs/entities-struct";
import { EntitiesEditorEvent } from "../types";
import { configElementStyle } from "./config-elements-style";
export const mapEntitiesConfigStruct = union([
object({
entity: string(),
label_mode: optional(string()),
focus: optional(boolean()),
name: optional(string()),
}),
string(),
]);
const cardConfigStruct = assign(
baseLovelaceCardConfig,
object({
@ -36,7 +46,7 @@ const cardConfigStruct = assign(
aspect_ratio: optional(string()),
default_zoom: optional(number()),
dark_mode: optional(boolean()),
entities: array(entitiesConfigStruct),
entities: array(mapEntitiesConfigStruct),
hours_to_show: optional(number()),
geo_location_sources: optional(array(string())),
auto_fit: optional(boolean()),