From f22768c2bca989e111bd30ccc3c2d0ac438f4c90 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Wed, 23 Aug 2023 12:52:49 -0300 Subject: [PATCH 1/4] fix(App.tsx): remove extra comma in the useContext hook feat(App.tsx): add support for displaying fetch error message when there is an error in the backend API call fix(typesContext.tsx): add error handling for API call and set fetchError state accordingly feat(typesContext.tsx): add fetchError state and setFetchError function to the typesContext --- src/frontend/src/App.tsx | 8 +++++++- src/frontend/src/contexts/typesContext.tsx | 14 ++++++++++++-- src/frontend/src/types/typesContext/index.ts | 2 ++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 467e15ed8..5bda7ff37 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -13,6 +13,7 @@ import LoadingComponent from "./components/loadingComponent"; import { alertContext } from "./contexts/alertContext"; import { locationContext } from "./contexts/locationContext"; import { TabsContext } from "./contexts/tabsContext"; +import { typesContext } from "./contexts/typesContext"; import Router from "./routes"; export default function App() { @@ -38,6 +39,7 @@ export default function App() { setSuccessOpen, loading, } = useContext(alertContext); + const { fetchError } = useContext(typesContext); // Initialize state variable for the list of alerts const [alertsList, setAlertsList] = useState< @@ -137,7 +139,11 @@ export default function App() { > {loading ? (
- + {fetchError ? ( +
There was an error on the backend
+ ) : ( + + )}
) : ( <> diff --git a/src/frontend/src/contexts/typesContext.tsx b/src/frontend/src/contexts/typesContext.tsx index ecdfb95a9..8f18b062c 100644 --- a/src/frontend/src/contexts/typesContext.tsx +++ b/src/frontend/src/contexts/typesContext.tsx @@ -6,7 +6,7 @@ import { useState, } from "react"; import { Node } from "reactflow"; -import { getAll } from "../controllers/API"; +import { getAll, getHealth } from "../controllers/API"; import { APIKindType } from "../types/api"; import { typesContextType } from "../types/typesContext"; import { alertContext } from "./alertContext"; @@ -23,6 +23,8 @@ const initialValue: typesContextType = { setTemplates: () => {}, data: {}, setData: () => {}, + setFetchError: () => {}, + fetchError: false, }; export const typesContext = createContext(initialValue); @@ -32,6 +34,7 @@ export function TypesProvider({ children }: { children: ReactNode }) { const [reactFlowInstance, setReactFlowInstance] = useState(null); const [templates, setTemplates] = useState({}); const [data, setData] = useState({}); + const [fetchError, setFetchError] = useState(false); const { setLoading } = useContext(alertContext); useEffect(() => { @@ -46,8 +49,13 @@ export function TypesProvider({ children }: { children: ReactNode }) { async function getTypes(): Promise { try { const result = await getAll(); + if (result?.status !== 200) { + let health = await getHealth().catch((e) => { + setFetchError(true); + }); + } // Make sure to only update the state if the component is still mounted. - if (isMounted) { + if (isMounted && result?.status === 200) { setLoading(false); setData(result.data); setTemplates( @@ -117,6 +125,8 @@ export function TypesProvider({ children }: { children: ReactNode }) { templates, data, setData, + fetchError, + setFetchError, }} > {children} diff --git a/src/frontend/src/types/typesContext/index.ts b/src/frontend/src/types/typesContext/index.ts index 64b6e3e9d..57b64d7e2 100644 --- a/src/frontend/src/types/typesContext/index.ts +++ b/src/frontend/src/types/typesContext/index.ts @@ -15,4 +15,6 @@ export type typesContextType = { setTemplates: (newState: {}) => void; data: typeof data; setData: (newState: {}) => void; + fetchError: boolean; + setFetchError: (newState: boolean) => void; }; From ea105ee7afa40557a538c90111ff4ca43bb12b7d Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Wed, 23 Aug 2023 14:44:45 -0300 Subject: [PATCH 2/4] refactor(typesContext.tsx): remove unnecessary retry logic and interval for fetching types fix(typesContext.tsx): fix issue where component was not unmounting properly and causing memory leaks --- src/frontend/src/contexts/typesContext.tsx | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/frontend/src/contexts/typesContext.tsx b/src/frontend/src/contexts/typesContext.tsx index 8f18b062c..bcaf67bf1 100644 --- a/src/frontend/src/contexts/typesContext.tsx +++ b/src/frontend/src/contexts/typesContext.tsx @@ -38,11 +38,6 @@ export function TypesProvider({ children }: { children: ReactNode }) { const { setLoading } = useContext(alertContext); useEffect(() => { - let delay = 1000; // Start delay of 1 second - let intervalId = null; - let retryCount = 0; // Count of retry attempts - const maxRetryCount = 5; // Max retry attempts - // We will keep a flag to handle the case where the component is unmounted before the API call resolves. let isMounted = true; @@ -85,22 +80,13 @@ export function TypesProvider({ children }: { children: ReactNode }) { }, {}) ); } - // Clear the interval if successful. - clearInterval(intervalId); } catch (error) { console.error("An error has occurred while fetching types."); } } // Start the initial interval. - intervalId = setInterval(getTypes, delay); - - return () => { - // This will clear the interval when the component unmounts, or when the dependencies of the useEffect hook change. - clearInterval(intervalId); - // Indicate that the component has been unmounted. - isMounted = false; - }; + getTypes(); }, []); function deleteNode(idx: string) { From d9b03980f7609ccea434adec4a07e13ff8ed6c6a Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Wed, 23 Aug 2023 14:59:20 -0300 Subject: [PATCH 3/4] fix(typesContext.tsx): remove unnecessary code that checks result status and fetches health on error fix(typesContext.tsx): handle error when fetching types and set fetchError state to true --- src/frontend/src/contexts/typesContext.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/frontend/src/contexts/typesContext.tsx b/src/frontend/src/contexts/typesContext.tsx index bcaf67bf1..189f61af0 100644 --- a/src/frontend/src/contexts/typesContext.tsx +++ b/src/frontend/src/contexts/typesContext.tsx @@ -44,11 +44,6 @@ export function TypesProvider({ children }: { children: ReactNode }) { async function getTypes(): Promise { try { const result = await getAll(); - if (result?.status !== 200) { - let health = await getHealth().catch((e) => { - setFetchError(true); - }); - } // Make sure to only update the state if the component is still mounted. if (isMounted && result?.status === 200) { setLoading(false); @@ -82,10 +77,13 @@ export function TypesProvider({ children }: { children: ReactNode }) { } } catch (error) { console.error("An error has occurred while fetching types."); + await getHealth().catch((e) => { + console.log("entrou"); + setFetchError(true); + }); } } - // Start the initial interval. getTypes(); }, []); From cd6985591f7b352b29da624727494815348e775c Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Wed, 23 Aug 2023 21:09:53 -0300 Subject: [PATCH 4/4] fix(App.tsx): replace hardcoded error message with FetchErrorComponent to improve error handling and display feat(App.tsx): add support for displaying fetch error message and description in FetchErrorComponent feat(fetchErrorComponent): create FetchErrorComponent to display fetch error message and description fix(genericIconComponent): add stroke-width property to ensure consistent icon stroke width feat(loadingComponent): import LoadingComponentProps from types/components to improve type safety feat(constants): add FETCH_ERROR_MESSAGE and FETCH_ERROR_DESCRIPTION constants for fetch error handling fix(typesContext): remove console.log statement and set fetchError to true when an error occurs during fetching types feat(typesContext): add error handling for fetching types and set fetchError to true when an error occurs feat(typesContext): import fetchErrorComponentType from types/components to improve type safety feat(types/components): create fetchErrorComponentType and LoadingComponentProps interfaces for type safety fix(styleUtils): import Unplug icon from lucide-react to fix missing icon issue --- src/frontend/src/App.tsx | 10 +++++++++- .../src/components/fetchErrorComponent/index.tsx | 16 ++++++++++++++++ .../components/genericIconComponent/index.tsx | 8 +++++++- .../src/components/loadingComponent/index.tsx | 4 +--- src/frontend/src/constants/constants.ts | 4 ++++ src/frontend/src/contexts/typesContext.tsx | 1 - src/frontend/src/types/components/index.ts | 8 ++++++++ src/frontend/src/utils/styleUtils.ts | 2 ++ 8 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 src/frontend/src/components/fetchErrorComponent/index.tsx diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 5bda7ff37..2109222ed 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -9,7 +9,12 @@ import ErrorAlert from "./alerts/error"; import NoticeAlert from "./alerts/notice"; import SuccessAlert from "./alerts/success"; import CrashErrorComponent from "./components/CrashErrorComponent"; +import FetchErrorComponent from "./components/fetchErrorComponent"; import LoadingComponent from "./components/loadingComponent"; +import { + FETCH_ERROR_DESCRIPION, + FETCH_ERROR_MESSAGE, +} from "./constants/constants"; import { alertContext } from "./contexts/alertContext"; import { locationContext } from "./contexts/locationContext"; import { TabsContext } from "./contexts/tabsContext"; @@ -140,7 +145,10 @@ export default function App() { {loading ? (
{fetchError ? ( -
There was an error on the backend
+ ) : ( )} diff --git a/src/frontend/src/components/fetchErrorComponent/index.tsx b/src/frontend/src/components/fetchErrorComponent/index.tsx new file mode 100644 index 000000000..6004d9dfc --- /dev/null +++ b/src/frontend/src/components/fetchErrorComponent/index.tsx @@ -0,0 +1,16 @@ +import { fetchErrorComponentType } from "../../types/components"; +import IconComponent from "../genericIconComponent"; + +export default function FetchErrorComponent({ + message, + description, +}: fetchErrorComponentType) { + return ( +
+ +

+ {message} + {description} +
+ ); +} diff --git a/src/frontend/src/components/genericIconComponent/index.tsx b/src/frontend/src/components/genericIconComponent/index.tsx index 32647f159..a06707d74 100644 --- a/src/frontend/src/components/genericIconComponent/index.tsx +++ b/src/frontend/src/components/genericIconComponent/index.tsx @@ -7,5 +7,11 @@ export default function IconComponent({ iconColor, }: IconComponentProps): JSX.Element { const TargetIcon = nodeIconsLucide[name] ?? nodeIconsLucide["unknown"]; - return ; + return ( + + ); } diff --git a/src/frontend/src/components/loadingComponent/index.tsx b/src/frontend/src/components/loadingComponent/index.tsx index 31e78d474..a1e406710 100644 --- a/src/frontend/src/components/loadingComponent/index.tsx +++ b/src/frontend/src/components/loadingComponent/index.tsx @@ -1,6 +1,4 @@ -type LoadingComponentProps = { - remSize: number; -}; +import { LoadingComponentProps } from "../../types/components"; export default function LoadingComponent({ remSize }: LoadingComponentProps) { return ( diff --git a/src/frontend/src/constants/constants.ts b/src/frontend/src/constants/constants.ts index 3f698c64e..aa9f1555a 100644 --- a/src/frontend/src/constants/constants.ts +++ b/src/frontend/src/constants/constants.ts @@ -511,3 +511,7 @@ export const URL_EXCLUDED_FROM_ERROR_RETRIES = [ ]; export const skipNodeUpdate = ["CustomComponent"]; + +export const FETCH_ERROR_MESSAGE = "Couldn't establish a connection."; +export const FETCH_ERROR_DESCRIPION = + "Check if everything is working properly and try again."; diff --git a/src/frontend/src/contexts/typesContext.tsx b/src/frontend/src/contexts/typesContext.tsx index 189f61af0..05346838d 100644 --- a/src/frontend/src/contexts/typesContext.tsx +++ b/src/frontend/src/contexts/typesContext.tsx @@ -78,7 +78,6 @@ export function TypesProvider({ children }: { children: ReactNode }) { } catch (error) { console.error("An error has occurred while fetching types."); await getHealth().catch((e) => { - console.log("entrou"); setFetchError(true); }); } diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 5cf87b8d3..0ebe768c1 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -171,3 +171,11 @@ export type IconComponentProps = { export interface languageMap { [key: string]: string | undefined; } +export type fetchErrorComponentType = { + message: string; + description: string; +}; + +export type LoadingComponentProps = { + remSize: number; +}; diff --git a/src/frontend/src/utils/styleUtils.ts b/src/frontend/src/utils/styleUtils.ts index 42fbe8773..ca100b5c3 100644 --- a/src/frontend/src/utils/styleUtils.ts +++ b/src/frontend/src/utils/styleUtils.ts @@ -56,6 +56,7 @@ import { TerminalSquare, Trash2, Undo, + Unplug, Upload, Users2, Variable, @@ -275,4 +276,5 @@ export const nodeIconsLucide = { Upload, MessageSquare, MoreHorizontal, + Unplug, };