From 68ca8b0976efe90c0c40bcae69f0825671b98bad Mon Sep 17 00:00:00 2001
From: crupest <crupest@outlook.com>
Date: Sat, 30 May 2020 16:23:25 +0800
Subject: Merge front end to this repo. But I need to wait for aspnet core
 support for custom port and package manager for dev server.

---
 Timeline/ClientApp/src/common/AlertHost.tsx | 75 +++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100644 Timeline/ClientApp/src/common/AlertHost.tsx

(limited to 'Timeline/ClientApp/src/common/AlertHost.tsx')

diff --git a/Timeline/ClientApp/src/common/AlertHost.tsx b/Timeline/ClientApp/src/common/AlertHost.tsx
new file mode 100644
index 00000000..2d9dbb13
--- /dev/null
+++ b/Timeline/ClientApp/src/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;
-- 
cgit v1.2.3

