From 15f33e1f191b64e1a55b95b3e7f02fab545021f3 Mon Sep 17 00:00:00 2001 From: Petar Petrov Date: Fri, 31 Jan 2025 16:42:46 +0200 Subject: [PATCH] Echarts: show all series in tooltip (#23989) * Echarts: show all series in tooltip * fix typo * remove duplicate tooltip entries in statistics chart * take last valid point instead of first --- .../chart/state-history-chart-line.ts | 103 +++++++++++------- src/components/chart/statistics-chart.ts | 12 +- 2 files changed, 74 insertions(+), 41 deletions(-) diff --git a/src/components/chart/state-history-chart-line.ts b/src/components/chart/state-history-chart-line.ts index 3dedd3cacf..f55c205000 100644 --- a/src/components/chart/state-history-chart-line.ts +++ b/src/components/chart/state-history-chart-line.ts @@ -88,45 +88,74 @@ export class StateHistoryChartLine extends LitElement { `; } - private _renderTooltip(params) { - return params - .map((param, index: number) => { - let value = `${formatNumber( - param.value[1] as number, - this.hass.locale, - getNumberFormatOptions( - undefined, - this.hass.entities[this._entityIds[param.seriesIndex]] - ) - )} ${this.unit}`; - const dataIndex = this._datasetToDataIndex[param.seriesIndex]; - const data = this.data[dataIndex]; - if (data.statistics && data.statistics.length > 0) { - value += "
     "; - const source = - data.states.length === 0 || - param.value[0] < data.states[0].last_changed - ? `${this.hass.localize( - "ui.components.history_charts.source_stats" - )}` - : `${this.hass.localize( - "ui.components.history_charts.source_history" - )}`; - value += source; + private _renderTooltip(params: any) { + const time = params[0].axisValue; + const title = + formatDateTimeWithSeconds( + new Date(time), + this.hass.locale, + this.hass.config + ) + "
"; + const datapoints: Record[] = []; + this._chartData.forEach((dataset, index) => { + const param = params.find( + (p: Record) => p.seriesIndex === index + ); + if (param) { + datapoints.push(param); + return; + } + // If the datapoint is not found, we need to find the last datapoint before the current time + let lastData; + const data = dataset.data || []; + for (let i = data.length - 1; i >= 0; i--) { + const point = data[i]; + if (point && point[0] <= time && point[1]) { + lastData = point; + break; } + } + if (!lastData) return; + datapoints.push({ + seriesName: dataset.name, + seriesIndex: index, + value: lastData, + // HTML copied from echarts. May change based on options + marker: ``, + }); + }); + return ( + title + + datapoints + .map((param) => { + let value = `${formatNumber( + param.value[1] as number, + this.hass.locale, + getNumberFormatOptions( + undefined, + this.hass.entities[this._entityIds[param.seriesIndex]] + ) + )} ${this.unit}`; + const dataIndex = this._datasetToDataIndex[param.seriesIndex]; + const data = this.data[dataIndex]; + if (data.statistics && data.statistics.length > 0) { + value += "
     "; + const source = + data.states.length === 0 || + param.value[0] < data.states[0].last_changed + ? `${this.hass.localize( + "ui.components.history_charts.source_stats" + )}` + : `${this.hass.localize( + "ui.components.history_charts.source_history" + )}`; + value += source; + } - const time = - index === 0 - ? formatDateTimeWithSeconds( - new Date(param.value[0]), - this.hass.locale, - this.hass.config - ) + "
" - : ""; - return `${time}${param.marker} ${param.seriesName}: ${value} - `; - }) - .join("
"); + return `${param.marker} ${param.seriesName}: ${value}`; + }) + .join("
") + ); } public willUpdate(changedProps: PropertyValues) { diff --git a/src/components/chart/statistics-chart.ts b/src/components/chart/statistics-chart.ts index 6d88f3a5d6..f35d1cdcbb 100644 --- a/src/components/chart/statistics-chart.ts +++ b/src/components/chart/statistics-chart.ts @@ -185,9 +185,12 @@ export class StatisticsChart extends LitElement { this.requestUpdate("_hiddenStats"); } - private _renderTooltip = (params: any) => - params + private _renderTooltip = (params: any) => { + const rendered: Record = {}; + return params .map((param, index: number) => { + if (rendered[param.seriesName]) return ""; + rendered[param.seriesName] = true; const value = `${formatNumber( // max series can have 3 values, as the second value is the max-min to form a band (param.value[2] ?? param.value[1]) as number, @@ -206,10 +209,11 @@ export class StatisticsChart extends LitElement { this.hass.config ) + "
" : ""; - return `${time}${param.marker} ${param.seriesName}: ${value} - `; + return `${time}${param.marker} ${param.seriesName}: ${value}`; }) + .filter(Boolean) .join("
"); + }; private _createOptions() { const splitLineStyle = this.hass.themes?.darkMode ? { opacity: 0.15 } : {};