diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx
index 467e15ed8..2109222ed 100644
--- a/src/frontend/src/App.tsx
+++ b/src/frontend/src/App.tsx
@@ -9,10 +9,16 @@ 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";
+import { typesContext } from "./contexts/typesContext";
import Router from "./routes";
export default function App() {
@@ -38,6 +44,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 +144,14 @@ export default function App() {
>
{loading ? (
-
+ {fetchError ? (
+
+ ) : (
+
+ )}
) : (
<>
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 ecdfb95a9..05346838d 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,14 +34,10 @@ 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(() => {
- 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;
@@ -47,7 +45,7 @@ export function TypesProvider({ children }: { children: ReactNode }) {
try {
const result = await getAll();
// 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(
@@ -77,22 +75,15 @@ export function TypesProvider({ children }: { children: ReactNode }) {
}, {})
);
}
- // Clear the interval if successful.
- clearInterval(intervalId);
} catch (error) {
console.error("An error has occurred while fetching types.");
+ await getHealth().catch((e) => {
+ setFetchError(true);
+ });
}
}
- // 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) {
@@ -117,6 +108,8 @@ export function TypesProvider({ children }: { children: ReactNode }) {
templates,
data,
setData,
+ fetchError,
+ setFetchError,
}}
>
{children}
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/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;
};
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,
};