Skip to content

Commit

Permalink
Add API error message and links to code and docs in the header
Browse files Browse the repository at this point in the history
  • Loading branch information
ka7eh committed Nov 7, 2022
1 parent 52779fa commit 7393b12
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 42 deletions.
97 changes: 96 additions & 1 deletion src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,117 @@
import React, { StrictMode } from 'react';
import axios from 'axios';
import { createRoot } from 'react-dom/client';
import { StyledEngineProvider, ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import Box from '@mui/material/Box';

import Icon from '@mui/material/Icon';
import { StoreContext, initialState, reducers } from './store';
import { theme } from './theme';
import Content from './components/Main/Content';

interface ReadyState {
model: 'loading' | 'ready' | 'error';
sites: 'loading' | 'ready' | 'error';
cases: 'loading' | 'ready' | 'error';
variables: 'loading' | 'ready' | 'error';
}

const App = (): JSX.Element => {
const store = React.useReducer(reducers, initialState);
const dispatch = store[1];

const [readyState, updateReadyState] = React.useState<ReadyState>({
model: 'loading',
sites: 'loading',
cases: 'loading',
variables: 'loading'
});
const [hasAPIError, updateHasAPIError] = React.useState(false);

const handleReadyState = <R,>(url: string, category: keyof ReadyState, callback: (data: R) => void) => {
axios
.get<R>(url)
.then(({ data }) => {
callback(data);
updateReadyState((prevState) => ({
...prevState,
[category]: 'ready'
}));
})
.catch((error) => {
console.error(error);
updateReadyState((prevState) => ({
...prevState,
[category]: 'error'
}));
updateHasAPIError(true);
});
};

React.useEffect(() => {
dispatch({
type: 'updateLoadingState',
isLoading: true
});

handleReadyState<ModelInfo>(`${API_PATH}/cases/model-info`, 'model', (info) => {
dispatch({ type: 'updateModelInfo', info });
});

handleReadyState<GeoJSON.FeatureCollection<GeoJSON.Point, SiteProps>>(`${API_PATH}/sites`, 'sites', (sites) => {
dispatch({ type: 'updateSites', sites });
});

handleReadyState<CaseWithTaskInfo[]>(`${API_PATH}/cases`, 'cases', (cases) => {
dispatch({ type: 'updateCases', cases });
});

handleReadyState<CaseVariableConfig[]>(`${API_PATH}/cases/variables`, 'variables', (vars) => {
dispatch({ type: 'updateVariablesConfig', vars });
});
}, []);

React.useEffect(() => {
if (
hasAPIError ||
(readyState.model === 'ready' &&
readyState.sites === 'ready' &&
readyState.cases === 'ready' &&
readyState.variables === 'ready')
) {
dispatch({
type: 'updateLoadingState',
isLoading: false
});
}
}, [readyState, hasAPIError]);

return (
<StrictMode>
<CssBaseline />
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<StoreContext.Provider value={store}>
<Content />
{hasAPIError ? (
<Box
sx={{
position: 'absolute',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
width: '100%'
}}
>
<Icon baseClassName="icons" fontSize="small" color="error">
error_outline
</Icon>
Cannot connect to API
</Box>
) : (
<Content />
)}
</StoreContext.Provider>
</ThemeProvider>
</StyledEngineProvider>
Expand Down
42 changes: 1 addition & 41 deletions src/components/Main/Content.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import axios from 'axios';
import Box from '@mui/material/Box';
import Divider from '@mui/material/Divider';

Expand All @@ -13,49 +12,10 @@ import Header from './Header';
import Loading from './Loading';

const Content = (): JSX.Element => {
const [state, dispatch] = React.useContext(StoreContext);
const [state] = React.useContext(StoreContext);

const mapRef = React.useRef<maplibregl.Map>();

React.useEffect(() => {
axios.get<ModelInfo>(`${API_PATH}/cases/model-info`).then(({ data }) => {
dispatch({
type: 'updateModelInfo',
info: data
});
});

axios
.get<GeoJSON.FeatureCollection<GeoJSON.Point, SiteProps>>(`${API_PATH}/sites`)
.then(({ data }) => {
dispatch({ type: 'updateSites', sites: data });
})
.catch(console.error);

axios.get<CaseWithTaskInfo[]>(`${API_PATH}/cases`).then(({ data }) => {
dispatch({
type: 'updateCases',
cases: data
});
});

dispatch({
type: 'updateLoadingState',
isLoading: true
});
axios
.get<CaseVariableConfig[]>(`${API_PATH}/cases/variables`)
.then(({ data }) => {
dispatch({ type: 'updateVariablesConfig', vars: data });
})
.finally(() => {
dispatch({
type: 'updateLoadingState',
isLoading: false
});
});
}, []);

return (
<>
<Header />
Expand Down
18 changes: 18 additions & 0 deletions src/components/Main/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,24 @@ const Header = () => {
>
<Icon baseClassName="icons">info</Icon>
</IconButton>
<IconButton
component={Link}
color="inherit"
href="https://noresmhub.github.io/noresm-land-sites-platform/"
target="_blank"
referrerPolicy="no-referrer"
>
<Icon baseClassName="icons">description</Icon>
</IconButton>
<IconButton
component={Link}
color="inherit"
href="https://github.com/noresmhub/noresm-land-sites-platform/"
target="_blank"
referrerPolicy="no-referrer"
>
<Icon baseClassName="icons">code</Icon>
</IconButton>
</Toolbar>
</AppBar>
<Dialog
Expand Down

0 comments on commit 7393b12

Please sign in to comment.