Energyflow UI: add price/co2 toggle (#25717)
This commit is contained in:
parent
bdcacb8374
commit
25382accc7
4 changed files with 84 additions and 28 deletions
|
|
@ -140,14 +140,16 @@
|
|||
</template>
|
||||
</EnergyflowEntry>
|
||||
<EnergyflowEntry
|
||||
:key="`grid-${showCo2}`"
|
||||
:name="$t('main.energyflow.gridImport')"
|
||||
icon="powersupply"
|
||||
:power="gridImport"
|
||||
:powerUnit="powerUnit"
|
||||
:details="detailsValue(tariffGrid, tariffCo2)"
|
||||
:detailsFmt="detailsFmt"
|
||||
:detailsTooltip="detailsTooltip(tariffGrid, tariffCo2)"
|
||||
:detailsClickable="hasPriceAndCo2"
|
||||
data-testid="energyflow-entry-gridimport"
|
||||
@details-clicked="toggleCo2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -163,15 +165,17 @@
|
|||
<div>
|
||||
<EnergyflowEntry
|
||||
v-if="pvPossible"
|
||||
:key="`home-${showCo2}`"
|
||||
:name="$t('main.energyflow.homePower')"
|
||||
icon="home"
|
||||
:power="homePower"
|
||||
:powerUnit="powerUnit"
|
||||
:details="detailsValue(tariffPriceHome, tariffCo2Home)"
|
||||
:detailsFmt="detailsFmt"
|
||||
:detailsTooltip="detailsTooltip(tariffPriceHome, tariffCo2Home)"
|
||||
:detailsClickable="hasPriceAndCo2"
|
||||
data-testid="energyflow-entry-home"
|
||||
:expanded="consumersExpanded"
|
||||
@details-clicked="toggleCo2"
|
||||
@toggle="toggleConsumers"
|
||||
>
|
||||
<template v-if="consumers.length > 0" #expanded>
|
||||
|
|
@ -188,6 +192,7 @@
|
|||
</template>
|
||||
</EnergyflowEntry>
|
||||
<EnergyflowEntry
|
||||
:key="`loadpoints-${showCo2}`"
|
||||
:name="loadpointsLabel"
|
||||
icon="vehicle"
|
||||
:iconProps="{ names: vehicleIcons }"
|
||||
|
|
@ -199,11 +204,10 @@
|
|||
: undefined
|
||||
"
|
||||
:detailsFmt="detailsFmt"
|
||||
:detailsTooltip="
|
||||
detailsTooltip(tariffPriceLoadpoints, tariffCo2Loadpoints)
|
||||
"
|
||||
:detailsClickable="hasPriceAndCo2"
|
||||
data-testid="energyflow-entry-loadpoints"
|
||||
:expanded="loadpointsExpanded"
|
||||
@details-clicked="toggleCo2"
|
||||
@toggle="toggleLoadpoints"
|
||||
>
|
||||
<template v-if="activeLoadpointsCount > 0" #expanded>
|
||||
|
|
@ -277,14 +281,16 @@
|
|||
</EnergyflowEntry>
|
||||
<EnergyflowEntry
|
||||
v-if="pvPossible"
|
||||
:key="`export-${showCo2}`"
|
||||
:name="$t('main.energyflow.pvExport')"
|
||||
icon="powersupply"
|
||||
:power="pvExport"
|
||||
:powerUnit="powerUnit"
|
||||
:details="detailsValue(-tariffFeedIn)"
|
||||
:detailsFmt="detailsFmt"
|
||||
:detailsTooltip="detailsTooltip(-tariffFeedIn)"
|
||||
:detailsClickable="hasPriceAndCo2"
|
||||
data-testid="energyflow-entry-gridexport"
|
||||
@details-clicked="toggleCo2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -356,6 +362,21 @@ export default defineComponent({
|
|||
return { detailsOpen: false, detailsCompleteHeight: null as number | null, ready: false };
|
||||
},
|
||||
computed: {
|
||||
showCo2() {
|
||||
if (this.hasCo2 && !this.hasPrice) {
|
||||
return true;
|
||||
}
|
||||
return settings.energyflowCo2;
|
||||
},
|
||||
hasPrice() {
|
||||
return this.tariffGrid !== undefined;
|
||||
},
|
||||
hasCo2() {
|
||||
return this.tariffCo2 !== undefined;
|
||||
},
|
||||
hasPriceAndCo2() {
|
||||
return this.hasPrice && this.hasCo2;
|
||||
},
|
||||
gridImport() {
|
||||
return Math.max(0, this.gridPower);
|
||||
},
|
||||
|
|
@ -434,14 +455,14 @@ export default defineComponent({
|
|||
fmtLoadpointTemp() {
|
||||
return (temp: number) => this.fmtTemperature(temp);
|
||||
},
|
||||
co2Available() {
|
||||
smartCostCo2() {
|
||||
return this.smartCostType === SMART_COST_TYPE.CO2;
|
||||
},
|
||||
pvPossible() {
|
||||
return this.pvConfigured || this.gridConfigured;
|
||||
},
|
||||
batteryGridChargeNow() {
|
||||
if (this.co2Available) {
|
||||
if (this.smartCostCo2) {
|
||||
return this.fmtCo2Short(this.tariffCo2);
|
||||
}
|
||||
return this.fmtPricePerKWh(this.tariffGrid, this.currency, true);
|
||||
|
|
@ -455,7 +476,7 @@ export default defineComponent({
|
|||
if (!this.batteryGridChargeLimitSet) {
|
||||
return;
|
||||
}
|
||||
if (this.co2Available) {
|
||||
if (this.smartCostCo2) {
|
||||
return this.fmtCo2Short(this.batteryGridChargeLimit);
|
||||
}
|
||||
return this.fmtPricePerKWh(this.batteryGridChargeLimit, this.currency, true);
|
||||
|
|
@ -532,27 +553,16 @@ export default defineComponent({
|
|||
window.removeEventListener("resize", this.updateHeight);
|
||||
},
|
||||
methods: {
|
||||
detailsTooltip(price?: number, co2?: number) {
|
||||
const result = [];
|
||||
if (co2 !== undefined) {
|
||||
result.push(`${this.fmtCo2Long(co2)}`);
|
||||
}
|
||||
if (price !== undefined) {
|
||||
result.push(`${this.fmtPricePerKWh(price, this.currency)}`);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
detailsValue(price?: number, co2?: number) {
|
||||
if (this.co2Available) {
|
||||
return co2;
|
||||
}
|
||||
return price;
|
||||
return this.showCo2 ? co2 : price;
|
||||
},
|
||||
detailsFmt(value: number) {
|
||||
if (this.co2Available) {
|
||||
return this.fmtCo2Short(value);
|
||||
}
|
||||
return this.fmtPricePerKWh(value, this.currency, true);
|
||||
return this.showCo2
|
||||
? this.fmtCo2Short(value)
|
||||
: this.fmtPricePerKWh(value, this.currency, true);
|
||||
},
|
||||
toggleCo2() {
|
||||
settings.energyflowCo2 = !settings.energyflowCo2;
|
||||
},
|
||||
forecastFmt(value: number) {
|
||||
if (typeof value !== "number") return "";
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
<span class="text-end text-nowrap ps-1 fw-bold d-flex align-items-center">
|
||||
<div
|
||||
ref="details"
|
||||
class="fw-normal d-flex align-items-center"
|
||||
class="fw-normal d-flex align-items-center user-select-none"
|
||||
:class="{
|
||||
'text-decoration-underline': detailsClickable,
|
||||
'evcc-gray': detailsInactive,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const SETTINGS_UNIT = "settings_unit";
|
|||
const SETTINGS_12H_FORMAT = "settings_12h_format";
|
||||
const SETTINGS_HIDDEN_FEATURES = "settings_hidden_features";
|
||||
const SETTINGS_ENERGYFLOW_DETAILS = "settings_energyflow_details";
|
||||
const SETTINGS_ENERGYFLOW_CO2 = "settings_energyflow_co2";
|
||||
const SETTINGS_ENERGYFLOW_PV = "settings_energyflow_pv";
|
||||
const SETTINGS_ENERGYFLOW_BATTERY = "settings_energyflow_battery";
|
||||
const SETTINGS_ENERGYFLOW_LOADPOINTS = "settings_energyflow_loadpoints";
|
||||
|
|
@ -105,6 +106,7 @@ export interface Settings {
|
|||
is12hFormat: boolean;
|
||||
hiddenFeatures: boolean;
|
||||
energyflowDetails: boolean;
|
||||
energyflowCo2: boolean;
|
||||
energyflowPv: boolean;
|
||||
energyflowBattery: boolean;
|
||||
energyflowLoadpoints: boolean;
|
||||
|
|
@ -126,6 +128,7 @@ const settings: Settings = reactive({
|
|||
is12hFormat: readBool(SETTINGS_12H_FORMAT),
|
||||
hiddenFeatures: readBool(SETTINGS_HIDDEN_FEATURES),
|
||||
energyflowDetails: readBool(SETTINGS_ENERGYFLOW_DETAILS),
|
||||
energyflowCo2: readBool(SETTINGS_ENERGYFLOW_CO2),
|
||||
energyflowPv: readBool(SETTINGS_ENERGYFLOW_PV),
|
||||
energyflowBattery: readBool(SETTINGS_ENERGYFLOW_BATTERY),
|
||||
energyflowLoadpoints: readBool(SETTINGS_ENERGYFLOW_LOADPOINTS),
|
||||
|
|
@ -146,6 +149,7 @@ watch(() => settings.unit, save(SETTINGS_UNIT));
|
|||
watch(() => settings.is12hFormat, saveBool(SETTINGS_12H_FORMAT));
|
||||
watch(() => settings.hiddenFeatures, saveBool(SETTINGS_HIDDEN_FEATURES));
|
||||
watch(() => settings.energyflowDetails, saveBool(SETTINGS_ENERGYFLOW_DETAILS));
|
||||
watch(() => settings.energyflowCo2, saveBool(SETTINGS_ENERGYFLOW_CO2));
|
||||
watch(() => settings.energyflowPv, saveBool(SETTINGS_ENERGYFLOW_PV));
|
||||
watch(() => settings.energyflowBattery, saveBool(SETTINGS_ENERGYFLOW_BATTERY));
|
||||
watch(() => settings.energyflowLoadpoints, saveBool(SETTINGS_ENERGYFLOW_LOADPOINTS));
|
||||
|
|
|
|||
42
tests/energyflow.spec.ts
Normal file
42
tests/energyflow.spec.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { start, stop, baseUrl } from "./evcc";
|
||||
|
||||
const CONFIG = "config-with-tariffs.evcc.yaml";
|
||||
|
||||
test.use({ baseURL: baseUrl() });
|
||||
|
||||
test.beforeAll(async () => {
|
||||
await start(CONFIG);
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await stop();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("/");
|
||||
});
|
||||
|
||||
test("tariff toggle", async ({ page }) => {
|
||||
const energyflow = page.getByTestId("energyflow");
|
||||
await energyflow.click();
|
||||
|
||||
const details = page
|
||||
.getByTestId("energyflow-entry-gridimport")
|
||||
.getByTestId("energyflow-entry-details");
|
||||
|
||||
// check price
|
||||
await expect(details).toHaveText("30.0 öre");
|
||||
|
||||
// toggle to co2
|
||||
await details.click();
|
||||
await expect(details).toHaveText("300 g");
|
||||
|
||||
// reload page and verify persistence
|
||||
await page.reload();
|
||||
await expect(details).toHaveText("300 g");
|
||||
|
||||
// toggle back to price
|
||||
await details.click();
|
||||
await expect(details).toHaveText("30.0 öre");
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue