Skip to content

Commit 0dd07a3

Browse files
authored
Fix legend in devices-detail-graph (home-assistant#26596)
1 parent 589771d commit 0dd07a3

File tree

2 files changed

+70
-16
lines changed

2 files changed

+70
-16
lines changed

src/components/chart/ha-chart-base.ts

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export type CustomLegendOption = ECOption["legend"] & {
3939
type: "custom";
4040
data?: {
4141
id?: string;
42+
secondaryIds?: string[]; // Other dataset IDs that should be controlled by this legend item.
4243
name: string;
4344
itemStyle?: Record<string, any>;
4445
}[];
@@ -181,6 +182,10 @@ export class HaChartBase extends LitElement {
181182
return;
182183
}
183184
let chartOptions: ECOption = {};
185+
if (changedProps.has("options")) {
186+
// Separate 'if' from below since this must updated before _getSeries()
187+
this._updateHiddenStatsFromOptions(this.options);
188+
}
184189
if (changedProps.has("data") || changedProps.has("_hiddenDatasets")) {
185190
chartOptions.series = this._getSeries();
186191
}
@@ -451,14 +456,7 @@ export class HaChartBase extends LitElement {
451456
});
452457
}
453458

454-
const legend = ensureArray(this.options?.legend || [])[0] as
455-
| LegendComponentOption
456-
| undefined;
457-
Object.entries(legend?.selected || {}).forEach(([stat, selected]) => {
458-
if (selected === false) {
459-
this._hiddenDatasets.add(stat);
460-
}
461-
});
459+
this._updateHiddenStatsFromOptions(this.options);
462460

463461
this.chart.setOption({
464462
...this._createOptions(),
@@ -469,6 +467,42 @@ export class HaChartBase extends LitElement {
469467
}
470468
}
471469

470+
// Return an array of all IDs associated with the legend item of the primaryId
471+
private _getAllIdsFromLegend(
472+
options: ECOption | undefined,
473+
primaryId: string
474+
): string[] {
475+
if (!options) return [primaryId];
476+
const legend = ensureArray(this.options?.legend || [])[0] as
477+
| LegendComponentOption
478+
| undefined;
479+
480+
let customLegendItem;
481+
if (legend?.type === "custom") {
482+
customLegendItem = (legend as CustomLegendOption).data?.find(
483+
(li) => typeof li === "object" && li.id === primaryId
484+
);
485+
}
486+
487+
return [primaryId, ...(customLegendItem?.secondaryIds || [])];
488+
}
489+
490+
// Parses the options structure and adds all ids of unselected legend items to hiddenDatasets.
491+
// No known need to remove items at this time.
492+
private _updateHiddenStatsFromOptions(options: ECOption | undefined) {
493+
if (!options) return;
494+
const legend = ensureArray(this.options?.legend || [])[0] as
495+
| LegendComponentOption
496+
| undefined;
497+
Object.entries(legend?.selected || {}).forEach(([stat, selected]) => {
498+
if (selected === false) {
499+
this._getAllIdsFromLegend(options, stat).forEach((id) =>
500+
this._hiddenDatasets.add(id)
501+
);
502+
}
503+
});
504+
}
505+
472506
private _getDataZoomConfig(): DataZoomComponentOption | undefined {
473507
const xAxis = (this.options?.xAxis?.[0] ?? this.options?.xAxis) as
474508
| XAXisOption
@@ -844,10 +878,14 @@ export class HaChartBase extends LitElement {
844878
}
845879
const id = ev.currentTarget?.id;
846880
if (this._hiddenDatasets.has(id)) {
847-
this._hiddenDatasets.delete(id);
881+
this._getAllIdsFromLegend(this.options, id).forEach((i) =>
882+
this._hiddenDatasets.delete(i)
883+
);
848884
fireEvent(this, "dataset-unhidden", { id });
849885
} else {
850-
this._hiddenDatasets.add(id);
886+
this._getAllIdsFromLegend(this.options, id).forEach((i) =>
887+
this._hiddenDatasets.add(i)
888+
);
851889
fireEvent(this, "dataset-hidden", { id });
852890
}
853891
this.requestUpdate("_hiddenDatasets");

src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,18 @@ export class HuiEnergyDevicesDetailGraphCard
148148
{ num: formatNumber(total, this.hass.locale), unit: UNIT }
149149
);
150150

151+
// ha-chart-base will track hidden per ID (so it will have two entries for ID and compare-ID)
152+
// But it will only fire the event for the primary ID, and we will convert and store a list of statistic ids only
151153
private _datasetHidden(ev) {
152-
this._hiddenStats = [...this._hiddenStats, ev.detail.id];
154+
this._hiddenStats = [
155+
...this._hiddenStats,
156+
this._getStatIdFromId(ev.detail.id),
157+
];
153158
}
154159

155160
private _datasetUnhidden(ev) {
156161
this._hiddenStats = this._hiddenStats.filter(
157-
(stat) => stat !== ev.detail.id
162+
(stat) => stat !== this._getStatIdFromId(ev.detail.id)
158163
);
159164
}
160165

@@ -179,16 +184,25 @@ export class HuiEnergyDevicesDetailGraphCard
179184
this._formatTotal
180185
);
181186

187+
const selected = this._legendData
188+
? this._legendData
189+
.filter(
190+
(d) =>
191+
d.id && this._hiddenStats.includes(this._getStatIdFromId(d.id))
192+
)
193+
.reduce((acc, d) => {
194+
acc[d.id!] = false;
195+
return acc;
196+
}, {})
197+
: {};
198+
182199
return {
183200
...commonOptions,
184201
legend: {
185202
show: true,
186203
type: "custom",
187204
data: this._legendData,
188-
selected: this._hiddenStats.reduce((acc, stat) => {
189-
acc[stat] = false;
190-
return acc;
191-
}, {}),
205+
selected,
192206
},
193207
grid: {
194208
top: 15,
@@ -315,6 +329,7 @@ export class HuiEnergyDevicesDetailGraphCard
315329
datasets.push(...processedData);
316330
this._legendData = processedData.map((d) => ({
317331
id: d.id as string,
332+
secondaryIds: [`compare-${d.id}`],
318333
name: d.name as string,
319334
itemStyle: {
320335
color: d.color as string,
@@ -332,6 +347,7 @@ export class HuiEnergyDevicesDetailGraphCard
332347
datasets.push(untrackedData);
333348
this._legendData.push({
334349
id: untrackedData.id as string,
350+
secondaryIds: [`compare-${untrackedData.id}`],
335351
name: untrackedData.name as string,
336352
itemStyle: {
337353
color: untrackedData.color as string,

0 commit comments

Comments
 (0)