Session UI: small improvements (#30389)

This commit is contained in:
Michael Geers 2026-06-01 14:52:19 +02:00 • committed by GitHub
parent 5409ed21a8
commit 0ffbe0ea78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 33 additions and 54 deletions

View file

@ -59,10 +59,10 @@ export default defineComponent({
},
computed: {
totalClients() {
return this.result.totalClients;
return this.fmtNumber(this.result.totalClients || 0, 0);
},
activeClients() {
return this.result.activeClients;
return this.fmtNumber(this.result.activeClients || 0, 0);
},
chargePower() {
const { chargePower = 0 } = this.result;

View file

@ -53,8 +53,6 @@ export default defineComponent({
currency: { type: String as PropType<CURRENCY>, default: CURRENCY.EUR },
colorMappings: { type: Object, default: () => ({ loadpoint: {}, vehicle: {} }) },
deviceColors: { type: Object as PropType<DeviceColors>, default: () => ({}) },
suggestedMaxAvgCost: { type: Number, default: 0 },
suggestedMaxCost: { type: Number, default: 0 },
},
computed: {
firstDay() {
@ -179,7 +177,9 @@ export default defineComponent({
this.costType === TYPES.PRICE
? this.$t("sessions.avgPrice")
: this.$t("sessions.co2"),
data: Object.values(result).map((index) => index.avgCost),
data: Object.values(result).map((index) =>
index.totalKWh > 0 ? index.avgCost : null
),
yAxisID: "y1",
tension: 0.25,
pointRadius: 0,
@ -231,6 +231,22 @@ export default defineComponent({
};
});
},
maxBarCost() {
if (this.costType !== TYPES.PRICE) return 0;
const barDatasets = this.chartData.datasets.filter(
(d: any) => (d as any).type === "bar"
);
const labelCount = this.chartData.labels?.length || 0;
let max = 0;
for (let i = 0; i < labelCount; i++) {
const total = barDatasets.reduce(
(sum: number, d: any) => sum + ((d.data[i] as number) || 0),
0
);
if (total > max) max = total;
}
return max;
},
options() {
// capture vue component this to be used in chartjs callbacks
// eslint-disable-next-line @typescript-eslint/no-this-alias
@ -331,7 +347,7 @@ export default defineComponent({
ticks: {
callback: (value: number) => {
if (this.costType === TYPES.PRICE) {
const showDecimals = this.suggestedMaxCost < 4;
const showDecimals = this.maxBarCost < 4;
return this.fmtMoney(value, this.currency, showDecimals, true);
} else {
return this.fmtNumber(value / 1e3, 0);
@ -340,13 +356,11 @@ export default defineComponent({
color: colors.muted,
maxTicksLimit: 6,
},
suggestedMax: this.suggestedMaxCost,
suggestedMin: 0,
},
y1: {
position: "left",
border: { display: false },
suggestedMax: this.suggestedMaxAvgCost,
grid: {
drawOnChartArea: false,
},

View file

@ -92,8 +92,6 @@
:cost-type="activeType"
:currency="currency"
:period="period"
:suggested-max-avg-cost="suggestedMaxAvgCost"
:suggested-max-cost="suggestedMaxCost"
/>
<div v-if="showExtraCharts" class="row align-items-start">
<div class="col-12 col-lg-6 mb-5">
@ -640,29 +638,6 @@ export default defineComponent({
? this.suggestedMaxAvgPrice
: this.suggestedMaxAvgCo2;
},
suggestedMaxCo2() {
// returns the 98th percentile of total co2 emissions by time period
const sessionsWithCo2 = this.sessions.filter((s) => s.co2PerKWh !== null);
const co2Map = sessionsWithCo2.reduce((acc: Record<string, number>, s) => {
const key = this.dateToPeriodKey(new Date(s.created));
acc[key] = (acc[key] || 0) + (s.co2PerKWh ?? 0) * s.chargedEnergy;
return acc;
}, {});
return Math.max(this.percentile(Object.values(co2Map), 98) ?? 0, 5); // 5kg default
},
suggestedMaxPrice() {
// returns the 98th percentile of total price by time period
const sessionsWithPrice = this.sessions.filter((s) => s.price !== null);
const priceMap = sessionsWithPrice.reduce((acc: Record<string, number>, s) => {
const key = this.dateToPeriodKey(new Date(s.created));
acc[key] = (acc[key] || 0) + (s.price || 0);
return acc;
}, {});
return Math.max(this.percentile(Object.values(priceMap), 98) ?? 0, 1); // 1 CURRENCY default
},
suggestedMaxCost() {
return this.activeType === TYPES.PRICE ? this.suggestedMaxPrice : this.suggestedMaxCo2;
},
},
watch: {
offline() {
@ -691,16 +666,6 @@ export default defineComponent({
}
this.$router.push({ query: { ...this.$route.query, period, month, year } });
},
dateToPeriodKey(date: Date) {
const options: Intl.DateTimeFormatOptions = {
year: "numeric",
month: "numeric",
day: "numeric",
};
if (this.period === PERIODS.YEAR) options.day = undefined;
if (this.period === PERIODS.TOTAL) options.month = undefined;
return date.toLocaleDateString(undefined, options);
},
async loadSessions() {
const response = await api.get("sessions");
// ensure sessions are sorted by created date

View file

@ -881,7 +881,7 @@
"greenShareSub2": "PV und Speicher",
"power": "Ladeleistung",
"powerSub1": "{activeClients} von {totalClients} Nutzern",
"powerSub2": "laden…",
"powerSub2": "laden gerade.",
"tabTitle": "Live-Community"
},
"savings": {
@ -1412,7 +1412,7 @@
"meterstart": "Anfangszählerstand",
"meterstop": "Endzählerstand",
"odometer": "Kilometerstand",
"price": "Preis",
"price": "Kosten",
"started": "Startzeit",
"title": "Ladevorgang"
},
@ -1451,7 +1451,7 @@
"meterstart": "Anfangszählerstand (kWh)",
"meterstop": "Endzählerstand (kWh)",
"odometer": "Kilometerstand (km)",
"price": "Preis",
"price": "Kosten",
"priceperkwh": "Preis/kWh",
"solarpercentage": "Sonne (%)",
"vehicle": "Fahrzeug"
@ -1468,7 +1468,7 @@
"group": {
"co2": "Emissionen",
"grid": "Netz",
"price": "Preis",
"price": "Kosten",
"self": "Sonne"
},
"groupBy": {
@ -1491,10 +1491,10 @@
"showIndividualEntries": "Einzelne Ladevorgänge anzeigen",
"solar": "Sonne",
"title": "Ladevorgänge",
"total": "Insgesamt",
"total": "Gesamt",
"type": {
"co2": "CO₂",
"price": "Preis",
"price": "Kosten",
"solar": "Sonne"
},
"vehicle": "Fahrzeug"

View file

@ -881,7 +881,7 @@
"greenShareSub2": "solar, and battery storage",
"power": "Charging power",
"powerSub1": "{activeClients} of {totalClients} participants",
"powerSub2": "charging…",
"powerSub2": "are charging.",
"tabTitle": "Live community"
},
"savings": {
@ -1412,7 +1412,7 @@
"meterstart": "Meter start",
"meterstop": "Meter stop",
"odometer": "Mileage",
"price": "Price",
"price": "Cost",
"started": "Started",
"title": "Charging Session"
},
@ -1451,7 +1451,7 @@
"meterstart": "Meter start (kWh)",
"meterstop": "Meter stop (kWh)",
"odometer": "Mileage (km)",
"price": "Price",
"price": "Cost",
"priceperkwh": "Price/kWh",
"solarpercentage": "Solar (%)",
"vehicle": "Vehicle"
@ -1468,7 +1468,7 @@
"group": {
"co2": "Emissions",
"grid": "Grid",
"price": "Price",
"price": "Cost",
"self": "Solar"
},
"groupBy": {
@ -1494,7 +1494,7 @@
"total": "Total",
"type": {
"co2": "CO₂",
"price": "Price",
"price": "Cost",
"solar": "Solar"
},
"vehicle": "Vehicle"