Compact legend mode for statistics-graph-card (#19089)

* Compact legend mode for statistics-graph-card

* remove clearable from selector

* Remove legend_mode, make compact default
This commit is contained in:
karwosts 2024-02-16 10:02:42 -05:00 committed by GitHub
parent 316756d06a
commit 26600e3d78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 117 additions and 22 deletions

View File

@ -5,10 +5,18 @@ import type {
ChartOptions,
TooltipModel,
} from "chart.js";
import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit";
import {
css,
CSSResultGroup,
html,
nothing,
LitElement,
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 { fireEvent } from "../../common/dom/fire_event";
import { clamp } from "../../common/number/clamp";
import { HomeAssistant } from "../../types";
import { debounce } from "../../common/util/debounce";
@ -27,6 +35,11 @@ interface Tooltip
left: string;
}
export interface ChartDatasetExtra {
show_legend?: boolean;
legend_label?: string;
}
@customElement("ha-chart-base")
export class HaChartBase extends LitElement {
public chart?: Chart;
@ -38,6 +51,8 @@ export class HaChartBase extends LitElement {
@property({ attribute: false }) public data: ChartData = { datasets: [] };
@property({ attribute: false }) public extraData?: ChartDatasetExtra[];
@property({ attribute: false }) public options?: ChartOptions;
@property({ attribute: false }) public plugins?: any[];
@ -46,6 +61,8 @@ export class HaChartBase extends LitElement {
@property({ type: Number }) public paddingYAxis = 0;
@property({ type: Boolean }) public externalHidden = false;
@state() private _chartHeight?: number;
@state() private _tooltip?: Tooltip;
@ -148,6 +165,19 @@ export class HaChartBase extends LitElement {
}
}
if (changedProps.has("data")) {
if (this.externalHidden) {
this._hiddenDatasets = new Set();
if (this.data?.datasets) {
this.data.datasets.forEach((dataset, index) => {
if (dataset.hidden) {
this._hiddenDatasets.add(index);
}
});
}
}
}
if (!this.hasUpdated || !this.chart) {
return;
}
@ -157,7 +187,7 @@ export class HaChartBase extends LitElement {
return;
}
if (changedProps.has("data")) {
if (this._hiddenDatasets.size) {
if (this._hiddenDatasets.size && !this.externalHidden) {
this.data.datasets.forEach((dataset, index) => {
dataset.hidden = this._hiddenDatasets.has(index);
});
@ -175,25 +205,30 @@ export class HaChartBase extends LitElement {
${this.options?.plugins?.legend?.display === true
? html`<div class="chartLegend">
<ul>
${this.data.datasets.map(
(dataset, index) =>
html`<li
.datasetIndex=${index}
@click=${this._legendClick}
class=${classMap({
hidden: this._hiddenDatasets.has(index),
})}
.title=${dataset.label}
>
<div
class="bullet"
style=${styleMap({
backgroundColor: dataset.backgroundColor as string,
borderColor: dataset.borderColor as string,
${this.data.datasets.map((dataset, index) =>
this.extraData?.[index]?.show_legend === false
? nothing
: html`<li
.datasetIndex=${index}
@click=${this._legendClick}
class=${classMap({
hidden: this._hiddenDatasets.has(index),
})}
></div>
<div class="label">${dataset.label}</div>
</li>`
.title=${this.extraData?.[index]?.legend_label ??
dataset.label}
>
<div
class="bullet"
style=${styleMap({
backgroundColor: dataset.backgroundColor as string,
borderColor: dataset.borderColor as string,
})}
></div>
<div class="label">
${this.extraData?.[index]?.legend_label ??
dataset.label}
</div>
</li>`
)}
</ul>
</div>`
@ -339,9 +374,19 @@ export class HaChartBase extends LitElement {
if (this.chart.isDatasetVisible(index)) {
this.chart.setDatasetVisibility(index, false);
this._hiddenDatasets.add(index);
if (this.externalHidden) {
fireEvent(this, "dataset-hidden", {
index,
});
}
} else {
this.chart.setDatasetVisibility(index, true);
this._hiddenDatasets.delete(index);
if (this.externalHidden) {
fireEvent(this, "dataset-unhidden", {
index,
});
}
}
this.chart.update("none");
this.requestUpdate("_hiddenDatasets");
@ -486,4 +531,8 @@ declare global {
interface HTMLElementTagNameMap {
"ha-chart-base": HaChartBase;
}
interface HASSDomEvents {
"dataset-hidden": { index: number };
"dataset-unhidden": { index: number };
}
}

View File

@ -32,7 +32,11 @@ import {
} from "../../data/recorder";
import type { HomeAssistant } from "../../types";
import "./ha-chart-base";
import type { ChartResizeOptions, HaChartBase } from "./ha-chart-base";
import type {
ChartResizeOptions,
ChartDatasetExtra,
HaChartBase,
} from "./ha-chart-base";
export const supportedStatTypeMap: Record<StatisticType, StatisticType> = {
mean: "mean",
@ -79,10 +83,14 @@ export class StatisticsChart extends LitElement {
@state() private _chartData: ChartData = { datasets: [] };
@state() private _chartDatasetExtra: ChartDatasetExtra[] = [];
@state() private _statisticIds: string[] = [];
@state() private _chartOptions?: ChartOptions;
@state() private _hiddenStats = new Set<string>();
@query("ha-chart-base") private _chart?: HaChartBase;
private _computedStyle?: CSSStyleDeclaration;
@ -96,6 +104,9 @@ export class StatisticsChart extends LitElement {
}
public willUpdate(changedProps: PropertyValues) {
if (changedProps.has("legendMode")) {
this._hiddenStats.clear();
}
if (
!this.hasUpdated ||
changedProps.has("unit") ||
@ -110,7 +121,8 @@ export class StatisticsChart extends LitElement {
changedProps.has("statisticsData") ||
changedProps.has("statTypes") ||
changedProps.has("chartType") ||
changedProps.has("hideLegend")
changedProps.has("hideLegend") ||
changedProps.has("_hiddenStats")
) {
this._generateData();
}
@ -145,14 +157,30 @@ export class StatisticsChart extends LitElement {
return html`
<ha-chart-base
externalHidden
.hass=${this.hass}
.data=${this._chartData}
.extraData=${this._chartDatasetExtra}
.options=${this._chartOptions}
.chartType=${this.chartType}
@dataset-hidden=${this._datasetHidden}
@dataset-unhidden=${this._datasetUnhidden}
></ha-chart-base>
`;
}
private _datasetHidden(ev) {
ev.stopPropagation();
this._hiddenStats.add(this._statisticIds[ev.detail.index]);
this.requestUpdate("_hiddenStats");
}
private _datasetUnhidden(ev) {
ev.stopPropagation();
this._hiddenStats.delete(this._statisticIds[ev.detail.index]);
this.requestUpdate("_hiddenStats");
}
private _createOptions(unit?: string) {
this._chartOptions = {
parsing: false,
@ -274,6 +302,7 @@ export class StatisticsChart extends LitElement {
let colorIndex = 0;
const statisticsData = Object.entries(this.statisticsData);
const totalDataSets: ChartDataset<"line">[] = [];
const totalDatasetExtras: ChartDatasetExtra[] = [];
const statisticIds: string[] = [];
let endTime: Date;
@ -324,6 +353,7 @@ export class StatisticsChart extends LitElement {
// The datasets for the current statistic
const statDataSets: ChartDataset<"line">[] = [];
const statDatasetExtras: ChartDatasetExtra[] = [];
const pushData = (
start: Date,
@ -384,9 +414,20 @@ export class StatisticsChart extends LitElement {
})
: this.statTypes;
let displayed_legend = false;
sortedTypes.forEach((type) => {
if (statisticsHaveType(stats, type)) {
const band = drawBands && (type === "min" || type === "max");
if (!this.hideLegend) {
const show_legend = hasMean
? type === "mean"
: displayed_legend === false;
statDatasetExtras.push({
legend_label: name,
show_legend,
});
displayed_legend = displayed_legend || show_legend;
}
statTypes.push(type);
statDataSets.push({
label: name
@ -408,6 +449,9 @@ export class StatisticsChart extends LitElement {
band && hasMean ? color + (this.hideLegend ? "00" : "7F") : color,
backgroundColor: band ? color + "3F" : color + "7F",
pointRadius: 0,
hidden: !this.hideLegend
? this._hiddenStats.has(statistic_id)
: false,
data: [],
// @ts-ignore
unit: meta?.unit_of_measurement,
@ -446,6 +490,7 @@ export class StatisticsChart extends LitElement {
// Concat two arrays
Array.prototype.push.apply(totalDataSets, statDataSets);
Array.prototype.push.apply(totalDatasetExtras, statDatasetExtras);
});
if (unit) {
@ -455,6 +500,7 @@ export class StatisticsChart extends LitElement {
this._chartData = {
datasets: totalDataSets,
};
this._chartDatasetExtra = totalDatasetExtras;
this._statisticIds = statisticIds;
}