diff options
author | crupest <crupest@outlook.com> | 2020-06-11 17:27:15 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-06-11 17:27:15 +0800 |
commit | cf6cfe87b46a2a3eb2913209092ab4c5639e75c3 (patch) | |
tree | eba7504d04dad89f67524b48d88a3b5eb27de6de /Timeline/ClientApp/src/app/common/AlertHost.tsx | |
parent | 4b8abdd1921935ebb29d18961534db04a2e58fbb (diff) | |
download | timeline-cf6cfe87b46a2a3eb2913209092ab4c5639e75c3.tar.gz timeline-cf6cfe87b46a2a3eb2913209092ab4c5639e75c3.tar.bz2 timeline-cf6cfe87b46a2a3eb2913209092ab4c5639e75c3.zip |
feat(front): Service worker is coming!
Diffstat (limited to 'Timeline/ClientApp/src/app/common/AlertHost.tsx')
-rw-r--r-- | Timeline/ClientApp/src/app/common/AlertHost.tsx | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/Timeline/ClientApp/src/app/common/AlertHost.tsx b/Timeline/ClientApp/src/app/common/AlertHost.tsx new file mode 100644 index 00000000..c815db2b --- /dev/null +++ b/Timeline/ClientApp/src/app/common/AlertHost.tsx @@ -0,0 +1,75 @@ +import React, { useCallback } from 'react'; +import { Alert } from 'reactstrap'; +import without from 'lodash/without'; +import concat from 'lodash/concat'; + +import { + alertService, + AlertInfoEx, + kAlertHostId, + AlertInfo, +} from './alert-service'; + +interface AutoCloseAlertProps { + alert: AlertInfo; + close: () => void; +} + +export const AutoCloseAlert: React.FC<AutoCloseAlertProps> = (props) => { + const { alert } = props; + + React.useEffect(() => { + const tag = window.setTimeout(props.close, 5000); + return () => window.clearTimeout(tag); + }, [props.close]); + + return ( + <Alert className="m-3" color={alert.type ?? 'primary'} toggle={props.close}> + {alert.message} + </Alert> + ); +}; + +// oh what a bad name! +interface AlertInfoExEx extends AlertInfoEx { + close: () => void; +} + +export const AlertHost: React.FC = () => { + const [alerts, setAlerts] = React.useState<AlertInfoExEx[]>([]); + + // 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); + }); + }, + }; + 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} /> + ); + })} + </div> + ); +}; + +export default AlertHost; |