Make map card trails clickable, provide time context. (#14515)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
karwosts 2022-12-14 09:39:38 -08:00 committed by GitHub
parent ebcbfda92d
commit 77b8152c55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 58 additions and 20 deletions

View File

@ -23,8 +23,12 @@ import "./ha-entity-marker";
const getEntityId = (entity: string | HaMapEntity): string => const getEntityId = (entity: string | HaMapEntity): string =>
typeof entity === "string" ? entity : entity.entity_id; typeof entity === "string" ? entity : entity.entity_id;
export interface HaMapPathPoint {
point: LatLngTuple;
tooltip: string;
}
export interface HaMapPaths { export interface HaMapPaths {
points: LatLngTuple[]; points: HaMapPathPoint[];
color?: string; color?: string;
gradualOpacity?: number; gradualOpacity?: number;
} }
@ -247,19 +251,21 @@ export class HaMap extends ReactiveElement {
// DRAW point // DRAW point
this._mapPaths.push( this._mapPaths.push(
Leaflet!.circleMarker(path.points[pointIndex], { Leaflet!
radius: 3, .circleMarker(path.points[pointIndex].point, {
color: path.color || darkPrimaryColor, radius: 3,
opacity, color: path.color || darkPrimaryColor,
fillOpacity: opacity, opacity,
interactive: false, fillOpacity: opacity,
}) interactive: true,
})
.bindTooltip(path.points[pointIndex].tooltip, { direction: "top" })
); );
// DRAW line between this and next point // DRAW line between this and next point
this._mapPaths.push( this._mapPaths.push(
Leaflet!.polyline( Leaflet!.polyline(
[path.points[pointIndex], path.points[pointIndex + 1]], [path.points[pointIndex].point, path.points[pointIndex + 1].point],
{ {
color: path.color || darkPrimaryColor, color: path.color || darkPrimaryColor,
opacity, opacity,
@ -275,13 +281,15 @@ export class HaMap extends ReactiveElement {
: undefined; : undefined;
// DRAW end path point // DRAW end path point
this._mapPaths.push( this._mapPaths.push(
Leaflet!.circleMarker(path.points[pointIndex], { Leaflet!
radius: 3, .circleMarker(path.points[pointIndex].point, {
color: path.color || darkPrimaryColor, radius: 3,
opacity, color: path.color || darkPrimaryColor,
fillOpacity: opacity, opacity,
interactive: false, fillOpacity: opacity,
}) interactive: true,
})
.bindTooltip(path.points[pointIndex].tooltip, { direction: "top" })
); );
} }
this._mapPaths.forEach((marker) => map.addLayer(marker)); this._mapPaths.forEach((marker) => map.addLayer(marker));
@ -491,6 +499,14 @@ export class HaMap extends ReactiveElement {
.leaflet-bottom { .leaflet-bottom {
z-index: 1 !important; z-index: 1 !important;
} }
.leaflet-tooltip {
padding: 8px;
font-size: 90%;
background: rgba(80, 80, 80, 0.9) !important;
color: white !important;
border-radius: 4px;
box-shadow: none !important;
}
`; `;
} }
} }

View File

@ -11,6 +11,7 @@ import {
import { customElement, property, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import { mdiImageFilterCenterFocus } from "@mdi/js"; import { mdiImageFilterCenterFocus } from "@mdi/js";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { isToday } from "date-fns";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import parseAspectRatio from "../../../common/util/parse-aspect-ratio"; import parseAspectRatio from "../../../common/util/parse-aspect-ratio";
import "../../../components/ha-card"; import "../../../components/ha-card";
@ -23,8 +24,17 @@ import { EntityConfig } from "../entity-rows/types";
import { LovelaceCard } from "../types"; import { LovelaceCard } from "../types";
import { MapCardConfig } from "./types"; import { MapCardConfig } from "./types";
import "../../../components/map/ha-map"; import "../../../components/map/ha-map";
import type { HaMap, HaMapPaths } from "../../../components/map/ha-map"; import type {
HaMap,
HaMapPaths,
HaMapPathPoint,
} from "../../../components/map/ha-map";
import { getColorByIndex } from "../../../common/color/colors"; import { getColorByIndex } from "../../../common/color/colors";
import { formatDateTime } from "../../../common/datetime/format_date_time";
import {
formatTime,
formatTimeWeekday,
} from "../../../common/datetime/format_time";
const MINUTE = 60000; const MINUTE = 60000;
@ -274,16 +284,28 @@ class HuiMapCard extends LitElement implements LovelaceCard {
} }
// filter location data from states and remove all invalid locations // filter location data from states and remove all invalid locations
const points = entityStates.reduce( const points = entityStates.reduce(
(accumulator: LatLngTuple[], entityState) => { (accumulator: HaMapPathPoint[], entityState) => {
const latitude = entityState.attributes.latitude; const latitude = entityState.attributes.latitude;
const longitude = entityState.attributes.longitude; const longitude = entityState.attributes.longitude;
if (latitude && longitude) { if (latitude && longitude) {
accumulator.push([latitude, longitude] as LatLngTuple); const p = {} as HaMapPathPoint;
p.point = [latitude, longitude] as LatLngTuple;
const t = new Date(entityState.last_updated);
if (config.hours_to_show! > 144) {
// if showing > 6 days in the history trail, show the full
// date and time
p.tooltip = formatDateTime(t, this.hass.locale);
} else if (isToday(t)) {
p.tooltip = formatTime(t, this.hass.locale);
} else {
p.tooltip = formatTimeWeekday(t, this.hass.locale);
}
accumulator.push(p);
} }
return accumulator; return accumulator;
}, },
[] []
) as LatLngTuple[]; ) as HaMapPathPoint[];
paths.push({ paths.push({
points, points,