Add 'focus' option to geo_location_sources for map card (#22535)

* Add 'focus' option to geo_location_sources for map card

* visual editor compatibility
This commit is contained in:
karwosts 2024-10-29 06:32:30 -07:00 committed by GitHub
parent 48dfa1163b
commit 42f2341e06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 53 additions and 14 deletions

View File

@ -50,6 +50,11 @@ interface MapEntityConfig extends EntityConfig {
focus?: boolean; focus?: boolean;
} }
interface GeoEntity {
entity_id: string;
focus: boolean;
}
@customElement("hui-map-card") @customElement("hui-map-card")
class HuiMapCard extends LitElement implements LovelaceCard { class HuiMapCard extends LitElement implements LovelaceCard {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@ -332,23 +337,32 @@ class HuiMapCard extends LitElement implements LovelaceCard {
return color; return color;
} }
private _getSourceEntities(states?: HassEntities): string[] { private _getSourceEntities(states?: HassEntities): GeoEntity[] {
if (!states || !this._config?.geo_location_sources) { if (!states || !this._config?.geo_location_sources) {
return []; return [];
} }
const geoEntities: string[] = []; const sourceObjs = this._config.geo_location_sources.map((source) =>
typeof source === "string" ? { source } : source
);
const geoEntities: GeoEntity[] = [];
// Calculate visible geo location sources // Calculate visible geo location sources
const includesAll = this._config.geo_location_sources.includes("all"); const allSource = sourceObjs.find((s) => s.source === "all");
for (const stateObj of Object.values(states)) { for (const stateObj of Object.values(states)) {
const sourceObj = sourceObjs.find(
(s) => s.source === stateObj.attributes.source
);
if ( if (
computeDomain(stateObj.entity_id) === "geo_location" && computeDomain(stateObj.entity_id) === "geo_location" &&
(includesAll || (allSource || sourceObj)
this._config.geo_location_sources.includes(
stateObj.attributes.source
))
) { ) {
geoEntities.push(stateObj.entity_id); geoEntities.push({
entity_id: stateObj.entity_id,
focus: sourceObj
? (sourceObj.focus ?? true)
: (allSource?.focus ?? true),
});
} }
} }
return geoEntities; return geoEntities;
@ -364,8 +378,9 @@ class HuiMapCard extends LitElement implements LovelaceCard {
name: entityConf.name, name: entityConf.name,
})), })),
...this._getSourceEntities(this.hass?.states).map((entity) => ({ ...this._getSourceEntities(this.hass?.states).map((entity) => ({
entity_id: entity, entity_id: entity.entity_id,
color: this._getColor(entity), focus: entity.focus,
color: this._getColor(entity.entity_id),
})), })),
]; ];
} }

View File

@ -298,6 +298,11 @@ export interface LogbookCardConfig extends LovelaceCardConfig {
theme?: string; theme?: string;
} }
interface GeoLocationSourceConfig {
source: string;
focus?: boolean;
}
export interface MapCardConfig extends LovelaceCardConfig { export interface MapCardConfig extends LovelaceCardConfig {
type: "map"; type: "map";
title?: string; title?: string;
@ -307,7 +312,7 @@ export interface MapCardConfig extends LovelaceCardConfig {
default_zoom?: number; default_zoom?: number;
entities?: Array<EntityConfig | string>; entities?: Array<EntityConfig | string>;
hours_to_show?: number; hours_to_show?: number;
geo_location_sources?: string[]; geo_location_sources?: Array<GeoLocationSourceConfig | string>;
dark_mode?: boolean; dark_mode?: boolean;
theme_mode?: ThemeMode; theme_mode?: ThemeMode;
} }

View File

@ -44,6 +44,14 @@ export const mapEntitiesConfigStruct = union([
string(), string(),
]); ]);
const geoSourcesConfigStruct = union([
object({
source: string(),
focus: optional(boolean()),
}),
string(),
]);
const cardConfigStruct = assign( const cardConfigStruct = assign(
baseLovelaceCardConfig, baseLovelaceCardConfig,
object({ object({
@ -53,7 +61,7 @@ const cardConfigStruct = assign(
dark_mode: optional(boolean()), dark_mode: optional(boolean()),
entities: array(mapEntitiesConfigStruct), entities: array(mapEntitiesConfigStruct),
hours_to_show: optional(number()), hours_to_show: optional(number()),
geo_location_sources: optional(array(string())), geo_location_sources: optional(array(geoSourcesConfigStruct)),
auto_fit: optional(boolean()), auto_fit: optional(boolean()),
theme_mode: optional(string()), theme_mode: optional(string()),
}) })
@ -139,8 +147,12 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
: []; : [];
} }
private _geoSourcesStrings = memoizeOne((sources): string[] | undefined =>
sources?.map((s) => (typeof s === "string" ? s : s.source))
);
get _geo_location_sources(): string[] { get _geo_location_sources(): string[] {
return this._config!.geo_location_sources || []; return this._geoSourcesStrings(this._config!.geo_location_sources) || [];
} }
protected render() { protected render() {
@ -228,9 +240,16 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
this._config = { ...this._config }; this._config = { ...this._config };
delete this._config.geo_location_sources; delete this._config.geo_location_sources;
} else { } else {
const newSources = value.map(
(newSource) =>
this._config!.geo_location_sources?.find(
(oldSource) =>
typeof oldSource === "object" && oldSource.source === newSource
) || newSource
);
this._config = { this._config = {
...this._config, ...this._config,
geo_location_sources: value, geo_location_sources: newSources,
}; };
} }
fireEvent(this, "config-changed", { config: this._config }); fireEvent(this, "config-changed", { config: this._config });