mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-22 08:46:35 +00:00
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:
parent
316756d06a
commit
26600e3d78
@ -5,10 +5,18 @@ import type {
|
|||||||
ChartOptions,
|
ChartOptions,
|
||||||
TooltipModel,
|
TooltipModel,
|
||||||
} from "chart.js";
|
} 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 { customElement, property, state } from "lit/decorators";
|
||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import { styleMap } from "lit/directives/style-map";
|
import { styleMap } from "lit/directives/style-map";
|
||||||
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import { clamp } from "../../common/number/clamp";
|
import { clamp } from "../../common/number/clamp";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import { debounce } from "../../common/util/debounce";
|
import { debounce } from "../../common/util/debounce";
|
||||||
@ -27,6 +35,11 @@ interface Tooltip
|
|||||||
left: string;
|
left: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ChartDatasetExtra {
|
||||||
|
show_legend?: boolean;
|
||||||
|
legend_label?: string;
|
||||||
|
}
|
||||||
|
|
||||||
@customElement("ha-chart-base")
|
@customElement("ha-chart-base")
|
||||||
export class HaChartBase extends LitElement {
|
export class HaChartBase extends LitElement {
|
||||||
public chart?: Chart;
|
public chart?: Chart;
|
||||||
@ -38,6 +51,8 @@ export class HaChartBase extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public data: ChartData = { datasets: [] };
|
@property({ attribute: false }) public data: ChartData = { datasets: [] };
|
||||||
|
|
||||||
|
@property({ attribute: false }) public extraData?: ChartDatasetExtra[];
|
||||||
|
|
||||||
@property({ attribute: false }) public options?: ChartOptions;
|
@property({ attribute: false }) public options?: ChartOptions;
|
||||||
|
|
||||||
@property({ attribute: false }) public plugins?: any[];
|
@property({ attribute: false }) public plugins?: any[];
|
||||||
@ -46,6 +61,8 @@ export class HaChartBase extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Number }) public paddingYAxis = 0;
|
@property({ type: Number }) public paddingYAxis = 0;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public externalHidden = false;
|
||||||
|
|
||||||
@state() private _chartHeight?: number;
|
@state() private _chartHeight?: number;
|
||||||
|
|
||||||
@state() private _tooltip?: Tooltip;
|
@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) {
|
if (!this.hasUpdated || !this.chart) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -157,7 +187,7 @@ export class HaChartBase extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (changedProps.has("data")) {
|
if (changedProps.has("data")) {
|
||||||
if (this._hiddenDatasets.size) {
|
if (this._hiddenDatasets.size && !this.externalHidden) {
|
||||||
this.data.datasets.forEach((dataset, index) => {
|
this.data.datasets.forEach((dataset, index) => {
|
||||||
dataset.hidden = this._hiddenDatasets.has(index);
|
dataset.hidden = this._hiddenDatasets.has(index);
|
||||||
});
|
});
|
||||||
@ -175,25 +205,30 @@ export class HaChartBase extends LitElement {
|
|||||||
${this.options?.plugins?.legend?.display === true
|
${this.options?.plugins?.legend?.display === true
|
||||||
? html`<div class="chartLegend">
|
? html`<div class="chartLegend">
|
||||||
<ul>
|
<ul>
|
||||||
${this.data.datasets.map(
|
${this.data.datasets.map((dataset, index) =>
|
||||||
(dataset, index) =>
|
this.extraData?.[index]?.show_legend === false
|
||||||
html`<li
|
? nothing
|
||||||
.datasetIndex=${index}
|
: html`<li
|
||||||
@click=${this._legendClick}
|
.datasetIndex=${index}
|
||||||
class=${classMap({
|
@click=${this._legendClick}
|
||||||
hidden: this._hiddenDatasets.has(index),
|
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,
|
|
||||||
})}
|
})}
|
||||||
></div>
|
.title=${this.extraData?.[index]?.legend_label ??
|
||||||
<div class="label">${dataset.label}</div>
|
dataset.label}
|
||||||
</li>`
|
>
|
||||||
|
<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>
|
</ul>
|
||||||
</div>`
|
</div>`
|
||||||
@ -339,9 +374,19 @@ export class HaChartBase extends LitElement {
|
|||||||
if (this.chart.isDatasetVisible(index)) {
|
if (this.chart.isDatasetVisible(index)) {
|
||||||
this.chart.setDatasetVisibility(index, false);
|
this.chart.setDatasetVisibility(index, false);
|
||||||
this._hiddenDatasets.add(index);
|
this._hiddenDatasets.add(index);
|
||||||
|
if (this.externalHidden) {
|
||||||
|
fireEvent(this, "dataset-hidden", {
|
||||||
|
index,
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.chart.setDatasetVisibility(index, true);
|
this.chart.setDatasetVisibility(index, true);
|
||||||
this._hiddenDatasets.delete(index);
|
this._hiddenDatasets.delete(index);
|
||||||
|
if (this.externalHidden) {
|
||||||
|
fireEvent(this, "dataset-unhidden", {
|
||||||
|
index,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.chart.update("none");
|
this.chart.update("none");
|
||||||
this.requestUpdate("_hiddenDatasets");
|
this.requestUpdate("_hiddenDatasets");
|
||||||
@ -486,4 +531,8 @@ declare global {
|
|||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"ha-chart-base": HaChartBase;
|
"ha-chart-base": HaChartBase;
|
||||||
}
|
}
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"dataset-hidden": { index: number };
|
||||||
|
"dataset-unhidden": { index: number };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,11 @@ import {
|
|||||||
} from "../../data/recorder";
|
} from "../../data/recorder";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import "./ha-chart-base";
|
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> = {
|
export const supportedStatTypeMap: Record<StatisticType, StatisticType> = {
|
||||||
mean: "mean",
|
mean: "mean",
|
||||||
@ -79,10 +83,14 @@ export class StatisticsChart extends LitElement {
|
|||||||
|
|
||||||
@state() private _chartData: ChartData = { datasets: [] };
|
@state() private _chartData: ChartData = { datasets: [] };
|
||||||
|
|
||||||
|
@state() private _chartDatasetExtra: ChartDatasetExtra[] = [];
|
||||||
|
|
||||||
@state() private _statisticIds: string[] = [];
|
@state() private _statisticIds: string[] = [];
|
||||||
|
|
||||||
@state() private _chartOptions?: ChartOptions;
|
@state() private _chartOptions?: ChartOptions;
|
||||||
|
|
||||||
|
@state() private _hiddenStats = new Set<string>();
|
||||||
|
|
||||||
@query("ha-chart-base") private _chart?: HaChartBase;
|
@query("ha-chart-base") private _chart?: HaChartBase;
|
||||||
|
|
||||||
private _computedStyle?: CSSStyleDeclaration;
|
private _computedStyle?: CSSStyleDeclaration;
|
||||||
@ -96,6 +104,9 @@ export class StatisticsChart extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public willUpdate(changedProps: PropertyValues) {
|
public willUpdate(changedProps: PropertyValues) {
|
||||||
|
if (changedProps.has("legendMode")) {
|
||||||
|
this._hiddenStats.clear();
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
!this.hasUpdated ||
|
!this.hasUpdated ||
|
||||||
changedProps.has("unit") ||
|
changedProps.has("unit") ||
|
||||||
@ -110,7 +121,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();
|
||||||
}
|
}
|
||||||
@ -145,14 +157,30 @@ export class StatisticsChart extends LitElement {
|
|||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-chart-base
|
<ha-chart-base
|
||||||
|
externalHidden
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.data=${this._chartData}
|
.data=${this._chartData}
|
||||||
|
.extraData=${this._chartDatasetExtra}
|
||||||
.options=${this._chartOptions}
|
.options=${this._chartOptions}
|
||||||
.chartType=${this.chartType}
|
.chartType=${this.chartType}
|
||||||
|
@dataset-hidden=${this._datasetHidden}
|
||||||
|
@dataset-unhidden=${this._datasetUnhidden}
|
||||||
></ha-chart-base>
|
></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) {
|
private _createOptions(unit?: string) {
|
||||||
this._chartOptions = {
|
this._chartOptions = {
|
||||||
parsing: false,
|
parsing: false,
|
||||||
@ -274,6 +302,7 @@ 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: ChartDataset<"line">[] = [];
|
const totalDataSets: ChartDataset<"line">[] = [];
|
||||||
|
const totalDatasetExtras: ChartDatasetExtra[] = [];
|
||||||
const statisticIds: string[] = [];
|
const statisticIds: string[] = [];
|
||||||
let endTime: Date;
|
let endTime: Date;
|
||||||
|
|
||||||
@ -324,6 +353,7 @@ export class StatisticsChart extends LitElement {
|
|||||||
|
|
||||||
// The datasets for the current statistic
|
// The datasets for the current statistic
|
||||||
const statDataSets: ChartDataset<"line">[] = [];
|
const statDataSets: ChartDataset<"line">[] = [];
|
||||||
|
const statDatasetExtras: ChartDatasetExtra[] = [];
|
||||||
|
|
||||||
const pushData = (
|
const pushData = (
|
||||||
start: Date,
|
start: Date,
|
||||||
@ -384,9 +414,20 @@ export class StatisticsChart extends LitElement {
|
|||||||
})
|
})
|
||||||
: this.statTypes;
|
: this.statTypes;
|
||||||
|
|
||||||
|
let displayed_legend = false;
|
||||||
sortedTypes.forEach((type) => {
|
sortedTypes.forEach((type) => {
|
||||||
if (statisticsHaveType(stats, type)) {
|
if (statisticsHaveType(stats, type)) {
|
||||||
const band = drawBands && (type === "min" || type === "max");
|
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);
|
statTypes.push(type);
|
||||||
statDataSets.push({
|
statDataSets.push({
|
||||||
label: name
|
label: name
|
||||||
@ -408,6 +449,9 @@ export class StatisticsChart extends LitElement {
|
|||||||
band && hasMean ? color + (this.hideLegend ? "00" : "7F") : color,
|
band && hasMean ? color + (this.hideLegend ? "00" : "7F") : color,
|
||||||
backgroundColor: band ? color + "3F" : color + "7F",
|
backgroundColor: band ? color + "3F" : color + "7F",
|
||||||
pointRadius: 0,
|
pointRadius: 0,
|
||||||
|
hidden: !this.hideLegend
|
||||||
|
? this._hiddenStats.has(statistic_id)
|
||||||
|
: false,
|
||||||
data: [],
|
data: [],
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
unit: meta?.unit_of_measurement,
|
unit: meta?.unit_of_measurement,
|
||||||
@ -446,6 +490,7 @@ export class StatisticsChart extends LitElement {
|
|||||||
|
|
||||||
// Concat two arrays
|
// Concat two arrays
|
||||||
Array.prototype.push.apply(totalDataSets, statDataSets);
|
Array.prototype.push.apply(totalDataSets, statDataSets);
|
||||||
|
Array.prototype.push.apply(totalDatasetExtras, statDatasetExtras);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (unit) {
|
if (unit) {
|
||||||
@ -455,6 +500,7 @@ export class StatisticsChart extends LitElement {
|
|||||||
this._chartData = {
|
this._chartData = {
|
||||||
datasets: totalDataSets,
|
datasets: totalDataSets,
|
||||||
};
|
};
|
||||||
|
this._chartDatasetExtra = totalDatasetExtras;
|
||||||
this._statisticIds = statisticIds;
|
this._statisticIds = statisticIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user