Add more-info click to energy table and detail device graph (#21737)

* feat: more info energy dashboard

* add more info to device details usage

* Add some more-info click to energy

---------

Co-authored-by: Muka Schultze <samuelschultze@gmail.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
karwosts 2024-08-27 23:43:53 -07:00 committed by GitHub
parent 395586ddeb
commit cf55824899
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 98 additions and 25 deletions

View File

@ -0,0 +1,6 @@
import type { ChartEvent } from "chart.js";
export const clickIsTouch = (event: ChartEvent): boolean =>
!(event.native instanceof MouseEvent) ||
(event.native instanceof PointerEvent &&
event.native.pointerType !== "mouse");

View File

@ -16,6 +16,7 @@ import {
HaChartBase,
MIN_TIME_BETWEEN_UPDATES,
} from "./ha-chart-base";
import { clickIsTouch } from "./click_is_touch";
const safeParseFloat = (value) => {
const parsed = parseFloat(value);
@ -220,12 +221,7 @@ export class StateHistoryChartLine extends LitElement {
// @ts-expect-error
locale: numberFormatToLocale(this.hass.locale),
onClick: (e: any) => {
if (
!this.clickForMoreInfo ||
!(e.native instanceof MouseEvent) ||
(e.native instanceof PointerEvent &&
e.native.pointerType !== "mouse")
) {
if (!this.clickForMoreInfo || clickIsTouch(e)) {
return;
}

View File

@ -16,6 +16,7 @@ import {
} from "./ha-chart-base";
import type { TimeLineData } from "./timeline-chart/const";
import { computeTimelineColor } from "./timeline-chart/timeline-color";
import { clickIsTouch } from "./click_is_touch";
@customElement("state-history-chart-timeline")
export class StateHistoryChartTimeline extends LitElement {
@ -224,11 +225,7 @@ export class StateHistoryChartTimeline extends LitElement {
// @ts-expect-error
locale: numberFormatToLocale(this.hass.locale),
onClick: (e: any) => {
if (
!this.clickForMoreInfo ||
!(e.native instanceof MouseEvent) ||
(e.native instanceof PointerEvent && e.native.pointerType !== "mouse")
) {
if (!this.clickForMoreInfo || clickIsTouch(e)) {
return;
}

View File

@ -39,6 +39,7 @@ import type {
ChartDatasetExtra,
HaChartBase,
} from "./ha-chart-base";
import { clickIsTouch } from "./click_is_touch";
export const supportedStatTypeMap: Record<StatisticType, StatisticType> = {
mean: "mean",
@ -278,11 +279,7 @@ export class StatisticsChart extends LitElement {
// @ts-expect-error
locale: numberFormatToLocale(this.hass.locale),
onClick: (e: any) => {
if (
!this.clickForMoreInfo ||
!(e.native instanceof MouseEvent) ||
(e.native instanceof PointerEvent && e.native.pointerType !== "mouse")
) {
if (!this.clickForMoreInfo || clickIsTouch(e)) {
return;
}

View File

@ -30,6 +30,7 @@ import {
getStatisticLabel,
Statistics,
StatisticsMetaData,
isExternalStatistic,
} from "../../../../data/recorder";
import { FrontendLocaleData } from "../../../../data/translation";
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
@ -38,7 +39,9 @@ import { LovelaceCard } from "../../types";
import { EnergyDevicesDetailGraphCardConfig } from "../types";
import { hasConfigChanged } from "../../common/has-changed";
import { getCommonOptions } from "./common/energy-chart-options";
import { fireEvent } from "../../../../common/dom/fire_event";
import { storage } from "../../../../common/decorators/storage";
import { clickIsTouch } from "../../../../components/chart/click_is_touch";
const UNIT = "kWh";
@ -197,6 +200,20 @@ export class HuiEnergyDevicesDetailGraphCard
},
},
},
onClick: (event, elements, chart) => {
if (clickIsTouch(event)) return;
const index = elements[0]?.datasetIndex ?? -1;
if (index < 0) return;
const statisticId =
this._data?.prefs.device_consumption[index]?.stat_consumption;
if (!statisticId || isExternalStatistic(statisticId)) return;
fireEvent(this, "hass-more-info", { entityId: statisticId });
chart?.canvas?.dispatchEvent(new Event("mouseout")); // to hide tooltip
},
};
return options;
}

View File

@ -31,6 +31,7 @@ import { EnergyData, getEnergyDataCollection } from "../../../../data/energy";
import {
calculateStatisticSumGrowth,
getStatisticLabel,
isExternalStatistic,
} from "../../../../data/recorder";
import { FrontendLocaleData } from "../../../../data/translation";
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
@ -38,6 +39,7 @@ import { HomeAssistant } from "../../../../types";
import { LovelaceCard } from "../../types";
import { EnergyDevicesGraphCardConfig } from "../types";
import { hasConfigChanged } from "../../common/has-changed";
import { clickIsTouch } from "../../../../components/chart/click_is_touch";
@customElement("hui-energy-devices-graph-card")
export class HuiEnergyDevicesGraphCard
@ -158,15 +160,18 @@ export class HuiEnergyDevicesGraphCard
// @ts-expect-error
locale: numberFormatToLocale(this.hass.locale),
onClick: (e: any) => {
if (clickIsTouch(e)) return;
const chart = e.chart;
const canvasPosition = getRelativePosition(e, chart);
const index = Math.abs(
chart.scales.y.getValueForPixel(canvasPosition.y)
);
// @ts-ignore
const statisticId = this._chartData?.datasets[0]?.data[index]?.y;
if (!statisticId || isExternalStatistic(statisticId)) return;
fireEvent(this, "hass-more-info", {
// @ts-ignore
entityId: this._chartData?.datasets[0]?.data[index]?.y,
entityId: statisticId,
});
chart.canvas.dispatchEvent(new Event("mouseout")); // to hide tooltip
},

View File

@ -11,6 +11,7 @@ import {
PropertyValues,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { styleMap } from "lit/directives/style-map";
import { formatNumber } from "../../../../common/number/format_number";
import { getEnergyColor } from "./common/color";
@ -25,12 +26,14 @@ import {
import {
calculateStatisticSumGrowth,
getStatisticLabel,
isExternalStatistic,
} from "../../../../data/recorder";
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
import { HomeAssistant } from "../../../../types";
import { LovelaceCard } from "../../types";
import { EnergySourcesTableCardConfig } from "../types";
import { hasConfigChanged } from "../../common/has-changed";
import { fireEvent } from "../../../../common/dom/fire_event";
const colorPropertyMap = {
grid_return: "--energy-grid-return-color",
@ -225,7 +228,13 @@ export class HuiEnergySourcesTableCard
0;
totalSolarCompare += compareEnergy;
return html`<tr class="mdc-data-table__row">
return html`<tr
class="mdc-data-table__row ${classMap({
clickable: !isExternalStatistic(source.stat_energy_from),
})}"
@click=${this._handleMoreInfo}
.entity=${source.stat_energy_from}
>
<td class="mdc-data-table__cell cell-bullet">
<div
class="bullet"
@ -330,7 +339,13 @@ export class HuiEnergySourcesTableCard
0;
totalBatteryCompare += energyFromCompare - energyToCompare;
return html`<tr class="mdc-data-table__row">
return html`<tr
class="mdc-data-table__row ${classMap({
clickable: !isExternalStatistic(source.stat_energy_from),
})}"
@click=${this._handleMoreInfo}
.entity=${source.stat_energy_from}
>
<td class="mdc-data-table__cell cell-bullet">
<div
class="bullet"
@ -381,7 +396,13 @@ export class HuiEnergySourcesTableCard
? html`<td class="mdc-data-table__cell"></td>`
: ""}
</tr>
<tr class="mdc-data-table__row">
<tr
class="mdc-data-table__row ${classMap({
clickable: !isExternalStatistic(source.stat_energy_to),
})}"
@click=${this._handleMoreInfo}
.entity=${source.stat_energy_to}
>
<td class="mdc-data-table__cell cell-bullet">
<div
class="bullet"
@ -508,7 +529,13 @@ export class HuiEnergySourcesTableCard
totalGridCostCompare += costCompare;
}
return html`<tr class="mdc-data-table__row">
return html`<tr
class="mdc-data-table__row ${classMap({
clickable: !isExternalStatistic(flow.stat_energy_from),
})}"
@click=${this._handleMoreInfo}
.entity=${flow.stat_energy_from}
>
<td class="mdc-data-table__cell cell-bullet">
<div
class="bullet"
@ -619,7 +646,13 @@ export class HuiEnergySourcesTableCard
totalGridCostCompare += costCompare;
}
return html`<tr class="mdc-data-table__row">
return html`<tr
class="mdc-data-table__row ${classMap({
clickable: !isExternalStatistic(flow.stat_energy_to),
})}"
@click=${this._handleMoreInfo}
.entity=${flow.stat_energy_to}
>
<td class="mdc-data-table__cell cell-bullet">
<div
class="bullet"
@ -784,7 +817,13 @@ export class HuiEnergySourcesTableCard
totalGasCostCompare += costCompare;
}
return html`<tr class="mdc-data-table__row">
return html`<tr
class="mdc-data-table__row ${classMap({
clickable: !isExternalStatistic(source.stat_energy_from),
})}"
@click=${this._handleMoreInfo}
.entity=${source.stat_energy_from}
>
<td class="mdc-data-table__cell cell-bullet">
<div
class="bullet"
@ -942,7 +981,13 @@ export class HuiEnergySourcesTableCard
totalWaterCostCompare += costCompare;
}
return html`<tr class="mdc-data-table__row">
return html`<tr
class="mdc-data-table__row ${classMap({
clickable: !isExternalStatistic(source.stat_energy_from),
})}"
@click=${this._handleMoreInfo}
.entity=${source.stat_energy_from}
>
<td class="mdc-data-table__cell cell-bullet">
<div
class="bullet"
@ -1111,6 +1156,13 @@ export class HuiEnergySourcesTableCard
</ha-card>`;
}
private _handleMoreInfo(ev): void {
const entityId = ev.currentTarget?.entity;
if (entityId && !isExternalStatistic(entityId)) {
fireEvent(this, "hass-more-info", { entityId });
}
}
static get styles(): CSSResultGroup {
return css`
${unsafeCSS(dataTableStyles)}
@ -1127,6 +1179,9 @@ export class HuiEnergySourcesTableCard
.mdc-data-table__row:not(.mdc-data-table__row--selected):hover {
background-color: rgba(var(--rgb-primary-text-color), 0.04);
}
.clickable {
cursor: pointer;
}
.total {
--mdc-typography-body2-font-weight: 500;
}