From 0ffbe0ea782056e75bea292f738d08704fbeda88 Mon Sep 17 00:00:00 2001 From: Michael Geers Date: Mon, 1 Jun 2026 14:52:19 +0200 Subject: [PATCH] Session UI: small improvements (#30389) --- .../js/components/Savings/LiveCommunity.vue | 4 +-- .../components/Sessions/CostHistoryChart.vue | 26 ++++++++++---- assets/js/views/Sessions.vue | 35 ------------------- i18n/de.json | 12 +++---- i18n/en.json | 10 +++--- 5 files changed, 33 insertions(+), 54 deletions(-) diff --git a/assets/js/components/Savings/LiveCommunity.vue b/assets/js/components/Savings/LiveCommunity.vue index 868928f36..57caaef02 100644 --- a/assets/js/components/Savings/LiveCommunity.vue +++ b/assets/js/components/Savings/LiveCommunity.vue @@ -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; diff --git a/assets/js/components/Sessions/CostHistoryChart.vue b/assets/js/components/Sessions/CostHistoryChart.vue index eedb19560..023809735 100644 --- a/assets/js/components/Sessions/CostHistoryChart.vue +++ b/assets/js/components/Sessions/CostHistoryChart.vue @@ -53,8 +53,6 @@ export default defineComponent({ currency: { type: String as PropType, default: CURRENCY.EUR }, colorMappings: { type: Object, default: () => ({ loadpoint: {}, vehicle: {} }) }, deviceColors: { type: Object as PropType, 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, }, diff --git a/assets/js/views/Sessions.vue b/assets/js/views/Sessions.vue index a8fe22f48..4bb87725f 100644 --- a/assets/js/views/Sessions.vue +++ b/assets/js/views/Sessions.vue @@ -92,8 +92,6 @@ :cost-type="activeType" :currency="currency" :period="period" - :suggested-max-avg-cost="suggestedMaxAvgCost" - :suggested-max-cost="suggestedMaxCost" />
@@ -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, 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, 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 diff --git a/i18n/de.json b/i18n/de.json index da04eae7c..b8a8c4d2c 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -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" diff --git a/i18n/en.json b/i18n/en.json index a153c0775..a1c853986 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -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"