diff --git a/apps/quartz-app/.env.example b/apps/quartz-app/.env.example new file mode 100644 index 00000000..649aebf8 --- /dev/null +++ b/apps/quartz-app/.env.example @@ -0,0 +1,3 @@ +# history window config for issue #655 +NEXT_PUBLIC_HISTORY_START_TYPE=rolling +NEXT_PUBLIC_HISTORY_START_OFFSET_HOURS=48 \ No newline at end of file diff --git a/apps/quartz-app/src/data/queries.ts b/apps/quartz-app/src/data/queries.ts index 87d80499..7f6c5f73 100644 --- a/apps/quartz-app/src/data/queries.ts +++ b/apps/quartz-app/src/data/queries.ts @@ -2,6 +2,7 @@ import { QueryFunction, useQuery } from "@tanstack/react-query"; import { components, operations, paths } from "../types/schema"; import client from "./apiClient"; +import { getHistoryStartISO } from "../helpers/historyWindow"; // paths export const GET_REGIONS = "/{source}/regions"; @@ -46,6 +47,7 @@ export const getGenerationQuery = ( region: operations["get_historic_timeseries_route__source___region__generation_get"]["parameters"]["path"]["region"] ): QueryFunction => { return async ({ meta, signal }) => { + const startISO = getHistoryStartISO(); const { accessToken } = await fetch("/api/token").then((res) => res.json()); const { data, error } = await client.GET(GET_GENERATION, { params: { @@ -56,6 +58,9 @@ export const getGenerationQuery = ( query: { ...sharedQueryParams, resample_minutes: 15, + // start of history window for UI + // @ts-ignore – schema typing may not include this yet + start_datetime_utc: startISO, }, }, // Add bearer token to headers @@ -78,6 +83,7 @@ export const getForecastQuery = ( forecast_horizon_minutes?: number ): QueryFunction => { return async ({ meta, signal }) => { + const startISO = getHistoryStartISO(); const { accessToken } = await fetch("/api/token").then((res) => res.json()); const { data, error } = await client.GET(GET_FORECAST, { params: { @@ -90,6 +96,9 @@ export const getForecastQuery = ( forecast_horizon, forecast_horizon_minutes: forecast_horizon === "horizon" ? forecast_horizon_minutes : null, + // start of history window for UI + // @ts-ignore – schema typing may not include this yet + start_datetime_utc: startISO, }, }, // Add bearer token to headers diff --git a/apps/quartz-app/src/helpers/historyWindow.ts b/apps/quartz-app/src/helpers/historyWindow.ts new file mode 100644 index 00000000..24021e6f --- /dev/null +++ b/apps/quartz-app/src/helpers/historyWindow.ts @@ -0,0 +1,41 @@ +export type HistoryStartType = "fixed" | "rolling"; + +/** + * Returns the start Date for the UI history window. + * - rolling: now - OFFSET hours + * - fixed: midnight (UTC) N days ago, where N = round(OFFSET/24), min 1 + */ +export function getHistoryStart(now = new Date()): Date { + const rawType = ( + process.env.NEXT_PUBLIC_HISTORY_START_TYPE ?? "rolling" + ).toLowerCase(); + const type: HistoryStartType = rawType === "fixed" ? "fixed" : "rolling"; + + const offsetStr = process.env.NEXT_PUBLIC_HISTORY_START_OFFSET_HOURS ?? "48"; + const offsetHours = Number(offsetStr); + const safeOffset = + Number.isFinite(offsetHours) && offsetHours > 0 ? offsetHours : 48; + + if (type === "fixed") { + const days = Math.max(1, Math.round(safeOffset / 24)); + const midnightTodayUTC = new Date( + Date.UTC( + now.getUTCFullYear(), + now.getUTCMonth(), + now.getUTCDate(), + 0, + 0, + 0, + 0 + ) + ); + midnightTodayUTC.setUTCDate(midnightTodayUTC.getUTCDate() - days); + return midnightTodayUTC; + } + + // rolling + return new Date(now.getTime() - safeOffset * 3600 * 1000); +} + +export const getHistoryStartISO = (now?: Date) => + getHistoryStart(now).toISOString();