diff --git a/apps/admin-ui/src/components/alert/AlertPanel.tsx b/apps/admin-ui/src/components/alert/AlertPanel.tsx
index 37884f9d62..e9895cd020 100644
--- a/apps/admin-ui/src/components/alert/AlertPanel.tsx
+++ b/apps/admin-ui/src/components/alert/AlertPanel.tsx
@@ -4,10 +4,10 @@ import {
AlertActionCloseButton,
AlertVariant,
} from "@patternfly/react-core";
-import type { AlertType } from "./Alerts";
+import type { AlertEntry } from "./Alerts";
type AlertPanelProps = {
- alerts: AlertType[];
+ alerts: AlertEntry[];
onCloseAlert: (id: number) => void;
};
@@ -27,8 +27,6 @@ export function AlertPanel({ alerts, onCloseAlert }: AlertPanelProps) {
onClose={() => onCloseAlert(id)}
/>
}
- timeout
- onTimeout={() => onCloseAlert(id)}
>
{description &&
{description}
}
diff --git a/apps/admin-ui/src/components/alert/Alerts.tsx b/apps/admin-ui/src/components/alert/Alerts.tsx
index 390ebea766..df631940e6 100644
--- a/apps/admin-ui/src/components/alert/Alerts.tsx
+++ b/apps/admin-ui/src/components/alert/Alerts.tsx
@@ -1,22 +1,25 @@
-import { FunctionComponent, useState } from "react";
-import { useTranslation } from "react-i18next";
import { AlertVariant } from "@patternfly/react-core";
-import axios from "axios";
import type { AxiosError } from "axios";
+import axios from "axios";
+import { FunctionComponent, useCallback, useMemo, useState } from "react";
+import { useTranslation } from "react-i18next";
import { createNamedContext } from "../../utils/createNamedContext";
import useRequiredContext from "../../utils/useRequiredContext";
+import useSetTimeout from "../../utils/useSetTimeout";
import { AlertPanel } from "./AlertPanel";
+const ALERT_TIMEOUT = 8000;
+
export type AddAlertFunction = (
message: string,
variant?: AlertVariant,
description?: string
) => void;
-export type AddErrorFunction = (message: string, error: any) => void;
+export type AddErrorFunction = (message: string, error: unknown) => void;
-type AlertProps = {
+export type AlertProps = {
addAlert: AddAlertFunction;
addError: AddErrorFunction;
};
@@ -28,7 +31,7 @@ export const AlertContext = createNamedContext(
export const useAlerts = () => useRequiredContext(AlertContext);
-export type AlertType = {
+export type AlertEntry = {
id: number;
message: string;
variant: AlertVariant;
@@ -37,65 +40,70 @@ export type AlertType = {
export const AlertProvider: FunctionComponent = ({ children }) => {
const { t } = useTranslation();
- const [alerts, setAlerts] = useState([]);
+ const setTimeout = useSetTimeout();
+ const [alerts, setAlerts] = useState([]);
- const hideAlert = (id: number) => {
+ const removeAlert = (id: number) =>
setAlerts((alerts) => alerts.filter((alert) => alert.id !== id));
- };
- const addAlert = (
- message: string,
- variant: AlertVariant = AlertVariant.success,
- description?: string
- ) => {
- setAlerts([
- {
+ const addAlert = useCallback(
+ (message, variant = AlertVariant.success, description) => {
+ const alert: AlertEntry = {
id: Math.random(),
message,
variant,
description,
- },
- ...alerts,
- ]);
- };
+ };
- const addError = (message: string, error: Error | AxiosError | string) => {
+ setAlerts((alerts) => [alert, ...alerts]);
+ setTimeout(() => removeAlert(alert.id), ALERT_TIMEOUT);
+ },
+ []
+ );
+
+ const addError = useCallback((message, error) => {
addAlert(
t(message, {
error: getErrorMessage(error),
}),
AlertVariant.danger
);
- };
+ }, []);
+
+ const value = useMemo(() => ({ addAlert, addError }), []);
return (
-
-
+
+
{children}
);
};
-function getErrorMessage(
- error: Error | AxiosError> | string
-) {
+function getErrorMessage(error: unknown) {
if (typeof error === "string") {
return error;
}
- if (!axios.isAxiosError(error)) {
+ if (axios.isAxiosError(error)) {
+ return getErrorMessageAxios(error);
+ }
+
+ if (error instanceof Error) {
return error.message;
}
- const responseData = (error.response?.data ?? {}) as Record;
+ throw new Error("Unable to determine error message.");
+}
+
+function getErrorMessageAxios(error: AxiosError) {
+ const data = (error.response?.data ?? {}) as Record;
for (const key of ["error_description", "errorMessage", "error"]) {
- const value = responseData[key];
+ const value = data[key];
if (typeof value === "string") {
return value;
}
}
-
- return error.message;
}