mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-29 12:16:39 +00:00
Merge branch 'rc'
This commit is contained in:
commit
0ab9098f23
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "home-assistant-frontend"
|
name = "home-assistant-frontend"
|
||||||
version = "20250205.0"
|
version = "20250210.0"
|
||||||
license = {text = "Apache-2.0"}
|
license = {text = "Apache-2.0"}
|
||||||
description = "The Home Assistant frontend"
|
description = "The Home Assistant frontend"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -328,6 +328,7 @@ export class HaChartBase extends LitElement {
|
|||||||
backgroundColor: "transparent",
|
backgroundColor: "transparent",
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: style.getPropertyValue("--primary-text-color"),
|
color: style.getPropertyValue("--primary-text-color"),
|
||||||
|
fontFamily: "Roboto, Noto, sans-serif",
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textStyle: {
|
textStyle: {
|
||||||
|
@ -222,14 +222,14 @@ export class StateHistoryChartLine extends LitElement {
|
|||||||
minYAxis = ({ min }) => Math.min(min, this.minYAxis!);
|
minYAxis = ({ min }) => Math.min(min, this.minYAxis!);
|
||||||
}
|
}
|
||||||
} else if (this.logarithmicScale) {
|
} else if (this.logarithmicScale) {
|
||||||
minYAxis = ({ min }) => (min > 0 ? min * 0.95 : min * 1.05);
|
minYAxis = ({ min }) => Math.floor(min > 0 ? min * 0.95 : min * 1.05);
|
||||||
}
|
}
|
||||||
if (typeof maxYAxis === "number") {
|
if (typeof maxYAxis === "number") {
|
||||||
if (this.fitYData) {
|
if (this.fitYData) {
|
||||||
maxYAxis = ({ max }) => Math.max(max, this.maxYAxis!);
|
maxYAxis = ({ max }) => Math.max(max, this.maxYAxis!);
|
||||||
}
|
}
|
||||||
} else if (this.logarithmicScale) {
|
} else if (this.logarithmicScale) {
|
||||||
maxYAxis = ({ max }) => (max > 0 ? max * 1.05 : max * 0.95);
|
maxYAxis = ({ max }) => Math.ceil(max > 0 ? max * 1.05 : max * 0.95);
|
||||||
}
|
}
|
||||||
this._chartOptions = {
|
this._chartOptions = {
|
||||||
xAxis: {
|
xAxis: {
|
||||||
|
@ -237,14 +237,14 @@ export class StatisticsChart extends LitElement {
|
|||||||
minYAxis = ({ min }) => Math.min(min, this.minYAxis!);
|
minYAxis = ({ min }) => Math.min(min, this.minYAxis!);
|
||||||
}
|
}
|
||||||
} else if (this.logarithmicScale) {
|
} else if (this.logarithmicScale) {
|
||||||
minYAxis = ({ min }) => (min > 0 ? min * 0.95 : min * 1.05);
|
minYAxis = ({ min }) => Math.floor(min > 0 ? min * 0.95 : min * 1.05);
|
||||||
}
|
}
|
||||||
if (typeof maxYAxis === "number") {
|
if (typeof maxYAxis === "number") {
|
||||||
if (this.fitYData) {
|
if (this.fitYData) {
|
||||||
maxYAxis = ({ max }) => Math.max(max, this.maxYAxis!);
|
maxYAxis = ({ max }) => Math.max(max, this.maxYAxis!);
|
||||||
}
|
}
|
||||||
} else if (this.logarithmicScale) {
|
} else if (this.logarithmicScale) {
|
||||||
maxYAxis = ({ max }) => (max > 0 ? max * 1.05 : max * 0.95);
|
maxYAxis = ({ max }) => Math.ceil(max > 0 ? max * 1.05 : max * 0.95);
|
||||||
}
|
}
|
||||||
const endTime = this.endTime ?? new Date();
|
const endTime = this.endTime ?? new Date();
|
||||||
let startTime = this.startTime;
|
let startTime = this.startTime;
|
||||||
@ -290,7 +290,6 @@ export class StatisticsChart extends LitElement {
|
|||||||
align: "left",
|
align: "left",
|
||||||
},
|
},
|
||||||
position: computeRTL(this.hass) ? "right" : "left",
|
position: computeRTL(this.hass) ? "right" : "left",
|
||||||
// @ts-ignore
|
|
||||||
scale: true,
|
scale: true,
|
||||||
min: this._clampYAxis(minYAxis),
|
min: this._clampYAxis(minYAxis),
|
||||||
max: this._clampYAxis(maxYAxis),
|
max: this._clampYAxis(maxYAxis),
|
||||||
|
@ -64,9 +64,13 @@ export class HaNetwork extends LitElement {
|
|||||||
>
|
>
|
||||||
</ha-checkbox>
|
</ha-checkbox>
|
||||||
</span>
|
</span>
|
||||||
<span slot="heading" data-for="auto_configure"> Auto Configure </span>
|
<span slot="heading" data-for="auto_configure">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.network.adapter.auto_configure"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
<span slot="description" data-for="auto_configure">
|
<span slot="description" data-for="auto_configure">
|
||||||
Detected:
|
${this.hass.localize("ui.panel.config.network.adapter.detected")}:
|
||||||
${format_auto_detected_interfaces(this.networkConfig.adapters)}
|
${format_auto_detected_interfaces(this.networkConfig.adapters)}
|
||||||
</span>
|
</span>
|
||||||
</ha-settings-row>
|
</ha-settings-row>
|
||||||
@ -85,18 +89,21 @@ export class HaNetwork extends LitElement {
|
|||||||
</ha-checkbox>
|
</ha-checkbox>
|
||||||
</span>
|
</span>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
Adapter: ${adapter.name}
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.network.adapter.adapter"
|
||||||
|
)}:
|
||||||
|
${adapter.name}
|
||||||
${adapter.default
|
${adapter.default
|
||||||
? html`<ha-svg-icon .path=${mdiStar}></ha-svg-icon>
|
? html`<ha-svg-icon .path=${mdiStar}></ha-svg-icon>
|
||||||
(Default)`
|
(${this.hass.localize("ui.common.default")})`
|
||||||
: ""}
|
: nothing}
|
||||||
</span>
|
</span>
|
||||||
<span slot="description">
|
<span slot="description">
|
||||||
${format_addresses([...adapter.ipv4, ...adapter.ipv6])}
|
${format_addresses([...adapter.ipv4, ...adapter.ipv6])}
|
||||||
</span>
|
</span>
|
||||||
</ha-settings-row>`
|
</ha-settings-row>`
|
||||||
)
|
)
|
||||||
: ""}
|
: nothing}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,6 +329,9 @@ class DialogAreaDetail extends LitElement {
|
|||||||
return [
|
return [
|
||||||
haStyleDialog,
|
haStyleDialog,
|
||||||
css`
|
css`
|
||||||
|
ha-textfield {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
ha-aliases-editor,
|
ha-aliases-editor,
|
||||||
ha-entity-picker,
|
ha-entity-picker,
|
||||||
ha-floor-picker,
|
ha-floor-picker,
|
||||||
|
@ -72,7 +72,10 @@ export function getCommonOptions(
|
|||||||
yAxis: {
|
yAxis: {
|
||||||
type: "value",
|
type: "value",
|
||||||
name: unit,
|
name: unit,
|
||||||
nameGap: 5,
|
nameGap: 2,
|
||||||
|
nameTextStyle: {
|
||||||
|
align: "left",
|
||||||
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
formatter: (value: number) => formatNumber(Math.abs(value), locale),
|
formatter: (value: number) => formatNumber(Math.abs(value), locale),
|
||||||
},
|
},
|
||||||
@ -81,10 +84,10 @@ export function getCommonOptions(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
top: 35,
|
top: 15,
|
||||||
bottom: 10,
|
bottom: 0,
|
||||||
left: 10,
|
left: 1,
|
||||||
right: 10,
|
right: 1,
|
||||||
containLabel: true,
|
containLabel: true,
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
@ -222,7 +225,7 @@ export function fillDataGapsAndRoundCaps(datasets: BarSeriesOption[]) {
|
|||||||
if (x === undefined) {
|
if (x === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (x !== bucket) {
|
if (Number(x) !== bucket) {
|
||||||
datasets[i].data?.splice(index, 0, {
|
datasets[i].data?.splice(index, 0, {
|
||||||
value: [bucket, 0],
|
value: [bucket, 0],
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
|
@ -193,9 +193,10 @@ export class HuiEnergyDevicesDetailGraphCard
|
|||||||
icon: "circle",
|
icon: "circle",
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
|
top: 45,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
left: 5,
|
left: 1,
|
||||||
right: 5,
|
right: 1,
|
||||||
containLabel: true,
|
containLabel: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -446,9 +447,9 @@ export class HuiEnergyDevicesDetailGraphCard
|
|||||||
stack: compare ? "devicesCompare" : "devices",
|
stack: compare ? "devicesCompare" : "devices",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return sorted_devices.map(
|
return sorted_devices
|
||||||
(device) => data.find((d) => (d.id as string).includes(device))!
|
.map((device) => data.find((d) => (d.id as string).includes(device))!)
|
||||||
);
|
.filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = css`
|
static styles = css`
|
||||||
|
@ -27,6 +27,7 @@ import { hasConfigChanged } from "../../common/has-changed";
|
|||||||
import type { ECOption } from "../../../../resources/echarts";
|
import type { ECOption } from "../../../../resources/echarts";
|
||||||
import "../../../../components/ha-card";
|
import "../../../../components/ha-card";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { measureTextWidth } from "../../../../util/text";
|
||||||
|
|
||||||
@customElement("hui-energy-devices-graph-card")
|
@customElement("hui-energy-devices-graph-card")
|
||||||
export class HuiEnergyDevicesGraphCard
|
export class HuiEnergyDevicesGraphCard
|
||||||
@ -109,8 +110,11 @@ export class HuiEnergyDevicesGraphCard
|
|||||||
return `${title}${params.marker} ${params.seriesName}: ${value}`;
|
return `${title}${params.marker} ${params.seriesName}: ${value}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createOptions = memoizeOne(
|
private _createOptions = memoizeOne((data: BarSeriesOption[]): ECOption => {
|
||||||
(data: BarSeriesOption[]): ECOption => ({
|
const isMobile = window.matchMedia(
|
||||||
|
"all and (max-width: 450px), all and (max-height: 500px)"
|
||||||
|
).matches;
|
||||||
|
return {
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: "value",
|
type: "value",
|
||||||
name: "kWh",
|
name: "kWh",
|
||||||
@ -124,6 +128,17 @@ export class HuiEnergyDevicesGraphCard
|
|||||||
axisLabel: {
|
axisLabel: {
|
||||||
formatter: this._getDeviceName.bind(this),
|
formatter: this._getDeviceName.bind(this),
|
||||||
overflow: "truncate",
|
overflow: "truncate",
|
||||||
|
fontSize: 12,
|
||||||
|
margin: 5,
|
||||||
|
width: Math.min(
|
||||||
|
isMobile ? 100 : 200,
|
||||||
|
Math.max(
|
||||||
|
...(data[0]?.data?.map(
|
||||||
|
(d: any) =>
|
||||||
|
measureTextWidth(this._getDeviceName(d.value[1]), 12) + 5
|
||||||
|
) || [])
|
||||||
|
)
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
@ -137,8 +152,8 @@ export class HuiEnergyDevicesGraphCard
|
|||||||
show: true,
|
show: true,
|
||||||
formatter: this._renderTooltip.bind(this),
|
formatter: this._renderTooltip.bind(this),
|
||||||
},
|
},
|
||||||
})
|
};
|
||||||
);
|
});
|
||||||
|
|
||||||
private _getDeviceName(statisticId: string): string {
|
private _getDeviceName(statisticId: string): string {
|
||||||
return (
|
return (
|
||||||
|
@ -367,6 +367,7 @@ export class HuiEnergySolarGraphCard
|
|||||||
data.push({
|
data.push({
|
||||||
id: "forecast-" + source.stat_energy_from,
|
id: "forecast-" + source.stat_energy_from,
|
||||||
type: "line",
|
type: "line",
|
||||||
|
stack: "forecast",
|
||||||
name: this.hass.localize(
|
name: this.hass.localize(
|
||||||
"ui.panel.lovelace.cards.energy.energy_solar_graph.forecast",
|
"ui.panel.lovelace.cards.energy.energy_solar_graph.forecast",
|
||||||
{
|
{
|
||||||
|
@ -300,6 +300,8 @@ export class HuiEnergyUsageGraphCard
|
|||||||
type: "bar",
|
type: "bar",
|
||||||
stack: "usage",
|
stack: "usage",
|
||||||
data: [],
|
data: [],
|
||||||
|
// @ts-expect-error
|
||||||
|
order: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,6 +317,8 @@ export class HuiEnergyUsageGraphCard
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
datasets.sort((a, b) => a.order - b.order);
|
||||||
fillDataGapsAndRoundCaps(datasets);
|
fillDataGapsAndRoundCaps(datasets);
|
||||||
this._chartData = datasets;
|
this._chartData = datasets;
|
||||||
}
|
}
|
||||||
@ -482,7 +486,7 @@ export class HuiEnergyUsageGraphCard
|
|||||||
this._compareStart!
|
this._compareStart!
|
||||||
);
|
);
|
||||||
|
|
||||||
Object.entries(combinedData).forEach(([type, sources]) => {
|
Object.entries(combinedData).forEach(([type, sources], idx) => {
|
||||||
Object.entries(sources).forEach(([statId, source]) => {
|
Object.entries(sources).forEach(([statId, source]) => {
|
||||||
const points: BarSeriesOption["data"] = [];
|
const points: BarSeriesOption["data"] = [];
|
||||||
// Process chart data.
|
// Process chart data.
|
||||||
@ -513,6 +517,13 @@ export class HuiEnergyUsageGraphCard
|
|||||||
statId,
|
statId,
|
||||||
statisticsMetaData[statId]
|
statisticsMetaData[statId]
|
||||||
),
|
),
|
||||||
|
// @ts-expect-error
|
||||||
|
order:
|
||||||
|
type === "used_solar"
|
||||||
|
? 1
|
||||||
|
: type === "to_battery"
|
||||||
|
? Object.keys(combinedData).length
|
||||||
|
: idx + 2,
|
||||||
barMaxWidth: 50,
|
barMaxWidth: 50,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderColor: getEnergyColor(
|
borderColor: getEnergyColor(
|
||||||
|
@ -6122,7 +6122,12 @@
|
|||||||
},
|
},
|
||||||
"network_adapter": "Network adapter",
|
"network_adapter": "Network adapter",
|
||||||
"network_adapter_info": "Configure which network adapters integrations will use. Currently this setting only affects multicast traffic. A restart is required for these settings to apply.",
|
"network_adapter_info": "Configure which network adapters integrations will use. Currently this setting only affects multicast traffic. A restart is required for these settings to apply.",
|
||||||
"ip_information": "IP Information"
|
"ip_information": "IP Information",
|
||||||
|
"adapter": {
|
||||||
|
"auto_configure": "Auto configure",
|
||||||
|
"detected": "Detected",
|
||||||
|
"adapter": "Adapter"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"storage": {
|
"storage": {
|
||||||
"caption": "Storage",
|
"caption": "Storage",
|
||||||
|
@ -10,7 +10,7 @@ let textMeasureCanvas: HTMLCanvasElement | undefined;
|
|||||||
export function measureTextWidth(
|
export function measureTextWidth(
|
||||||
text: string,
|
text: string,
|
||||||
fontSize: number,
|
fontSize: number,
|
||||||
fontFamily = "sans-serif"
|
fontFamily = "Roboto, Noto, sans-serif"
|
||||||
): number {
|
): number {
|
||||||
if (!textMeasureCanvas) {
|
if (!textMeasureCanvas) {
|
||||||
textMeasureCanvas = document.createElement("canvas");
|
textMeasureCanvas = document.createElement("canvas");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user