Skip to content

Commit 855e3f9

Browse files
authored
Merge pull request #161 from NREL/develop
release v1.2.1-beta
2 parents c3bdb8f + c25113f commit 855e3f9

14 files changed

Lines changed: 363 additions & 322 deletions

File tree

‎dw_tap‎

Lines changed: 0 additions & 1 deletion
This file was deleted.

‎windwatts-ui/package.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
"terser": "^5.43.1",
4343
"typescript": "~5.8.3",
4444
"typescript-eslint": "^8.35.1",
45-
"vite": "^7.0.4",
46-
"vitest": "^3.0.8"
45+
"vite": "^7.1.12",
46+
"vitest": "^4.0.3"
4747
},
4848
"engines": {
4949
"node": ">=22.14.0"

‎windwatts-ui/src/components/resultPane/AnalysisResults.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import { useOutputUnit } from "../../hooks";
1010

1111
export const AnalysisResults = () => {
1212
const { ensemble, preferredModel } = useContext(SettingsContext);
13-
13+
1414
useOutputUnit(); // auto-switches between kWh and MWh
15-
15+
1616
return (
1717
<Stack spacing={2}>
1818
{/* Top row: either Wind Speed + Resource, or Ensemble Model tiles */}

‎windwatts-ui/src/components/settings/EnsembleSettings.tsx‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,17 @@ export const EnsembleSettings = () => {
1919
}
2020
label="Enable Ensemble Model"
2121
/>
22-
<Typography variant="body2" color="text.secondary" sx={{ mt: 1, fontStyle: "italic" }}>
23-
The WindWatts Ensemble model is an alternative to our default atmospheric model, ERA5. This new model leverages machine learning with data from multiple constituent models with ancillary location and terrain data. While early results show significant performance improvements, this model is still being developed and should be used with care.
22+
<Typography
23+
variant="body2"
24+
color="text.secondary"
25+
sx={{ mt: 1, fontStyle: "italic" }}
26+
>
27+
The WindWatts Ensemble model is an alternative to our default
28+
atmospheric model, ERA5. This new model leverages machine learning
29+
with data from multiple constituent models with ancillary location and
30+
terrain data. While early results show significant performance
31+
improvements, this model is still being developed and should be used
32+
with care.
2433
</Typography>
2534
</Paper>
2635
</>

‎windwatts-ui/src/components/settings/Settings.tsx‎

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
import {
2-
Box,
3-
Modal,
4-
Typography,
5-
IconButton,
6-
} from "@mui/material";
1+
import { Box, Modal, Typography, IconButton } from "@mui/material";
72
import { Close } from "@mui/icons-material";
83
import { UnitsSettings } from "./UnitsSettings";
94
import { useContext, useState } from "react";
@@ -19,8 +14,7 @@ import {
1914
import { EnsembleSettings } from "./EnsembleSettings";
2015

2116
export const Settings = () => {
22-
const { settingsOpen, toggleSettings } =
23-
useContext(SettingsContext);
17+
const { settingsOpen, toggleSettings } = useContext(SettingsContext);
2418
const [hasScrolled, setHasScrolled] = useState(false);
2519

2620
const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {

‎windwatts-ui/src/components/settings/UnitsSettings.tsx‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import { Box, Typography, ToggleButton } from "@mui/material";
22
import { useContext } from "react";
3+
import { SettingsContext } from "../../providers/SettingsContext";
34
import { UnitsContext } from "../../providers/UnitsContext";
45
import { SettingToggleButtonGroup } from "./SettingToggleButtonGroup";
56

67
export function UnitsSettings() {
8+
const { setWindspeedUnit } = useContext(SettingsContext);
79
const { units, updateUnit } = useContext(UnitsContext);
810

911
const handleWindspeedChange = (
1012
_: React.MouseEvent<HTMLElement>,
1113
newWindspeedUnit: string
1214
) => {
1315
if (newWindspeedUnit !== null) {
16+
// Update both: SettingsContext (for URL) and UnitsContext (for components)
17+
setWindspeedUnit(newWindspeedUnit);
1418
updateUnit("windspeed", newWindspeedUnit);
1519
}
1620
};

‎windwatts-ui/src/hooks/useOutputUnit.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ export const useOutputUnit = () => {
2020

2121
let shouldUseMWh = false;
2222

23-
if (ensemble) { // ensemble mode - auto-convert if either output >= 10,000
23+
if (ensemble) {
24+
// ensemble mode - auto-convert if either output >= 10,000
2425
const ensembleProduction = Number(ensembleData?.energy_production || 0);
2526
shouldUseMWh = ensembleProduction >= 10000 || prodAvg >= 10000;
26-
} else { // non-ensemble mode - auto-convert if average output >= 10,000
27+
} else {
28+
// non-ensemble mode - auto-convert if average output >= 10,000
2729
shouldUseMWh = prodAvg >= 10000;
2830
}
2931

‎windwatts-ui/src/providers/AppProviders.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ interface AppProvidersProps {
88

99
export const AppProviders: React.FC<AppProvidersProps> = ({ children }) => {
1010
return (
11-
<SettingsProvider>
12-
<UnitsProvider>{children}</UnitsProvider>
13-
</SettingsProvider>
11+
<UnitsProvider>
12+
<SettingsProvider>{children}</SettingsProvider>
13+
</UnitsProvider>
1414
);
1515
};

‎windwatts-ui/src/providers/SettingsContext.tsx‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface StoredSettings {
1616
preferredModel: DataModel;
1717
ensemble: boolean;
1818
lossAssumptionFactor: number;
19+
windspeedUnit: string;
1920
}
2021

2122
export interface Settings extends StoredSettings {
@@ -35,6 +36,7 @@ export interface Settings extends StoredSettings {
3536
setEnsemble: (ensemble: boolean) => void;
3637
setLossAssumptionFactor: (factor: number) => void;
3738
setLossAssumptionPercent: (percent: number) => void;
39+
setWindspeedUnit: (unit: string) => void;
3840
}
3941

4042
export const defaultValues: StoredSettings = {
@@ -47,6 +49,7 @@ export const defaultValues: StoredSettings = {
4749
preferredModel: "era5",
4850
ensemble: false,
4951
lossAssumptionFactor: 1.0, // 1.0 = 0% loss, 0.83 = 17% loss defaulted to 0% loss
52+
windspeedUnit: "mph",
5053
};
5154

5255
export const SettingsContext = createContext<Settings>({
@@ -62,4 +65,5 @@ export const SettingsContext = createContext<Settings>({
6265
setEnsemble: () => {},
6366
setLossAssumptionFactor: () => {},
6467
setLossAssumptionPercent: () => {},
68+
setWindspeedUnit: () => {},
6569
});

‎windwatts-ui/src/providers/SettingsProvider.tsx‎

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1-
import { useState, useMemo, useCallback, useEffect } from "react";
1+
import {
2+
useState,
3+
useMemo,
4+
useCallback,
5+
useEffect,
6+
useContext,
7+
useRef,
8+
} from "react";
29
import {
310
SettingsContext,
411
defaultValues,
512
CurrentPosition,
613
StoredSettings,
714
} from "./SettingsContext";
15+
import { UnitsContext } from "./UnitsContext";
816
import { DataModel } from "../types";
917
import { percentToFactor } from "../utils";
1018
import {
@@ -15,8 +23,13 @@ import {
1523
} from "../utils/urlParams";
1624

1725
export function SettingsProvider({ children }: { children: React.ReactNode }) {
26+
const { updateUnit } = useContext(UnitsContext);
27+
28+
// Parse URL params once and cache the result
29+
const urlParamsRef = useRef(parseUrlParams());
30+
1831
const [settings, setSettings] = useState<StoredSettings>(() => {
19-
const urlParams = parseUrlParams();
32+
const urlParams = urlParamsRef.current;
2033

2134
if (hasLaunchParams(urlParams)) {
2235
return {
@@ -34,6 +47,8 @@ export function SettingsProvider({ children }: { children: React.ReactNode }) {
3447
urlParams.lossAssumption !== undefined
3548
? percentToFactor(urlParams.lossAssumption)
3649
: defaultValues.lossAssumptionFactor,
50+
windspeedUnit:
51+
urlParams.windspeedUnit ?? URL_PARAM_DEFAULTS.windspeedUnit,
3752
};
3853
}
3954

@@ -43,21 +58,29 @@ export function SettingsProvider({ children }: { children: React.ReactNode }) {
4358
};
4459
});
4560

61+
useEffect(() => {
62+
const urlParams = urlParamsRef.current;
63+
if (urlParams.windspeedUnit) {
64+
updateUnit("windspeed", urlParams.windspeedUnit);
65+
}
66+
}, [updateUnit]);
67+
4668
useEffect(() => {
4769
if (!settings.currentPosition) {
4870
return;
4971
}
5072

5173
const url = buildUrlFromSettings({
5274
currentPosition: settings.currentPosition,
53-
zoom: settings.zoom,
5475
hubHeight: settings.hubHeight,
5576
powerCurve: settings.powerCurve,
5677
preferredModel: settings.preferredModel,
5778
ensemble: settings.ensemble,
5879
lossAssumptionPercent: Math.round(
5980
(1 - settings.lossAssumptionFactor) * 100
6081
),
82+
zoom: settings.zoom,
83+
windspeedUnit: settings.windspeedUnit,
6184
});
6285

6386
if (url !== "/") {
@@ -71,6 +94,7 @@ export function SettingsProvider({ children }: { children: React.ReactNode }) {
7194
settings.preferredModel,
7295
settings.ensemble,
7396
settings.lossAssumptionFactor,
97+
settings.windspeedUnit,
7498
]);
7599

76100
const setCurrentPosition = useCallback(
@@ -137,6 +161,13 @@ export function SettingsProvider({ children }: { children: React.ReactNode }) {
137161
[setLossAssumptionFactor]
138162
);
139163

164+
const setWindspeedUnit = useCallback(
165+
(unit: string) => {
166+
setSettings((current) => ({ ...current, windspeedUnit: unit }));
167+
},
168+
[setSettings]
169+
);
170+
140171
// Toggle functions that update the settings directly
141172
const toggleSettings = useCallback(() => {
142173
setSettings((current) => ({
@@ -181,6 +212,8 @@ export function SettingsProvider({ children }: { children: React.ReactNode }) {
181212
),
182213
setLossAssumptionFactor,
183214
setLossAssumptionPercent,
215+
windspeedUnit: settings.windspeedUnit,
216+
setWindspeedUnit,
184217
}),
185218
[
186219
settings.settingsOpen,
@@ -192,6 +225,7 @@ export function SettingsProvider({ children }: { children: React.ReactNode }) {
192225
settings.preferredModel,
193226
settings.ensemble,
194227
settings.lossAssumptionFactor,
228+
settings.windspeedUnit,
195229
toggleSettings,
196230
toggleResults,
197231
setCurrentPosition,
@@ -202,6 +236,7 @@ export function SettingsProvider({ children }: { children: React.ReactNode }) {
202236
setEnsemble,
203237
setLossAssumptionFactor,
204238
setLossAssumptionPercent,
239+
setWindspeedUnit,
205240
]
206241
);
207242

0 commit comments

Comments
 (0)