From 60417057d0ebcc56e47c79d2e69c0b126a5dfe55 Mon Sep 17 00:00:00 2001 From: Michael Geers Date: Mon, 15 Dec 2025 11:09:32 +0100 Subject: [PATCH] Forecast Chart: dynamic width (#26022) --- assets/js/components/Forecast/Chart.vue | 49 +++++++++++++++++-------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/assets/js/components/Forecast/Chart.vue b/assets/js/components/Forecast/Chart.vue index 8ad7f142d..1ae1a806e 100644 --- a/assets/js/components/Forecast/Chart.vue +++ b/assets/js/components/Forecast/Chart.vue @@ -4,7 +4,14 @@ class="overflow-x-auto overflow-x-md-hidden chart-container border-1" @mouseleave="onMouseLeave" > -
+
@@ -218,6 +225,26 @@ export default defineComponent({ datasets, }; }, + chartDataMaxDate() { + let result: Date | null = null; + for (const dataset of this.chartData.datasets) { + for (const data of dataset.data) { + if (!result || data.x.getTime() > result.getTime()) result = data.x; + } + } + return result; + }, + chartWidth() { + const minWidth = 780; + const maxWidth = 1500; // allow diagram to to grow depending on available data + const realEndDate = this.chartDataMaxDate; + if (!realEndDate) return minWidth; + const maxRange = this.endDate.getTime() - this.startDate.getTime(); + const realRange = realEndDate.getTime() - this.startDate.getTime(); + if (maxRange <= 0 || realRange <= 0) return minWidth; + const scale = realRange / maxRange; + return Math.round(Math.min(maxWidth, Math.max(minWidth, scale * maxWidth))); + }, options() { // eslint-disable-next-line @typescript-eslint/no-this-alias const vThis = this; @@ -466,8 +493,12 @@ export default defineComponent({ } }, yMax(slots: ForecastSlot[] = []): number | undefined { - const value = this.maxValue(slots); - return value ? value * 1.15 : undefined; + const max = this.maxValue(slots); + if (!max) return undefined; + const fixedValues = slots.every((slot) => slot.value === max); + // add space to the top of the scale; shrink fixed-value datasets, they are not interesting and should not dominate the chart + const topSpace = fixedValues ? 3 : 1.15; + return max * topSpace; }, yMaxEntry(entries: TimeseriesEntry[] = [], scale: number = 1): number | undefined { const maxValue = this.maxEntryValue(entries); @@ -516,15 +547,3 @@ export default defineComponent({ }, }); - -