mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-19 15:26:36 +00:00
Move energy panel up in sidebar (#9636)
* Move energy panel up in sidebar * Remove headers from wizard * Update text * Always show all configured devices * Make leaf clickable * Bump HAWS
This commit is contained in:
parent
469faf509b
commit
9a92825954
@ -107,7 +107,7 @@
|
||||
"fuse.js": "^6.0.0",
|
||||
"google-timezones-json": "^1.0.2",
|
||||
"hls.js": "^1.0.7",
|
||||
"home-assistant-js-websocket": "^5.11.0",
|
||||
"home-assistant-js-websocket": "^5.11.1",
|
||||
"idb-keyval": "^5.0.5",
|
||||
"intl-messageformat": "^9.6.16",
|
||||
"js-yaml": "^4.1.0",
|
||||
|
@ -53,9 +53,10 @@ const SHOW_AFTER_SPACER = ["config", "developer-tools", "hassio"];
|
||||
const SUPPORT_SCROLL_IF_NEEDED = "scrollIntoViewIfNeeded" in document.body;
|
||||
|
||||
const SORT_VALUE_URL_PATHS = {
|
||||
map: 1,
|
||||
logbook: 2,
|
||||
history: 3,
|
||||
energy: 1,
|
||||
map: 2,
|
||||
logbook: 3,
|
||||
history: 4,
|
||||
"developer-tools": 9,
|
||||
hassio: 10,
|
||||
config: 11,
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
} from "../../../../dialogs/generic/show-dialog-box";
|
||||
import { haStyle } from "../../../../resources/styles";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import { documentationUrl } from "../../../../util/documentation-url";
|
||||
import { showEnergySettingsDeviceDialog } from "../dialogs/show-dialogs-energy";
|
||||
import { energyCardStyles } from "./styles";
|
||||
|
||||
@ -33,12 +34,29 @@ export class EnergyDeviceSettings extends LitElement {
|
||||
return html`
|
||||
<ha-card>
|
||||
<h1 class="card-header">
|
||||
<ha-svg-icon .path=${mdiDevices}></ha-svg-icon>Monitor individual
|
||||
devices
|
||||
<ha-svg-icon .path=${mdiDevices}></ha-svg-icon>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.energy.device_consumption.title"
|
||||
)}
|
||||
</h1>
|
||||
|
||||
<div class="card-content">
|
||||
<p>Monitor individual devices.</p>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.energy.device_consumption.sub"
|
||||
)}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferer"
|
||||
href="${documentationUrl(
|
||||
this.hass,
|
||||
"/docs/energy/individual-devices/"
|
||||
)}"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.energy.device_consumption.learn_more"
|
||||
)}</a
|
||||
>
|
||||
</p>
|
||||
<h3>Devices</h3>
|
||||
${this.preferences.device_consumption.map((device) => {
|
||||
const entityState = this.hass.states[device.stat_consumption];
|
||||
|
@ -34,6 +34,7 @@ import {
|
||||
} from "../../../../dialogs/generic/show-dialog-box";
|
||||
import { haStyle } from "../../../../resources/styles";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import { documentationUrl } from "../../../../util/documentation-url";
|
||||
import {
|
||||
showEnergySettingsGridFlowFromDialog,
|
||||
showEnergySettingsGridFlowToDialog,
|
||||
@ -63,12 +64,25 @@ export class EnergyGridSettings extends LitElement {
|
||||
return html`
|
||||
<ha-card>
|
||||
<h1 class="card-header">
|
||||
<ha-svg-icon .path=${mdiTransmissionTower}></ha-svg-icon
|
||||
>${this.hass.localize("ui.panel.config.energy.grid.title")}
|
||||
<ha-svg-icon .path=${mdiTransmissionTower}></ha-svg-icon>
|
||||
${this.hass.localize("ui.panel.config.energy.grid.title")}
|
||||
</h1>
|
||||
|
||||
<div class="card-content">
|
||||
<p>${this.hass.localize("ui.panel.config.energy.grid.sub")}</p>
|
||||
<p>
|
||||
${this.hass.localize("ui.panel.config.energy.grid.sub")}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferer"
|
||||
href="${documentationUrl(
|
||||
this.hass,
|
||||
"/docs/energy/electricity-grid/"
|
||||
)}"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.energy.grid.learn_more"
|
||||
)}</a
|
||||
>
|
||||
</p>
|
||||
<h3>Grid consumption</h3>
|
||||
${gridSource.flow_from.map((flow) => {
|
||||
const entityState = this.hass.states[flow.stat_energy_from];
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
} from "../../../../dialogs/generic/show-dialog-box";
|
||||
import { haStyle } from "../../../../resources/styles";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import { documentationUrl } from "../../../../util/documentation-url";
|
||||
import { showEnergySettingsSolarDialog } from "../dialogs/show-dialogs-energy";
|
||||
import { energyCardStyles } from "./styles";
|
||||
|
||||
@ -37,14 +38,24 @@ export class EnergySolarSettings extends LitElement {
|
||||
return html`
|
||||
<ha-card>
|
||||
<h1 class="card-header">
|
||||
<ha-svg-icon .path=${mdiSolarPower}></ha-svg-icon>Configure solar
|
||||
panels
|
||||
<ha-svg-icon .path=${mdiSolarPower}></ha-svg-icon>
|
||||
${this.hass.localize("ui.panel.config.energy.solar.title")}
|
||||
</h1>
|
||||
|
||||
<div class="card-content">
|
||||
<p>
|
||||
Let Home Assistant monitor your solar panels and give you insight on
|
||||
their performace.
|
||||
${this.hass.localize("ui.panel.config.energy.solar.sub")}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferer"
|
||||
href="${documentationUrl(
|
||||
this.hass,
|
||||
"/docs/energy/solar-panels/"
|
||||
)}"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.energy.solar.learn_more"
|
||||
)}</a
|
||||
>
|
||||
</p>
|
||||
<h3>Solar production</h3>
|
||||
${solarSources.map((source) => {
|
||||
|
@ -58,7 +58,6 @@ export class DialogEnergyDeviceSettings
|
||||
@closed=${this.closeDialog}
|
||||
>
|
||||
${this._error ? html`<p class="error">${this._error}</p>` : ""}
|
||||
<p>Track your devices <a href="#">Learn more</a></p>
|
||||
|
||||
<ha-statistic-picker
|
||||
.hass=${this.hass}
|
||||
|
@ -85,11 +85,11 @@ export class DialogEnergyGridFlowSettings
|
||||
@closed=${this.closeDialog}
|
||||
>
|
||||
${this._error ? html`<p class="error">${this._error}</p>` : ""}
|
||||
<p>
|
||||
<div>
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.energy.grid.flow_dialog.${this._params.direction}.paragraph`
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ha-statistic-picker
|
||||
.hass=${this.hass}
|
||||
@ -277,6 +277,9 @@ export class DialogEnergyGridFlowSettings
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
ha-dialog {
|
||||
--mdc-dialog-max-width: 430px;
|
||||
}
|
||||
ha-formfield {
|
||||
display: block;
|
||||
}
|
||||
|
@ -75,7 +75,6 @@ export class DialogEnergySolarSettings
|
||||
@closed=${this.closeDialog}
|
||||
>
|
||||
${this._error ? html`<p class="error">${this._error}</p>` : ""}
|
||||
<p>Solar production for the win! <a href="#">Learn more</a></p>
|
||||
|
||||
<ha-statistic-picker
|
||||
.hass=${this.hass}
|
||||
@ -212,6 +211,9 @@ export class DialogEnergySolarSettings
|
||||
haStyle,
|
||||
haStyleDialog,
|
||||
css`
|
||||
ha-dialog {
|
||||
--mdc-dialog-max-width: 430px;
|
||||
}
|
||||
img {
|
||||
height: 24px;
|
||||
margin-right: 16px;
|
||||
|
@ -41,9 +41,6 @@ export class EnergySetupWizard extends LitElement implements LovelaceCard {
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<h2>${this.hass.localize("ui.panel.energy.setup.header")}</h2>
|
||||
<h3>${this.hass.localize("ui.panel.energy.setup.slogan")}</h3>
|
||||
|
||||
<p>Step ${this._step + 1} of 3</p>
|
||||
${this._step === 0
|
||||
? html` <ha-energy-grid-settings
|
||||
|
@ -178,10 +178,6 @@ export class HuiEnergyDevicesGraphCard
|
||||
const statisticsData = Object.values(this._data!);
|
||||
let endTime: Date;
|
||||
|
||||
if (statisticsData.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
endTime = new Date(
|
||||
Math.max(
|
||||
...statisticsData.map((stats) =>
|
||||
@ -190,7 +186,7 @@ export class HuiEnergyDevicesGraphCard
|
||||
)
|
||||
);
|
||||
|
||||
if (endTime > new Date()) {
|
||||
if (!endTime || endTime > new Date()) {
|
||||
endTime = new Date();
|
||||
}
|
||||
|
||||
@ -207,27 +203,30 @@ export class HuiEnergyDevicesGraphCard
|
||||
},
|
||||
];
|
||||
|
||||
Object.entries(this._data).forEach(([id, statistics], idx) => {
|
||||
const entity = this.hass.states[id];
|
||||
const label = entity ? computeStateName(entity) : id;
|
||||
for (let idx = 0; idx < prefs.device_consumption.length; idx++) {
|
||||
const device = prefs.device_consumption[idx];
|
||||
const entity = this.hass.states[device.stat_consumption];
|
||||
const label = entity ? computeStateName(entity) : device.stat_consumption;
|
||||
|
||||
const color = getColorByIndex(idx);
|
||||
|
||||
borderColor.push(color);
|
||||
backgroundColor.push(color + "7F");
|
||||
|
||||
const value = calculateStatisticSumGrowth(statistics);
|
||||
const value =
|
||||
device.stat_consumption in this._data
|
||||
? calculateStatisticSumGrowth(this._data[device.stat_consumption])
|
||||
: 0;
|
||||
data.push({
|
||||
// @ts-expect-error
|
||||
y: label,
|
||||
x: value || 0,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
data.sort((a, b) => b.x - a.x);
|
||||
|
||||
this._chartData = {
|
||||
// labels,
|
||||
datasets,
|
||||
};
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
import { css, html, LitElement, svg } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { round } from "../../../../common/number/round";
|
||||
import { subscribeOne } from "../../../../common/util/subscribe-one";
|
||||
import "../../../../components/ha-card";
|
||||
@ -121,6 +122,8 @@ class HuiEnergyDistrubutionCard extends LitElement implements LovelaceCard {
|
||||
let homeLowCarbonCircumference: number | undefined;
|
||||
let homeHighCarbonCircumference: number | undefined;
|
||||
|
||||
let electricityMapUrl: string | undefined;
|
||||
|
||||
if (this._co2SignalEntity && this._co2SignalEntity in this._stats) {
|
||||
// Calculate high carbon consumption
|
||||
const highCarbonConsumption = calculateStatisticsSumGrowthWithPercentage(
|
||||
@ -130,6 +133,12 @@ class HuiEnergyDistrubutionCard extends LitElement implements LovelaceCard {
|
||||
.filter(Boolean)
|
||||
);
|
||||
|
||||
const co2State = this.hass.states[this._co2SignalEntity];
|
||||
|
||||
if (co2State) {
|
||||
electricityMapUrl = `https://www.electricitymap.org/zone/${co2State.attributes.country_code}`;
|
||||
}
|
||||
|
||||
if (highCarbonConsumption !== null) {
|
||||
const gridPctHighCarbon = highCarbonConsumption / totalConsumption;
|
||||
|
||||
@ -159,10 +168,15 @@ class HuiEnergyDistrubutionCard extends LitElement implements LovelaceCard {
|
||||
: html`
|
||||
<div class="circle-container low-carbon">
|
||||
<span class="label">Non-fossil</span>
|
||||
<div class="circle">
|
||||
<a
|
||||
class="circle"
|
||||
href=${ifDefined(electricityMapUrl)}
|
||||
target="_blank"
|
||||
rel="noopener no referrer"
|
||||
>
|
||||
<ha-svg-icon .path="${mdiLeaf}"></ha-svg-icon>
|
||||
${round(lowCarbonConsumption, 1)} kWh
|
||||
</div>
|
||||
</a>
|
||||
<svg width="80" height="30">
|
||||
<line x1="40" y1="0" x2="40" y2="30"></line>
|
||||
</svg>
|
||||
@ -478,6 +492,8 @@ class HuiEnergyDistrubutionCard extends LitElement implements LovelaceCard {
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
ha-svg-icon {
|
||||
padding-bottom: 2px;
|
||||
|
@ -992,8 +992,9 @@
|
||||
"description": "Monitor your energy production and consumption",
|
||||
"currency": "",
|
||||
"grid": {
|
||||
"title": "Configure grid",
|
||||
"sub": "Configure the different tarrifs for the energy you consume from the grid, and, if you return energy to the grid, the energy you return to the grid.",
|
||||
"title": "Electricity grid",
|
||||
"sub": "Configure the amount of energy that you consume from the grid and, if you produce energy, give back to the grid. This allows Home Assistant to track your whole home energy usage.",
|
||||
"learn_more": "More information on how to get started.",
|
||||
"flow_dialog": {
|
||||
"from": {
|
||||
"header": "Configure grid consumption",
|
||||
@ -1002,7 +1003,7 @@
|
||||
"cost_para": "Select how Home Assistant should keep track of the costs of the consumed energy.",
|
||||
"no_cost": "Do not track costs",
|
||||
"cost_stat": "Use an entity tracking the total costs",
|
||||
"cost_stat_input": "Entity keeping track of the total costs",
|
||||
"cost_stat_input": "Total Costs Entity",
|
||||
"cost_entity": "Use an entity with current price",
|
||||
"cost_entity_input": "Entity with the current price",
|
||||
"cost_number": "Use a static price",
|
||||
@ -1016,7 +1017,7 @@
|
||||
"cost_para": "Do you get money back when you return energy to the grid?",
|
||||
"no_cost": "I do not get money back",
|
||||
"cost_stat": "Use an entity tracking the total recieved money",
|
||||
"cost_stat_input": "Entity keeping track of the total of received money",
|
||||
"cost_stat_input": "Total Compensation Entity",
|
||||
"cost_entity": "Use an entity with current rate",
|
||||
"cost_entity_input": "Entity with the current rate",
|
||||
"cost_number": "Use a static rate",
|
||||
@ -1026,12 +1027,17 @@
|
||||
}
|
||||
},
|
||||
"solar": {
|
||||
"title": "Solar Panels",
|
||||
"sub": "Let Home Assistant monitor your solar panels and give you insight on their performance.",
|
||||
"learn_more": "More information on how to get started.",
|
||||
"stat_production": "Your solar energy production",
|
||||
"stat_return_to_grid": "Solar energy returned to the grid",
|
||||
"stat_predicted_production": "Prediction of your solar energy production"
|
||||
},
|
||||
"device_consumption": {
|
||||
"description": "If you measure the power consumption of individual devices, you can select the entities with the power consumption below",
|
||||
"title": "Individual devices",
|
||||
"sub": "Tracking the energy usage of individual devices allows Home Assistant to break down your energy usage by device.",
|
||||
"learn_more": "More information on how to get started.",
|
||||
"add_stat": "Pick entity to track energy of",
|
||||
"selected_stat": "Tracking energy for"
|
||||
}
|
||||
@ -3713,8 +3719,6 @@
|
||||
},
|
||||
"energy": {
|
||||
"setup": {
|
||||
"header": "Setup your energy dashboard",
|
||||
"slogan": "The world is heating up. Together we can fix that.",
|
||||
"next": "Next",
|
||||
"back": "Back",
|
||||
"done": "Show me my energy dashboard!"
|
||||
|
10
yarn.lock
10
yarn.lock
@ -8941,7 +8941,7 @@ fsevents@~2.3.1:
|
||||
gulp-rename: ^2.0.0
|
||||
gulp-zopfli-green: ^3.0.1
|
||||
hls.js: ^1.0.7
|
||||
home-assistant-js-websocket: ^5.11.0
|
||||
home-assistant-js-websocket: ^5.11.1
|
||||
html-minifier: ^4.0.0
|
||||
husky: ^1.3.1
|
||||
idb-keyval: ^5.0.5
|
||||
@ -9011,10 +9011,10 @@ fsevents@~2.3.1:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"home-assistant-js-websocket@npm:^5.11.0":
|
||||
version: 5.11.0
|
||||
resolution: "home-assistant-js-websocket@npm:5.11.0"
|
||||
checksum: 7e493f2528a49a2ea8b35468a7c655f97627820542bd4dd841060ca7b34d0fc9c5b4b7cc22d0ba16f1f7932342fd5978c923fc6a213d2af05509ad8ff6912422
|
||||
"home-assistant-js-websocket@npm:^5.11.1":
|
||||
version: 5.11.1
|
||||
resolution: "home-assistant-js-websocket@npm:5.11.1"
|
||||
checksum: 6766cff890831741cfb9ebc5372ed465be578897a8c763daac09a7673d804fa591658542ca1e93619104486956972c94b7f6f9098caaddbf36f89c7808db563d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user