mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-28 11:46:42 +00:00
Fixes for echarts (#23906)
* show negative untracked energy again * fix chart cards height * fix timeline label width * fix statistics chart legend * fix layout of chart cards * tweak timeline chart labels * timeline label tweak * css tweak * fix legend colors in statistics chart * dark mode fix * fix for y axis with a long name * listen for darkMode changes and update charts * legend tweak for darkMode * dark mode tweak * hide insignificant echarts errors for now
This commit is contained in:
parent
e1bda9b57d
commit
cc48ae82d6
@ -7,12 +7,15 @@ import type { EChartsType } from "echarts/core";
|
|||||||
import type { DataZoomComponentOption } from "echarts/components";
|
import type { DataZoomComponentOption } from "echarts/components";
|
||||||
import { ResizeController } from "@lit-labs/observers/resize-controller";
|
import { ResizeController } from "@lit-labs/observers/resize-controller";
|
||||||
import type { XAXisOption, YAXisOption } from "echarts/types/dist/shared";
|
import type { XAXisOption, YAXisOption } from "echarts/types/dist/shared";
|
||||||
|
import { consume } from "@lit-labs/context";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { isMac } from "../../util/is_mac";
|
import { isMac } from "../../util/is_mac";
|
||||||
import "../ha-icon-button";
|
import "../ha-icon-button";
|
||||||
import type { ECOption } from "../../resources/echarts";
|
import type { ECOption } from "../../resources/echarts";
|
||||||
import { listenMediaQuery } from "../../common/dom/media_query";
|
import { listenMediaQuery } from "../../common/dom/media_query";
|
||||||
|
import type { Themes } from "../../data/ws-themes";
|
||||||
|
import { themesContext } from "../../data/context";
|
||||||
|
|
||||||
export const MIN_TIME_BETWEEN_UPDATES = 60 * 5 * 1000;
|
export const MIN_TIME_BETWEEN_UPDATES = 60 * 5 * 1000;
|
||||||
|
|
||||||
@ -31,6 +34,10 @@ export class HaChartBase extends LitElement {
|
|||||||
@property({ attribute: "external-hidden", type: Boolean })
|
@property({ attribute: "external-hidden", type: Boolean })
|
||||||
public externalHidden = false;
|
public externalHidden = false;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
@consume({ context: themesContext, subscribe: true })
|
||||||
|
_themes!: Themes;
|
||||||
|
|
||||||
@state() private _isZoomed = false;
|
@state() private _isZoomed = false;
|
||||||
|
|
||||||
private _modifierPressed = false;
|
private _modifierPressed = false;
|
||||||
@ -110,6 +117,10 @@ export class HaChartBase extends LitElement {
|
|||||||
if (!this.hasUpdated || !this.chart) {
|
if (!this.hasUpdated || !this.chart) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (changedProps.has("_themes")) {
|
||||||
|
this._setupChart();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (changedProps.has("data")) {
|
if (changedProps.has("data")) {
|
||||||
this.chart.setOption(
|
this.chart.setOption(
|
||||||
{ series: this.data },
|
{ series: this.data },
|
||||||
@ -163,9 +174,15 @@ export class HaChartBase extends LitElement {
|
|||||||
const container = this.renderRoot.querySelector(".chart") as HTMLDivElement;
|
const container = this.renderRoot.querySelector(".chart") as HTMLDivElement;
|
||||||
this._loading = true;
|
this._loading = true;
|
||||||
try {
|
try {
|
||||||
|
if (this.chart) {
|
||||||
|
this.chart.dispose();
|
||||||
|
}
|
||||||
const echarts = (await import("../../resources/echarts")).default;
|
const echarts = (await import("../../resources/echarts")).default;
|
||||||
|
|
||||||
this.chart = echarts.init(container);
|
this.chart = echarts.init(
|
||||||
|
container,
|
||||||
|
this._themes.darkMode ? "dark" : "light"
|
||||||
|
);
|
||||||
this.chart.on("legendselectchanged", (params: any) => {
|
this.chart.on("legendselectchanged", (params: any) => {
|
||||||
if (this.externalHidden) {
|
if (this.externalHidden) {
|
||||||
const isSelected = params.selected[params.name];
|
const isSelected = params.selected[params.name];
|
||||||
@ -207,17 +224,10 @@ export class HaChartBase extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _createOptions(): ECOption {
|
private _createOptions(): ECOption {
|
||||||
const darkMode = this.hass.themes?.darkMode ?? false;
|
const darkMode = this._themes.darkMode ?? false;
|
||||||
const xAxis = Array.isArray(this.options?.xAxis)
|
|
||||||
? this.options?.xAxis
|
|
||||||
: [this.options?.xAxis];
|
|
||||||
const yAxis = Array.isArray(this.options?.yAxis)
|
|
||||||
? this.options?.yAxis
|
|
||||||
: [this.options?.yAxis];
|
|
||||||
// we should create our own theme but this is a quick fix for now
|
|
||||||
const splitLineStyle = darkMode ? { color: "#333" } : {};
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
|
backgroundColor: "transparent",
|
||||||
animation: !this._reducedMotion,
|
animation: !this._reducedMotion,
|
||||||
darkMode,
|
darkMode,
|
||||||
aria: {
|
aria: {
|
||||||
@ -225,32 +235,13 @@ export class HaChartBase extends LitElement {
|
|||||||
},
|
},
|
||||||
dataZoom: this._getDataZoomConfig(),
|
dataZoom: this._getDataZoomConfig(),
|
||||||
...this.options,
|
...this.options,
|
||||||
xAxis: xAxis.map((axis) =>
|
legend: this.options?.legend
|
||||||
axis
|
|
||||||
? {
|
? {
|
||||||
...axis,
|
// we should create our own theme but this is a quick fix for now
|
||||||
splitLine: axis.splitLine
|
inactiveColor: darkMode ? "#444" : "#ccc",
|
||||||
? {
|
...this.options.legend,
|
||||||
...axis.splitLine,
|
|
||||||
lineStyle: splitLineStyle,
|
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
) as XAXisOption[],
|
|
||||||
yAxis: yAxis.map((axis) =>
|
|
||||||
axis
|
|
||||||
? {
|
|
||||||
...axis,
|
|
||||||
splitLine: axis.splitLine
|
|
||||||
? {
|
|
||||||
...axis.splitLine,
|
|
||||||
lineStyle: splitLineStyle,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
) as YAXisOption[],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const isMobile = window.matchMedia(
|
const isMobile = window.matchMedia(
|
||||||
|
@ -192,7 +192,10 @@ export class StateHistoryChartLine extends LitElement {
|
|||||||
max: this.fitYData ? this.maxYAxis : undefined,
|
max: this.fitYData ? this.maxYAxis : undefined,
|
||||||
position: rtl ? "right" : "left",
|
position: rtl ? "right" : "left",
|
||||||
scale: true,
|
scale: true,
|
||||||
nameGap: 3,
|
nameGap: 2,
|
||||||
|
nameTextStyle: {
|
||||||
|
align: "left",
|
||||||
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: true,
|
show: true,
|
||||||
lineStyle: splitLineStyle,
|
lineStyle: splitLineStyle,
|
||||||
|
@ -154,10 +154,6 @@ export class StateHistoryChartTimeline extends LitElement {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public willUpdate(changedProps: PropertyValues) {
|
public willUpdate(changedProps: PropertyValues) {
|
||||||
if (!this.hasUpdated) {
|
|
||||||
this._createOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
changedProps.has("startTime") ||
|
changedProps.has("startTime") ||
|
||||||
changedProps.has("endTime") ||
|
changedProps.has("endTime") ||
|
||||||
@ -171,10 +167,12 @@ export class StateHistoryChartTimeline extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
!this.hasUpdated ||
|
||||||
changedProps.has("startTime") ||
|
changedProps.has("startTime") ||
|
||||||
changedProps.has("endTime") ||
|
changedProps.has("endTime") ||
|
||||||
changedProps.has("showNames") ||
|
changedProps.has("showNames") ||
|
||||||
changedProps.has("paddingYAxis")
|
changedProps.has("paddingYAxis") ||
|
||||||
|
changedProps.has("_yWidth")
|
||||||
) {
|
) {
|
||||||
this._createOptions();
|
this._createOptions();
|
||||||
}
|
}
|
||||||
@ -183,9 +181,11 @@ export class StateHistoryChartTimeline extends LitElement {
|
|||||||
private _createOptions() {
|
private _createOptions() {
|
||||||
const narrow = this.narrow;
|
const narrow = this.narrow;
|
||||||
const showNames = this.chunked || this.showNames;
|
const showNames = this.chunked || this.showNames;
|
||||||
|
const maxInternalLabelWidth = narrow ? 70 : 165;
|
||||||
const labelWidth = showNames
|
const labelWidth = showNames
|
||||||
? Math.max(narrow ? 70 : 170, this.paddingYAxis)
|
? Math.max(this.paddingYAxis, this._yWidth)
|
||||||
: 0;
|
: 0;
|
||||||
|
const labelMargin = 5;
|
||||||
const rtl = computeRTL(this.hass);
|
const rtl = computeRTL(this.hass);
|
||||||
const dayDifference = differenceInDays(this.endTime, this.startTime);
|
const dayDifference = differenceInDays(this.endTime, this.startTime);
|
||||||
this._chartOptions = {
|
this._chartOptions = {
|
||||||
@ -193,6 +193,12 @@ export class StateHistoryChartTimeline extends LitElement {
|
|||||||
type: "time",
|
type: "time",
|
||||||
min: this.startTime,
|
min: this.startTime,
|
||||||
max: this.endTime,
|
max: this.endTime,
|
||||||
|
axisTick: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
opacity: 0.4,
|
||||||
|
},
|
||||||
|
},
|
||||||
axisLabel: getTimeAxisLabelConfig(
|
axisLabel: getTimeAxisLabelConfig(
|
||||||
this.hass.locale,
|
this.hass.locale,
|
||||||
this.hass.config,
|
this.hass.config,
|
||||||
@ -217,12 +223,14 @@ export class StateHistoryChartTimeline extends LitElement {
|
|||||||
},
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
show: showNames,
|
show: showNames,
|
||||||
width: labelWidth,
|
width: labelWidth - labelMargin,
|
||||||
overflow: "truncate",
|
overflow: "truncate",
|
||||||
margin: 5,
|
margin: labelMargin,
|
||||||
// @ts-ignore this is a valid option
|
|
||||||
formatter: (label: string) => {
|
formatter: (label: string) => {
|
||||||
const width = Math.min(measureTextWidth(label, 12) + 5, labelWidth);
|
const width = Math.min(
|
||||||
|
measureTextWidth(label, 12) + labelMargin,
|
||||||
|
maxInternalLabelWidth
|
||||||
|
);
|
||||||
if (width > this._yWidth) {
|
if (width > this._yWidth) {
|
||||||
this._yWidth = width;
|
this._yWidth = width;
|
||||||
fireEvent(this, "y-width-changed", {
|
fireEvent(this, "y-width-changed", {
|
||||||
|
@ -2,7 +2,6 @@ import type { PropertyValues } from "lit";
|
|||||||
import { css, html, LitElement } from "lit";
|
import { css, html, LitElement } from "lit";
|
||||||
import { customElement, eventOptions, property, state } from "lit/decorators";
|
import { customElement, eventOptions, property, state } from "lit/decorators";
|
||||||
import type { RenderItemFunction } from "@lit-labs/virtualizer/virtualize";
|
import type { RenderItemFunction } from "@lit-labs/virtualizer/virtualize";
|
||||||
import { styleMap } from "lit/directives/style-map";
|
|
||||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||||
import { restoreScroll } from "../../common/decorators/restore-scroll";
|
import { restoreScroll } from "../../common/decorators/restore-scroll";
|
||||||
import type {
|
import type {
|
||||||
@ -136,10 +135,7 @@ export class StateHistoryCharts extends LitElement {
|
|||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
if (!Array.isArray(item)) {
|
if (!Array.isArray(item)) {
|
||||||
return html`<div
|
return html`<div class="entry-container">
|
||||||
class="entry-container"
|
|
||||||
style=${styleMap({ height: this.height })}
|
|
||||||
>
|
|
||||||
<state-history-chart-line
|
<state-history-chart-line
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.unit=${item.unit}
|
.unit=${item.unit}
|
||||||
@ -157,7 +153,7 @@ export class StateHistoryCharts extends LitElement {
|
|||||||
.maxYAxis=${this.maxYAxis}
|
.maxYAxis=${this.maxYAxis}
|
||||||
.fitYData=${this.fitYData}
|
.fitYData=${this.fitYData}
|
||||||
@y-width-changed=${this._yWidthChanged}
|
@y-width-changed=${this._yWidthChanged}
|
||||||
.height=${this.height}
|
.height=${this.virtualize ? undefined : this.height}
|
||||||
></state-history-chart-line>
|
></state-history-chart-line>
|
||||||
</div> `;
|
</div> `;
|
||||||
}
|
}
|
||||||
@ -281,7 +277,8 @@ export class StateHistoryCharts extends LitElement {
|
|||||||
|
|
||||||
static styles = css`
|
static styles = css`
|
||||||
:host {
|
:host {
|
||||||
display: block;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
/* height of single timeline chart = 60px */
|
/* height of single timeline chart = 60px */
|
||||||
min-height: 60px;
|
min-height: 60px;
|
||||||
}
|
}
|
||||||
@ -302,6 +299,7 @@ export class StateHistoryCharts extends LitElement {
|
|||||||
|
|
||||||
.entry-container {
|
.entry-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-container:hover {
|
.entry-container:hover {
|
||||||
|
@ -96,6 +96,8 @@ export class StatisticsChart extends LitElement {
|
|||||||
|
|
||||||
@state() private _chartOptions?: ECOption;
|
@state() private _chartOptions?: ECOption;
|
||||||
|
|
||||||
|
@state() private _hiddenStats = new Set<string>();
|
||||||
|
|
||||||
private _computedStyle?: CSSStyleDeclaration;
|
private _computedStyle?: CSSStyleDeclaration;
|
||||||
|
|
||||||
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
@ -107,7 +109,8 @@ export class StatisticsChart extends LitElement {
|
|||||||
changedProps.has("statisticsData") ||
|
changedProps.has("statisticsData") ||
|
||||||
changedProps.has("statTypes") ||
|
changedProps.has("statTypes") ||
|
||||||
changedProps.has("chartType") ||
|
changedProps.has("chartType") ||
|
||||||
changedProps.has("hideLegend")
|
changedProps.has("hideLegend") ||
|
||||||
|
changedProps.has("_hiddenStats")
|
||||||
) {
|
) {
|
||||||
this._generateData();
|
this._generateData();
|
||||||
}
|
}
|
||||||
@ -120,7 +123,8 @@ export class StatisticsChart extends LitElement {
|
|||||||
changedProps.has("maxYAxis") ||
|
changedProps.has("maxYAxis") ||
|
||||||
changedProps.has("fitYData") ||
|
changedProps.has("fitYData") ||
|
||||||
changedProps.has("logarithmicScale") ||
|
changedProps.has("logarithmicScale") ||
|
||||||
changedProps.has("hideLegend")
|
changedProps.has("hideLegend") ||
|
||||||
|
changedProps.has("_legendData")
|
||||||
) {
|
) {
|
||||||
this._createOptions();
|
this._createOptions();
|
||||||
}
|
}
|
||||||
@ -160,10 +164,23 @@ export class StatisticsChart extends LitElement {
|
|||||||
.options=${this._chartOptions}
|
.options=${this._chartOptions}
|
||||||
.height=${this.height}
|
.height=${this.height}
|
||||||
style=${styleMap({ height: this.height })}
|
style=${styleMap({ height: this.height })}
|
||||||
|
external-hidden
|
||||||
|
@dataset-hidden=${this._datasetHidden}
|
||||||
|
@dataset-unhidden=${this._datasetUnhidden}
|
||||||
></ha-chart-base>
|
></ha-chart-base>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _datasetHidden(ev: CustomEvent) {
|
||||||
|
this._hiddenStats.add(ev.detail.name);
|
||||||
|
this.requestUpdate("_hiddenStats");
|
||||||
|
}
|
||||||
|
|
||||||
|
private _datasetUnhidden(ev: CustomEvent) {
|
||||||
|
this._hiddenStats.delete(ev.detail.name);
|
||||||
|
this.requestUpdate("_hiddenStats");
|
||||||
|
}
|
||||||
|
|
||||||
private _renderTooltip(params: any) {
|
private _renderTooltip(params: any) {
|
||||||
return params
|
return params
|
||||||
.map((param, index: number) => {
|
.map((param, index: number) => {
|
||||||
@ -219,6 +236,10 @@ export class StatisticsChart extends LitElement {
|
|||||||
yAxis: {
|
yAxis: {
|
||||||
type: this.logarithmicScale ? "log" : "value",
|
type: this.logarithmicScale ? "log" : "value",
|
||||||
name: this.unit,
|
name: this.unit,
|
||||||
|
nameGap: 2,
|
||||||
|
nameTextStyle: {
|
||||||
|
align: "left",
|
||||||
|
},
|
||||||
position: computeRTL(this.hass) ? "right" : "left",
|
position: computeRTL(this.hass) ? "right" : "left",
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
scale: this.chartType !== "bar",
|
scale: this.chartType !== "bar",
|
||||||
@ -247,13 +268,6 @@ export class StatisticsChart extends LitElement {
|
|||||||
appendTo: document.body,
|
appendTo: document.body,
|
||||||
formatter: this._renderTooltip.bind(this),
|
formatter: this._renderTooltip.bind(this),
|
||||||
},
|
},
|
||||||
// scales: {
|
|
||||||
// x: {
|
|
||||||
// ticks: {
|
|
||||||
// source: this.chartType === "bar" ? "data" : undefined,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,8 +296,8 @@ export class StatisticsChart extends LitElement {
|
|||||||
|
|
||||||
let colorIndex = 0;
|
let colorIndex = 0;
|
||||||
const statisticsData = Object.entries(this.statisticsData);
|
const statisticsData = Object.entries(this.statisticsData);
|
||||||
const totalDataSets: LineSeriesOption[] = [];
|
const totalDataSets: typeof this._chartData = [];
|
||||||
const legendData: string[] = [];
|
const legendData: { name: string; color: string }[] = [];
|
||||||
const statisticIds: string[] = [];
|
const statisticIds: string[] = [];
|
||||||
let endTime: Date;
|
let endTime: Date;
|
||||||
|
|
||||||
@ -334,7 +348,7 @@ export class StatisticsChart extends LitElement {
|
|||||||
|
|
||||||
// The datasets for the current statistic
|
// The datasets for the current statistic
|
||||||
const statDataSets: (LineSeriesOption | BarSeriesOption)[] = [];
|
const statDataSets: (LineSeriesOption | BarSeriesOption)[] = [];
|
||||||
const statLegendData: string[] = [];
|
const statLegendData: { name: string; color: string }[] = [];
|
||||||
|
|
||||||
const pushData = (
|
const pushData = (
|
||||||
start: Date,
|
start: Date,
|
||||||
@ -403,7 +417,7 @@ export class StatisticsChart extends LitElement {
|
|||||||
? type === "mean"
|
? type === "mean"
|
||||||
: displayedLegend === false;
|
: displayedLegend === false;
|
||||||
if (showLegend) {
|
if (showLegend) {
|
||||||
statLegendData.push(name);
|
statLegendData.push({ name, color });
|
||||||
}
|
}
|
||||||
displayedLegend = displayedLegend || showLegend;
|
displayedLegend = displayedLegend || showLegend;
|
||||||
}
|
}
|
||||||
@ -415,8 +429,7 @@ export class StatisticsChart extends LitElement {
|
|||||||
name: name
|
name: name
|
||||||
? `${name} (${this.hass.localize(
|
? `${name} (${this.hass.localize(
|
||||||
`ui.components.statistics_charts.statistic_types.${type}`
|
`ui.components.statistics_charts.statistic_types.${type}`
|
||||||
)})
|
)})`
|
||||||
`
|
|
||||||
: this.hass.localize(
|
: this.hass.localize(
|
||||||
`ui.components.statistics_charts.statistic_types.${type}`
|
`ui.components.statistics_charts.statistic_types.${type}`
|
||||||
),
|
),
|
||||||
@ -472,7 +485,9 @@ export class StatisticsChart extends LitElement {
|
|||||||
}
|
}
|
||||||
dataValues.push(val);
|
dataValues.push(val);
|
||||||
});
|
});
|
||||||
|
if (!this._hiddenStats.has(name)) {
|
||||||
pushData(startDate, new Date(stat.end), dataValues);
|
pushData(startDate, new Date(stat.end), dataValues);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Concat two arrays
|
// Concat two arrays
|
||||||
@ -484,8 +499,22 @@ export class StatisticsChart extends LitElement {
|
|||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
legendData.forEach(({ name, color }) => {
|
||||||
|
// Add an empty series for the legend
|
||||||
|
totalDataSets.push({
|
||||||
|
id: name + "-legend",
|
||||||
|
name: name,
|
||||||
|
color,
|
||||||
|
type: this.chartType,
|
||||||
|
data: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
this._chartData = totalDataSets;
|
this._chartData = totalDataSets;
|
||||||
this._legendData = legendData;
|
if (legendData.length !== this._legendData.length) {
|
||||||
|
// only update the legend if it has changed or it will trigger options update
|
||||||
|
this._legendData = legendData.map(({ name }) => name);
|
||||||
|
}
|
||||||
this._statisticIds = statisticIds;
|
this._statisticIds = statisticIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,14 +326,12 @@ export class HuiEnergyDevicesDetailGraphCard
|
|||||||
Object.keys(consumptionData.total).forEach((time) => {
|
Object.keys(consumptionData.total).forEach((time) => {
|
||||||
const value =
|
const value =
|
||||||
consumptionData.total[time] - (totalDeviceConsumption[time] || 0);
|
consumptionData.total[time] - (totalDeviceConsumption[time] || 0);
|
||||||
if (value > 0) {
|
|
||||||
const dataPoint = [Number(time), value];
|
const dataPoint = [Number(time), value];
|
||||||
if (compare) {
|
if (compare) {
|
||||||
dataPoint[2] = dataPoint[0];
|
dataPoint[2] = dataPoint[0];
|
||||||
dataPoint[0] += compareOffset;
|
dataPoint[0] += compareOffset;
|
||||||
}
|
}
|
||||||
untrackedConsumption.push(dataPoint);
|
untrackedConsumption.push(dataPoint);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
const dataset: BarSeriesOption = {
|
const dataset: BarSeriesOption = {
|
||||||
type: "bar",
|
type: "bar",
|
||||||
|
@ -64,7 +64,6 @@ export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
|
|||||||
getGridOptions(): LovelaceGridOptions {
|
getGridOptions(): LovelaceGridOptions {
|
||||||
return {
|
return {
|
||||||
columns: 12,
|
columns: 12,
|
||||||
rows: 6,
|
|
||||||
min_columns: 6,
|
min_columns: 6,
|
||||||
min_rows: this._config?.entities?.length || 1,
|
min_rows: this._config?.entities?.length || 1,
|
||||||
};
|
};
|
||||||
@ -244,6 +243,9 @@ export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
|
|||||||
start_date: now.toISOString(),
|
start_date: now.toISOString(),
|
||||||
})}`;
|
})}`;
|
||||||
|
|
||||||
|
const columns = this._config.grid_options?.columns ?? 12;
|
||||||
|
const narrow = Number.isNaN(columns) || Number(columns) < 12;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-card>
|
<ha-card>
|
||||||
${this._config.title
|
${this._config.title
|
||||||
@ -281,7 +283,10 @@ export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
|
|||||||
.minYAxis=${this._config.min_y_axis}
|
.minYAxis=${this._config.min_y_axis}
|
||||||
.maxYAxis=${this._config.max_y_axis}
|
.maxYAxis=${this._config.max_y_axis}
|
||||||
.fitYData=${this._config.fit_y_data || false}
|
.fitYData=${this._config.fit_y_data || false}
|
||||||
height="100%"
|
.height=${this._config.grid_options?.rows
|
||||||
|
? "100%"
|
||||||
|
: undefined}
|
||||||
|
.narrow=${narrow}
|
||||||
></state-history-charts>
|
></state-history-charts>
|
||||||
`}
|
`}
|
||||||
</div>
|
</div>
|
||||||
|
@ -131,7 +131,6 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
|
|||||||
getGridOptions(): LovelaceGridOptions {
|
getGridOptions(): LovelaceGridOptions {
|
||||||
return {
|
return {
|
||||||
columns: 12,
|
columns: 12,
|
||||||
rows: 5,
|
|
||||||
min_columns: 6,
|
min_columns: 6,
|
||||||
min_rows: 3,
|
min_rows: 3,
|
||||||
};
|
};
|
||||||
@ -279,7 +278,7 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
|
|||||||
.hideLegend=${this._config.hide_legend || false}
|
.hideLegend=${this._config.hide_legend || false}
|
||||||
.logarithmicScale=${this._config.logarithmic_scale || false}
|
.logarithmicScale=${this._config.logarithmic_scale || false}
|
||||||
.daysToShow=${this._config.days_to_show || DEFAULT_DAYS_TO_SHOW}
|
.daysToShow=${this._config.days_to_show || DEFAULT_DAYS_TO_SHOW}
|
||||||
height="100%"
|
.height=${this._config.grid_options?.rows ? "100%" : undefined}
|
||||||
></statistics-chart>
|
></statistics-chart>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
|
@ -29,11 +29,21 @@ export const loggingMixin = <T extends Constructor<HassBaseEl>>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
!__DEV__ &&
|
// !__DEV__ &&
|
||||||
(ev.message.includes("ResizeObserver loop limit exceeded") ||
|
ev.message.includes("ResizeObserver loop limit exceeded") ||
|
||||||
ev.message.includes(
|
ev.message.includes(
|
||||||
"ResizeObserver loop completed with undelivered notifications"
|
"ResizeObserver loop completed with undelivered notifications"
|
||||||
))
|
) ||
|
||||||
|
(ev.error.stack.includes("echarts") &&
|
||||||
|
(ev.message.includes(
|
||||||
|
"Cannot read properties of undefined (reading 'hostedBy')"
|
||||||
|
) ||
|
||||||
|
ev.message.includes(
|
||||||
|
"Cannot read properties of undefined (reading 'scale')"
|
||||||
|
) ||
|
||||||
|
ev.message.includes(
|
||||||
|
"Cannot read properties of null (reading 'innerHTML')"
|
||||||
|
)))
|
||||||
) {
|
) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopImmediatePropagation();
|
ev.stopImmediatePropagation();
|
||||||
|
@ -21,5 +21,5 @@ export function measureTextWidth(
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.font = `${fontSize}px ${fontFamily}`;
|
context.font = `${fontSize}px ${fontFamily}`;
|
||||||
return context.measureText(text).width;
|
return Math.ceil(context.measureText(text).width);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user