Use our own timers to dismiss alerts (#3641)

This commit is contained in:
Erik Jan de Wit 2022-10-27 14:00:02 +02:00 committed by GitHub
parent 66a448720a
commit 2f60e78c4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 36 deletions

View file

@ -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 && <p>{description}</p>}
</Alert>

View file

@ -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<AlertProps | undefined>(
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<AlertType[]>([]);
const setTimeout = useSetTimeout();
const [alerts, setAlerts] = useState<AlertEntry[]>([]);
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<AddAlertFunction>(
(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<AddErrorFunction>((message, error) => {
addAlert(
t(message, {
error: getErrorMessage(error),
}),
AlertVariant.danger
);
};
}, []);
const value = useMemo(() => ({ addAlert, addError }), []);
return (
<AlertContext.Provider value={{ addAlert, addError }}>
<AlertPanel alerts={alerts} onCloseAlert={hideAlert} />
<AlertContext.Provider value={value}>
<AlertPanel alerts={alerts} onCloseAlert={removeAlert} />
{children}
</AlertContext.Provider>
);
};
function getErrorMessage(
error: Error | AxiosError<Record<string, unknown>> | 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<string, unknown>;
throw new Error("Unable to determine error message.");
}
function getErrorMessageAxios(error: AxiosError) {
const data = (error.response?.data ?? {}) as Record<string, unknown>;
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;
}