From 7393b1293276866e11b990e1ac622a1033fffe9f Mon Sep 17 00:00:00 2001 From: kaveh Date: Mon, 7 Nov 2022 16:18:26 +0100 Subject: [PATCH] Add API error message and links to code and docs in the header --- src/app.tsx | 97 ++++++++++++++++++++++++++++++++- src/components/Main/Content.tsx | 42 +------------- src/components/Main/Header.tsx | 18 ++++++ 3 files changed, 115 insertions(+), 42 deletions(-) diff --git a/src/app.tsx b/src/app.tsx index 90823a8..d66a8ff 100755 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,14 +1,91 @@ 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({ + model: 'loading', + sites: 'loading', + cases: 'loading', + variables: 'loading' + }); + const [hasAPIError, updateHasAPIError] = React.useState(false); + + const handleReadyState = (url: string, category: keyof ReadyState, callback: (data: R) => void) => { + axios + .get(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(`${API_PATH}/cases/model-info`, 'model', (info) => { + dispatch({ type: 'updateModelInfo', info }); + }); + + handleReadyState>(`${API_PATH}/sites`, 'sites', (sites) => { + dispatch({ type: 'updateSites', sites }); + }); + + handleReadyState(`${API_PATH}/cases`, 'cases', (cases) => { + dispatch({ type: 'updateCases', cases }); + }); + + handleReadyState(`${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 ( @@ -16,7 +93,25 @@ const App = (): JSX.Element => { - + {hasAPIError ? ( + + + error_outline + + Cannot connect to API + + ) : ( + + )} diff --git a/src/components/Main/Content.tsx b/src/components/Main/Content.tsx index a46e79c..a737ae3 100644 --- a/src/components/Main/Content.tsx +++ b/src/components/Main/Content.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import axios from 'axios'; import Box from '@mui/material/Box'; import Divider from '@mui/material/Divider'; @@ -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(); - React.useEffect(() => { - axios.get(`${API_PATH}/cases/model-info`).then(({ data }) => { - dispatch({ - type: 'updateModelInfo', - info: data - }); - }); - - axios - .get>(`${API_PATH}/sites`) - .then(({ data }) => { - dispatch({ type: 'updateSites', sites: data }); - }) - .catch(console.error); - - axios.get(`${API_PATH}/cases`).then(({ data }) => { - dispatch({ - type: 'updateCases', - cases: data - }); - }); - - dispatch({ - type: 'updateLoadingState', - isLoading: true - }); - axios - .get(`${API_PATH}/cases/variables`) - .then(({ data }) => { - dispatch({ type: 'updateVariablesConfig', vars: data }); - }) - .finally(() => { - dispatch({ - type: 'updateLoadingState', - isLoading: false - }); - }); - }, []); - return ( <>
diff --git a/src/components/Main/Header.tsx b/src/components/Main/Header.tsx index c524b1b..194dc53 100644 --- a/src/components/Main/Header.tsx +++ b/src/components/Main/Header.tsx @@ -49,6 +49,24 @@ const Header = () => { > info + + description + + + code +