UI: adaptive power digits (#13619)
This commit is contained in:
parent
e8dc709f98
commit
a6056e27d7
10 changed files with 74 additions and 35 deletions
|
|
@ -18,7 +18,8 @@
|
|||
:pvProduction="pvProduction"
|
||||
:homePower="homePower"
|
||||
:batterySoc="batterySoc"
|
||||
:powerInKw="powerInKw"
|
||||
:powerInKw="visualizationFormat.kw"
|
||||
:powerDigits="visualizationFormat.digits"
|
||||
:vehicleIcons="vehicleIcons"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -74,14 +75,16 @@
|
|||
icon="sun"
|
||||
:power="pvProduction"
|
||||
:powerTooltip="pvTooltip"
|
||||
:powerInKw="powerInKw"
|
||||
:powerInKw="entryFormat.kw"
|
||||
:powerDigits="entryFormat.digits"
|
||||
/>
|
||||
<EnergyflowEntry
|
||||
v-if="batteryConfigured"
|
||||
:name="batteryDischargeLabel"
|
||||
icon="battery"
|
||||
:power="batteryDischarge"
|
||||
:powerInKw="powerInKw"
|
||||
:powerInKw="entryFormat.kw"
|
||||
:powerDigits="entryFormat.digits"
|
||||
:soc="batterySoc"
|
||||
:details="batterySoc"
|
||||
:detailsFmt="batteryFmt"
|
||||
|
|
@ -93,7 +96,8 @@
|
|||
:name="$t('main.energyflow.gridImport')"
|
||||
icon="powersupply"
|
||||
:power="gridImport"
|
||||
:powerInKw="powerInKw"
|
||||
:powerInKw="entryFormat.kw"
|
||||
:powerDigits="entryFormat.digits"
|
||||
:details="detailsValue(tariffGrid, tariffCo2)"
|
||||
:detailsFmt="detailsFmt"
|
||||
:detailsTooltip="detailsTooltip(tariffGrid, tariffCo2)"
|
||||
|
|
@ -115,7 +119,8 @@
|
|||
:name="$t('main.energyflow.homePower')"
|
||||
icon="home"
|
||||
:power="homePower"
|
||||
:powerInKw="powerInKw"
|
||||
:powerInKw="entryFormat.kw"
|
||||
:powerDigits="entryFormat.digits"
|
||||
:details="detailsValue(tariffPriceHome, tariffCo2Home)"
|
||||
:detailsFmt="detailsFmt"
|
||||
:detailsTooltip="detailsTooltip(tariffPriceHome, tariffCo2Home)"
|
||||
|
|
@ -129,7 +134,8 @@
|
|||
icon="vehicle"
|
||||
:vehicleIcons="vehicleIcons"
|
||||
:power="loadpointsPower"
|
||||
:powerInKw="powerInKw"
|
||||
:powerInKw="entryFormat.kw"
|
||||
:powerDigits="entryFormat.digits"
|
||||
:details="
|
||||
activeLoadpointsCount
|
||||
? detailsValue(tariffPriceLoadpoints, tariffCo2Loadpoints)
|
||||
|
|
@ -145,7 +151,8 @@
|
|||
:name="batteryChargeLabel"
|
||||
icon="battery"
|
||||
:power="batteryCharge"
|
||||
:powerInKw="powerInKw"
|
||||
:powerInKw="entryFormat.kw"
|
||||
:powerDigits="entryFormat.digits"
|
||||
:soc="batterySoc"
|
||||
:details="batterySoc"
|
||||
:detailsFmt="batteryFmt"
|
||||
|
|
@ -156,7 +163,8 @@
|
|||
:name="$t('main.energyflow.pvExport')"
|
||||
icon="powersupply"
|
||||
:power="pvExport"
|
||||
:powerInKw="powerInKw"
|
||||
:powerInKw="entryFormat.kw"
|
||||
:powerDigits="entryFormat.digits"
|
||||
:details="detailsValue(-tariffFeedIn)"
|
||||
:detailsFmt="detailsFmt"
|
||||
:detailsTooltip="detailsTooltip(-tariffFeedIn)"
|
||||
|
|
@ -269,8 +277,25 @@ export default {
|
|||
pvExport: function () {
|
||||
return Math.max(0, this.gridPower * -1);
|
||||
},
|
||||
powerInKw: function () {
|
||||
return Math.max(this.gridImport, this.selfPv, this.selfBattery, this.pvExport) >= 1000;
|
||||
visualizationFormat: function () {
|
||||
const max = Math.max(this.gridImport, this.selfPv, this.selfBattery, this.pvExport);
|
||||
const kw = this.inKw(max);
|
||||
const digits = kw ? this.digitsKw(max) : 0;
|
||||
return { kw, digits };
|
||||
},
|
||||
entryFormat: function () {
|
||||
const max = Math.max(
|
||||
this.gridImport,
|
||||
this.pvProduction,
|
||||
this.batteryDischarge,
|
||||
this.homePower,
|
||||
this.loadpointsPower,
|
||||
this.pvExport,
|
||||
this.batteryCharge
|
||||
);
|
||||
const kw = this.inKw(max);
|
||||
const digits = kw ? this.digitsKw(max) : 0;
|
||||
return { kw, digits };
|
||||
},
|
||||
inPower: function () {
|
||||
return this.gridImport + this.pvProduction + this.batteryDischarge;
|
||||
|
|
@ -285,7 +310,9 @@ export default {
|
|||
if (!Array.isArray(this.pv) || this.pv.length <= 1) {
|
||||
return;
|
||||
}
|
||||
return this.pv.map(({ power }) => this.fmtKw(power, this.powerInKw));
|
||||
return this.pv.map(({ power }) =>
|
||||
this.fmtKw(power, this.entryFormat.kw, true, this.entryFormat.digits)
|
||||
);
|
||||
},
|
||||
batteryFmt() {
|
||||
return (soc) => `${Math.round(soc)}%`;
|
||||
|
|
@ -328,7 +355,7 @@ export default {
|
|||
return this.fmtPricePerKWh(value, this.currency, true);
|
||||
},
|
||||
kw: function (watt) {
|
||||
return this.fmtKw(watt, this.powerInKw);
|
||||
return this.fmtKw(watt, this.entryFormat.kw, true, this.entryFormat.digits);
|
||||
},
|
||||
toggleDetails: function () {
|
||||
this.updateHeight();
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ export default {
|
|||
power: { type: Number },
|
||||
powerTooltip: { type: Array },
|
||||
powerInKw: { type: Boolean },
|
||||
powerDigits: { type: Number },
|
||||
soc: { type: Number },
|
||||
details: { type: Number },
|
||||
detailsFmt: { type: Function },
|
||||
|
|
@ -86,6 +87,12 @@ export default {
|
|||
this.$refs.powerNumber.forceUpdate();
|
||||
}
|
||||
},
|
||||
powerDigits(newVal, oldVal) {
|
||||
// force update if digits change but not the value
|
||||
if (newVal !== oldVal) {
|
||||
this.$refs.powerNumber.forceUpdate();
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted: function () {
|
||||
this.updatePowerTooltip();
|
||||
|
|
@ -93,7 +100,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
kw: function (watt) {
|
||||
return this.fmtKw(watt, this.powerInKw);
|
||||
return this.fmtKw(watt, this.powerInKw, true, this.powerDigits);
|
||||
},
|
||||
updatePowerTooltip() {
|
||||
this.powerTooltipInstance = this.updateTooltip(
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ export default {
|
|||
homePower: { type: Number, default: 0 },
|
||||
batterySoc: { type: Number, default: 0 },
|
||||
powerInKw: { type: Boolean, default: false },
|
||||
powerDigits: { type: Number, default: 0 },
|
||||
},
|
||||
data: function () {
|
||||
return { width: 0 };
|
||||
|
|
@ -171,7 +172,7 @@ export default {
|
|||
return "";
|
||||
}
|
||||
const withUnit = this.enoughSpaceForUnit(watt);
|
||||
return this.fmtKw(watt, this.powerInKw, withUnit);
|
||||
return this.fmtKw(watt, this.powerInKw, withUnit, this.powerDigits);
|
||||
},
|
||||
powerLabelAvailableSpace(power) {
|
||||
if (this.totalAdjusted === 0) return 0;
|
||||
|
|
@ -182,7 +183,7 @@ export default {
|
|||
return this.powerLabelAvailableSpace(power) > 40;
|
||||
},
|
||||
enoughSpaceForUnit(power) {
|
||||
return this.powerLabelAvailableSpace(power) > 60;
|
||||
return this.powerLabelAvailableSpace(power) > 80;
|
||||
},
|
||||
hideLabelIcon(power, minWidth = 32) {
|
||||
if (this.totalAdjusted === 0) return true;
|
||||
|
|
|
|||
|
|
@ -315,12 +315,10 @@ export default {
|
|||
api.delete(this.apiPath("vehicle"));
|
||||
},
|
||||
fmtPower(value) {
|
||||
const inKw = value == 0 || value >= 1000;
|
||||
return this.fmtKw(value, inKw);
|
||||
return this.fmtKw(value, this.inKw(value));
|
||||
},
|
||||
fmtEnergy(value) {
|
||||
const inKw = value == 0 || value >= 1000;
|
||||
return this.fmtKWh(value, inKw);
|
||||
return this.fmtKWh(value, this.inKw(value));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ export default {
|
|||
return this.maxPowerPhases(this.phasesConfigured);
|
||||
}
|
||||
}
|
||||
return this.fmtKw(this.maxCurrent * V * this.phasesActive);
|
||||
return this.fmtKw(this.maxCurrent * V * this.phasesActive, true, true, 1);
|
||||
},
|
||||
minPower: function () {
|
||||
if (this.chargerPhases1p3p) {
|
||||
|
|
@ -231,7 +231,7 @@ export default {
|
|||
return this.minPowerPhases(this.phasesConfigured);
|
||||
}
|
||||
}
|
||||
return this.fmtKw(this.minCurrent * V * this.phasesActive);
|
||||
return this.fmtKw(this.minCurrent * V * this.phasesActive, true, true, 1);
|
||||
},
|
||||
minCurrentOptions: function () {
|
||||
const opt1 = [...range(Math.floor(this.maxCurrent), 1), 0.5, 0.25, 0.125];
|
||||
|
|
@ -279,10 +279,10 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
maxPowerPhases: function (phases) {
|
||||
return this.fmtKw(this.maxCurrent * V * phases);
|
||||
return this.fmtKw(this.maxCurrent * V * phases, true, true, 1);
|
||||
},
|
||||
minPowerPhases: function (phases) {
|
||||
return this.fmtKw(this.minCurrent * V * phases);
|
||||
return this.fmtKw(this.minCurrent * V * phases, true, true, 1);
|
||||
},
|
||||
formId: function (name) {
|
||||
return `loadpoint_${this.id}_${name}`;
|
||||
|
|
|
|||
|
|
@ -33,9 +33,15 @@ export default {
|
|||
val = Math.abs(val);
|
||||
return val >= this.fmtLimit ? this.round(val / 1e3, this.fmtDigits) : this.round(val, 0);
|
||||
},
|
||||
inKw: function (watt) {
|
||||
return watt === 0 || watt >= 1000;
|
||||
},
|
||||
digitsKw: function (watt) {
|
||||
return watt < 10000 ? 2 : 1;
|
||||
},
|
||||
fmtKw: function (watt = 0, kw = true, withUnit = true, digits) {
|
||||
if (digits === undefined) {
|
||||
digits = kw ? 1 : 0;
|
||||
digits = kw ? this.digitsKw(watt) : 0;
|
||||
}
|
||||
const value = kw ? watt / 1000 : watt;
|
||||
let unit = "";
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@ const fmt = mount({
|
|||
|
||||
describe("fmtkW", () => {
|
||||
test("should format kW and W", () => {
|
||||
expect(fmt.fmtKw(0, true)).eq("0,0 kW");
|
||||
expect(fmt.fmtKw(1200, true)).eq("1,2 kW");
|
||||
expect(fmt.fmtKw(0, true)).eq("0,00 kW");
|
||||
expect(fmt.fmtKw(1200, true)).eq("1,20 kW");
|
||||
expect(fmt.fmtKw(0, false)).eq("0 W");
|
||||
expect(fmt.fmtKw(1200, false)).eq("1.200 W");
|
||||
});
|
||||
test("should format without unit", () => {
|
||||
expect(fmt.fmtKw(0, true, false)).eq("0,0");
|
||||
expect(fmt.fmtKw(1200, true, false)).eq("1,2");
|
||||
expect(fmt.fmtKw(0, true, false)).eq("0,00");
|
||||
expect(fmt.fmtKw(1200, true, false)).eq("1,20");
|
||||
expect(fmt.fmtKw(0, false, false)).eq("0");
|
||||
expect(fmt.fmtKw(1200, false, false)).eq("1.200");
|
||||
});
|
||||
|
|
@ -32,8 +32,8 @@ describe("fmtkW", () => {
|
|||
|
||||
describe("fmtKWh", () => {
|
||||
test("should format with units", () => {
|
||||
expect(fmt.fmtKWh(1200)).eq("1,2 kWh");
|
||||
expect(fmt.fmtKWh(1200, true)).eq("1,2 kWh");
|
||||
expect(fmt.fmtKWh(1200)).eq("1,20 kWh");
|
||||
expect(fmt.fmtKWh(1200, true)).eq("1,20 kWh");
|
||||
expect(fmt.fmtKWh(1200, false)).eq("1.200 Wh");
|
||||
expect(fmt.fmtKWh(1200, false, false)).eq("1.200");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ export default {
|
|||
unit: "kWh",
|
||||
total: this.chargedEnergy,
|
||||
value: (session) => session.chargedEnergy,
|
||||
format: (value) => this.fmtKWh(value * 1e3, true, false),
|
||||
format: (value) => this.fmtKWh(value * 1e3, true, false, 2),
|
||||
},
|
||||
{
|
||||
name: "solar",
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ test.describe("main screen", async () => {
|
|||
test("visualization", async ({ page }) => {
|
||||
const locator = page.getByTestId("visualization");
|
||||
await expect(locator).toBeVisible();
|
||||
await expect(locator).toContainText("1.0 kW");
|
||||
await expect(locator).toContainText("1.00 kW");
|
||||
});
|
||||
|
||||
test("one loadpoint", async ({ page }) => {
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ test.describe("meters", async () => {
|
|||
await expect(meterModal.getByRole("button", { name: "Validate & save" })).toBeVisible();
|
||||
await meterModal.getByRole("link", { name: "validate" }).click();
|
||||
await expect(meterModal.getByText("SoC: 75.0%")).toBeVisible();
|
||||
await expect(meterModal.getByText("Power: -2.5 kW")).toBeVisible();
|
||||
await expect(meterModal.getByText("Power: -2.50 kW")).toBeVisible();
|
||||
await meterModal.getByRole("button", { name: "Save" }).click();
|
||||
await expect(page.getByTestId("battery")).toBeVisible(1);
|
||||
await expect(page.getByTestId("battery")).toContainText("openems");
|
||||
|
|
@ -190,14 +190,14 @@ test.describe("meters", async () => {
|
|||
await expect(page.getByTestId("battery")).toBeVisible(1);
|
||||
await expect(page.getByTestId("battery")).toContainText("openems");
|
||||
await expect(page.getByTestId("battery").getByText("SoC: 75.0%")).toBeVisible();
|
||||
await expect(page.getByTestId("battery").getByText("Power: -2.5 kW")).toBeVisible();
|
||||
await expect(page.getByTestId("battery").getByText("Power: -2.50 kW")).toBeVisible();
|
||||
await expect(page.getByTestId("battery").getByText("Capacity: 20.0 kWh")).toBeVisible();
|
||||
|
||||
// restart and check in main ui
|
||||
await restart(CONFIG_EMPTY);
|
||||
await page.goto("/");
|
||||
await page.getByTestId("visualization").click();
|
||||
await expect(page.getByTestId("energyflow")).toContainText("Battery charging75%2.5 kW");
|
||||
await expect(page.getByTestId("energyflow")).toContainText("Battery charging75%2.50 kW");
|
||||
|
||||
// delete #1
|
||||
await page.goto("/#/config");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue