aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src
diff options
context:
space:
mode:
Diffstat (limited to 'FrontEnd/src')
-rw-r--r--FrontEnd/src/app/services/alert.ts4
-rw-r--r--FrontEnd/src/app/views/common/alert/AlertHost.tsx70
2 files changed, 36 insertions, 38 deletions
diff --git a/FrontEnd/src/app/services/alert.ts b/FrontEnd/src/app/services/alert.ts
index e4c0e653..b6d6be6e 100644
--- a/FrontEnd/src/app/services/alert.ts
+++ b/FrontEnd/src/app/services/alert.ts
@@ -1,9 +1,11 @@
import React from "react";
import pull from "lodash/pull";
+import { I18nText } from "@/common";
+
export interface AlertInfo {
type?: "primary" | "secondary" | "success" | "danger" | "warning" | "info";
- message: string | React.FC<unknown> | { type: "i18n"; key: string };
+ message: React.FC<unknown> | I18nText;
dismissTime?: number | "never";
}
diff --git a/FrontEnd/src/app/views/common/alert/AlertHost.tsx b/FrontEnd/src/app/views/common/alert/AlertHost.tsx
index f50e41ad..949be7ed 100644
--- a/FrontEnd/src/app/views/common/alert/AlertHost.tsx
+++ b/FrontEnd/src/app/views/common/alert/AlertHost.tsx
@@ -1,6 +1,5 @@
-import React, { useCallback } from "react";
+import React from "react";
import without from "lodash/without";
-import concat from "lodash/concat";
import { useTranslation } from "react-i18next";
import { Alert } from "react-bootstrap";
@@ -10,6 +9,7 @@ import {
kAlertHostId,
AlertInfo,
} from "@/services/alert";
+import { convertI18nText } from "@/common";
interface AutoCloseAlertProps {
alert: AlertInfo;
@@ -17,39 +17,46 @@ interface AutoCloseAlertProps {
}
export const AutoCloseAlert: React.FC<AutoCloseAlertProps> = (props) => {
- const { alert } = props;
+ const { alert, close } = props;
const { dismissTime } = alert;
const { t } = useTranslation();
const timerTag = React.useRef<number | null>(null);
+ const closeHandler = React.useRef<(() => void) | null>(null);
+
+ React.useEffect(() => {
+ closeHandler.current = close;
+ }, [close]);
React.useEffect(() => {
const tag =
dismissTime === "never"
? null
: typeof dismissTime === "number"
- ? window.setTimeout(props.close, dismissTime)
- : window.setTimeout(props.close, 5000);
+ ? window.setTimeout(() => closeHandler.current?.(), dismissTime)
+ : window.setTimeout(() => closeHandler.current?.(), 5000);
timerTag.current = tag;
return () => {
if (tag != null) {
window.clearTimeout(tag);
}
};
- }, [dismissTime, props.close]);
+ }, [dismissTime]);
+
+ const cancelTimer = (): void => {
+ const { current: tag } = timerTag;
+ if (tag != null) {
+ window.clearTimeout(tag);
+ }
+ };
return (
<Alert
className="m-3"
variant={alert.type ?? "primary"}
- onClick={() => {
- const { current: tag } = timerTag;
- if (tag != null) {
- window.clearTimeout(tag);
- }
- }}
- onClose={props.close}
+ onClick={cancelTimer}
+ onClose={close}
dismissible
>
{(() => {
@@ -57,50 +64,39 @@ export const AutoCloseAlert: React.FC<AutoCloseAlertProps> = (props) => {
if (typeof message === "function") {
const Message = message;
return <Message />;
- } else if (typeof message === "object" && message.type === "i18n") {
- return t(message.key);
- } else return alert.message;
+ } else return convertI18nText(message, t);
})()}
</Alert>
);
};
-// oh what a bad name!
-interface AlertInfoExEx extends AlertInfoEx {
- close: () => void;
-}
-
const AlertHost: React.FC = () => {
- const [alerts, setAlerts] = React.useState<AlertInfoExEx[]>([]);
+ const [alerts, setAlerts] = React.useState<AlertInfoEx[]>([]);
// react guarantee that state setters are stable, so we don't need to add it to dependency list
- const consume = useCallback((alert: AlertInfoEx): void => {
- const alertEx: AlertInfoExEx = {
- ...alert,
- close: () => {
- setAlerts((oldAlerts) => {
- return without(oldAlerts, alertEx);
- });
- },
+ React.useEffect(() => {
+ const consume = (alert: AlertInfoEx): void => {
+ setAlerts((old) => [...old, alert]);
};
- setAlerts((oldAlerts) => {
- return concat(oldAlerts, alertEx);
- });
- }, []);
- React.useEffect(() => {
alertService.registerConsumer(consume);
return () => {
alertService.unregisterConsumer(consume);
};
- }, [consume]);
+ }, []);
return (
<div id={kAlertHostId} className="alert-container">
{alerts.map((alert) => {
return (
- <AutoCloseAlert key={alert.id} alert={alert} close={alert.close} />
+ <AutoCloseAlert
+ key={alert.id}
+ alert={alert}
+ close={() => {
+ setAlerts((old) => without(old, alert));
+ }}
+ />
);
})}
</div>