Skip to content

Commit fd563e1

Browse files
committed
dashboard: use search param for network, fixes #181
1 parent 0e88b5b commit fd563e1

File tree

4 files changed

+46
-28
lines changed

4 files changed

+46
-28
lines changed

dashboard/src/App.tsx

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { CssBaseline } from '@mui/material';
2+
import { HashRouter as Router } from 'react-router-dom';
23
import CustomThemeProvider from './components/CustomThemeProvider';
34
import Main from './components/Main';
45
import { NetworkContextProvider } from './contexts/NetworkContext';
@@ -9,9 +10,11 @@ function App() {
910
<SettingsContextProvider>
1011
<CustomThemeProvider>
1112
<CssBaseline />
12-
<NetworkContextProvider>
13-
<Main />
14-
</NetworkContextProvider>
13+
<Router>
14+
<NetworkContextProvider>
15+
<Main />
16+
</NetworkContextProvider>
17+
</Router>
1518
</CustomThemeProvider>
1619
</SettingsContextProvider>
1720
);

dashboard/src/components/Main.tsx

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,34 @@
11
import { GitHub } from '@mui/icons-material';
22
import { AppBar, Box, Button, Hidden, IconButton, Toolbar, Typography } from '@mui/material';
3-
import { Route, HashRouter as Router, Switch, NavLink } from 'react-router-dom';
3+
import { NavLink, Route, Switch } from 'react-router-dom';
44
import useChainHeartbeats from '../hooks/useChainHeartbeats';
55
import useHeartbeats from '../hooks/useHeartbeats';
66
import useLatestRelease from '../hooks/useLatestRelease';
77
import WormholeStatsIcon from '../icons/WormholeStatsIcon';
88
import Alerts from './Alerts';
99
import Home from './Home';
10+
import Metrics from './Metrics';
1011
import NetworkSelector from './NetworkSelector';
1112
import Settings from './Settings';
12-
import Metrics from './Metrics';
13+
14+
function NavButton(props: any) {
15+
// fix for Invalid value for prop `navigate` on <a> tag
16+
const { navigate, ...rest } = props;
17+
return <Button {...rest} />;
18+
}
1319

1420
function Main() {
1521
const heartbeats = useHeartbeats();
1622
const chainIdsToHeartbeats = useChainHeartbeats(heartbeats);
1723
const latestRelease = useLatestRelease();
1824
return (
19-
<Router>
25+
<>
2026
<AppBar position="static">
2127
<Toolbar variant="dense">
2228
<NavLink
2329
to="/"
2430
exact
25-
component={Button}
31+
component={NavButton}
2632
color="inherit"
2733
activeStyle={{ borderBottom: '2px solid', paddingBottom: 4 }}
2834
style={{ marginLeft: -8, textTransform: 'none', borderRadius: 0, minWidth: 0 }}
@@ -39,7 +45,7 @@ function Main() {
3945
<NavLink
4046
to="/metrics"
4147
exact
42-
component={Button}
48+
component={NavButton}
4349
color="inherit"
4450
activeStyle={{ borderBottom: '2px solid', paddingBottom: 4 }}
4551
style={{ paddingRight: 8, marginLeft: 8, textTransform: 'none', borderRadius: 0 }}
@@ -79,7 +85,7 @@ function Main() {
7985
/>
8086
</Route>
8187
</Switch>
82-
</Router>
88+
</>
8389
);
8490
}
8591
export default Main;

dashboard/src/contexts/NetworkContext.tsx

+28-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React, { ReactNode, useContext, useEffect, useMemo, useState } from 'react';
2-
import { useSettingsContext } from './SettingsContext';
1+
import React, { ReactNode, useCallback, useContext, useEffect, useMemo } from 'react';
2+
import { useHistory, useLocation } from 'react-router-dom';
33

44
export type Environment = 'mainnet' | 'testnet' | 'devnet';
55
export type Network = {
@@ -12,7 +12,7 @@ export type Network = {
1212

1313
type NetworkContextValue = {
1414
currentNetwork: Network;
15-
setCurrentNetwork: React.Dispatch<React.SetStateAction<Network>>;
15+
setCurrentNetwork: (network: Network) => void;
1616
};
1717

1818
// https://book.wormhole.com/reference/rpcnodes.html
@@ -107,23 +107,40 @@ export const networkOptions: Network[] = [
107107
];
108108

109109
const defaultNetwork: Network = networkOptions[0];
110+
const urlParamKey = 'endpoint';
110111

111112
const NetworkContext = React.createContext<NetworkContextValue>({
112113
currentNetwork: defaultNetwork,
113114
setCurrentNetwork: () => {},
114115
});
115116

116117
export const NetworkContextProvider = ({ children }: { children: ReactNode }) => {
117-
const {
118-
settings: { defaultEndpoint },
119-
updateDefaultEndpoint,
120-
} = useSettingsContext();
121-
const [currentNetwork, setCurrentNetwork] = useState<Network>(
122-
networkOptions.find((option) => option.endpoint === defaultEndpoint) || defaultNetwork
118+
const { push, replace } = useHistory();
119+
const { search } = useLocation();
120+
const { urlParams, urlNetwork, currentNetwork } = useMemo(() => {
121+
const urlParams = new URLSearchParams(search);
122+
const urlNetwork = urlParams.get(urlParamKey);
123+
const currentNetwork =
124+
networkOptions.find((option) => option.name === urlNetwork) || defaultNetwork;
125+
return { urlParams, urlNetwork, currentNetwork };
126+
}, [search]);
127+
const setCurrentNetwork = useCallback(
128+
(network: Network, shouldReplace?: boolean) => {
129+
if (urlNetwork !== network.name) {
130+
urlParams.set(urlParamKey, network.name);
131+
if (shouldReplace) {
132+
replace({ search: urlParams.toString() });
133+
} else {
134+
push({ search: urlParams.toString() });
135+
}
136+
}
137+
},
138+
[urlNetwork, urlParams, replace, push]
123139
);
124140
useEffect(() => {
125-
updateDefaultEndpoint(currentNetwork.endpoint);
126-
}, [currentNetwork, updateDefaultEndpoint]);
141+
// sync initial / bad param with drop down, this will do nothing when the current network matches
142+
setCurrentNetwork(currentNetwork, true);
143+
}, [currentNetwork, setCurrentNetwork]);
127144
const value = useMemo(
128145
() => ({ currentNetwork, setCurrentNetwork }),
129146
[currentNetwork, setCurrentNetwork]

dashboard/src/contexts/SettingsContext.tsx

-8
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ export type Theme = 'light' | 'dark' | 'auto';
77
type Settings = {
88
backgroundUrl?: string;
99
backgroundOpacity?: number;
10-
defaultEndpoint?: string;
1110
theme: Theme;
1211
showChainName?: boolean;
1312
showAllMisses?: boolean;
@@ -18,7 +17,6 @@ type SettingsContextValue = {
1817
settings: Settings;
1918
updateBackgroundOpacity(value: number): void;
2019
updateBackgroundUrl(value: string): void;
21-
updateDefaultEndpoint(value: string): void;
2220
updateTheme(value: Theme): void;
2321
updateShowChainName(value: boolean): void;
2422
updateShowAllMisses(value: boolean): void;
@@ -56,7 +54,6 @@ const SettingsContext = React.createContext<SettingsContextValue>({
5654
settings: initialSettings,
5755
updateBackgroundOpacity: (value: number) => {},
5856
updateBackgroundUrl: (value: string) => {},
59-
updateDefaultEndpoint: (value: string) => {},
6057
updateTheme: (value: Theme) => {},
6158
updateShowChainName: (value: boolean) => {},
6259
updateShowAllMisses: (value: boolean) => {},
@@ -71,9 +68,6 @@ export const SettingsContextProvider = ({ children }: { children: ReactNode }) =
7168
const updateBackgroundUrl = useCallback((value: string) => {
7269
setSettings((settings) => ({ ...settings, backgroundUrl: value }));
7370
}, []);
74-
const updateDefaultEndpoint = useCallback((value: string) => {
75-
setSettings((settings) => ({ ...settings, defaultEndpoint: value }));
76-
}, []);
7771
const updateTheme = useCallback((value: Theme) => {
7872
setSettings((settings) => ({ ...settings, theme: value }));
7973
}, []);
@@ -95,7 +89,6 @@ export const SettingsContextProvider = ({ children }: { children: ReactNode }) =
9589
settings,
9690
updateBackgroundOpacity,
9791
updateBackgroundUrl,
98-
updateDefaultEndpoint,
9992
updateTheme,
10093
updateShowChainName,
10194
updateShowAllMisses,
@@ -105,7 +98,6 @@ export const SettingsContextProvider = ({ children }: { children: ReactNode }) =
10598
settings,
10699
updateBackgroundOpacity,
107100
updateBackgroundUrl,
108-
updateDefaultEndpoint,
109101
updateTheme,
110102
updateShowChainName,
111103
updateShowAllMisses,

0 commit comments

Comments
 (0)