Push map strategy logic down into map card (#24303)

This commit is contained in:
karwosts 2025-02-24 06:13:52 -08:00 committed by GitHub
parent fc4996412e
commit 2b1f301db6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 52 additions and 29 deletions

View File

@ -12,6 +12,7 @@ import memoizeOne from "memoize-one";
import { getColorByIndex } from "../../../common/color/colors"; import { getColorByIndex } from "../../../common/color/colors";
import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { deepEqual } from "../../../common/util/deep-equal"; import { deepEqual } from "../../../common/util/deep-equal";
import parseAspectRatio from "../../../common/util/parse-aspect-ratio"; import parseAspectRatio from "../../../common/util/parse-aspect-ratio";
@ -80,14 +81,38 @@ class HuiMapCard extends LitElement implements LovelaceCard {
private _subscribed?: Promise<(() => Promise<void>) | undefined>; private _subscribed?: Promise<(() => Promise<void>) | undefined>;
private _getAllEntities(): string[] {
const hass = this.hass!;
const personSources = new Set<string>();
const locationEntities: string[] = [];
Object.values(hass.states).forEach((entity) => {
if (
!("latitude" in entity.attributes) ||
!("longitude" in entity.attributes)
) {
return;
}
locationEntities.push(entity.entity_id);
if (computeStateDomain(entity) === "person" && entity.attributes.source) {
personSources.add(entity.attributes.source);
}
});
return locationEntities.filter((entity) => !personSources.has(entity));
}
public setConfig(config: MapCardConfig): void { public setConfig(config: MapCardConfig): void {
if (!config) { if (!config) {
throw new Error("Error in card configuration."); throw new Error("Error in card configuration.");
} }
if (!config.entities?.length && !config.geo_location_sources) { if (
!config.show_all &&
!config.entities?.length &&
!config.geo_location_sources
) {
throw new Error( throw new Error(
"Either entities or geo_location_sources must be specified" "Either show_all, entities, or geo_location_sources must be specified"
); );
} }
if (config.entities && !Array.isArray(config.entities)) { if (config.entities && !Array.isArray(config.entities)) {
@ -99,10 +124,17 @@ class HuiMapCard extends LitElement implements LovelaceCard {
) { ) {
throw new Error("Parameter geo_location_sources needs to be an array"); throw new Error("Parameter geo_location_sources needs to be an array");
} }
if (config.show_all && (config.entities || config.geo_location_sources)) {
this._config = config; throw new Error(
this._configEntities = config.entities "Cannot specify show_all and entities or geo_location_sources"
? processConfigEntities<MapEntityConfig>(config.entities) );
}
this._config = { ...config };
if (this.hass && config.show_all) {
this._config.entities = this._getAllEntities();
}
this._configEntities = this._config.entities
? processConfigEntities<MapEntityConfig>(this._config.entities)
: []; : [];
this._mapEntities = this._getMapEntities(); this._mapEntities = this._getMapEntities();
} }
@ -239,6 +271,18 @@ class HuiMapCard extends LitElement implements LovelaceCard {
protected willUpdate(changedProps: PropertyValues): void { protected willUpdate(changedProps: PropertyValues): void {
super.willUpdate(changedProps); super.willUpdate(changedProps);
if (
this._config?.show_all &&
!this._config?.entities &&
this.hass &&
changedProps.has("hass")
) {
this._config.entities = this._getAllEntities();
this._configEntities = processConfigEntities<MapEntityConfig>(
this._config.entities
);
this._mapEntities = this._getMapEntities();
}
if ( if (
changedProps.has("hass") && changedProps.has("hass") &&
this._config?.geo_location_sources && this._config?.geo_location_sources &&

View File

@ -61,7 +61,7 @@ const cardConfigStruct = assign(
aspect_ratio: optional(string()), aspect_ratio: optional(string()),
default_zoom: optional(number()), default_zoom: optional(number()),
dark_mode: optional(boolean()), dark_mode: optional(boolean()),
entities: array(mapEntitiesConfigStruct), entities: optional(array(mapEntitiesConfigStruct)),
hours_to_show: optional(number()), hours_to_show: optional(number()),
geo_location_sources: optional(array(geoSourcesConfigStruct)), geo_location_sources: optional(array(geoSourcesConfigStruct)),
auto_fit: optional(boolean()), auto_fit: optional(boolean()),

View File

@ -1,6 +1,5 @@
import { ReactiveElement } from "lit"; import { ReactiveElement } from "lit";
import { customElement } from "lit/decorators"; import { customElement } from "lit/decorators";
import { computeStateDomain } from "../../../../common/entity/compute_state_domain";
import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view"; import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import type { MapCardConfig } from "../../cards/types"; import type { MapCardConfig } from "../../cards/types";
@ -9,32 +8,12 @@ export interface MapViewStrategyConfig {
type: "map"; type: "map";
} }
const getMapEntities = (hass: HomeAssistant) => {
const personSources = new Set<string>();
const locationEntities: string[] = [];
Object.values(hass.states).forEach((entity) => {
if (
!("latitude" in entity.attributes) ||
!("longitude" in entity.attributes)
) {
return;
}
locationEntities.push(entity.entity_id);
if (computeStateDomain(entity) === "person" && entity.attributes.source) {
personSources.add(entity.attributes.source);
}
});
return locationEntities.filter((entity) => !personSources.has(entity));
};
@customElement("map-view-strategy") @customElement("map-view-strategy")
export class MapViewStrategy extends ReactiveElement { export class MapViewStrategy extends ReactiveElement {
static async generate( static async generate(
_config: MapViewStrategyConfig, _config: MapViewStrategyConfig,
hass: HomeAssistant hass: HomeAssistant
): Promise<LovelaceViewConfig> { ): Promise<LovelaceViewConfig> {
const entities = getMapEntities(hass);
return { return {
type: "panel", type: "panel",
title: hass.localize("panel.map"), title: hass.localize("panel.map"),
@ -43,7 +22,7 @@ export class MapViewStrategy extends ReactiveElement {
{ {
type: "map", type: "map",
auto_fit: true, auto_fit: true,
entities: entities, show_all: true,
} as MapCardConfig, } as MapCardConfig,
], ],
}; };