2019-06-19 14:40:52 +00:00
|
|
|
import Button from "@material-ui/core/Button";
|
|
|
|
import IconButton from "@material-ui/core/IconButton";
|
|
|
|
import Snackbar from "@material-ui/core/Snackbar";
|
2019-11-25 16:23:52 +00:00
|
|
|
import Typography from "@material-ui/core/Typography";
|
2019-06-19 14:40:52 +00:00
|
|
|
import CloseIcon from "@material-ui/icons/Close";
|
2020-06-23 11:47:30 +00:00
|
|
|
import classNames from "classnames";
|
|
|
|
import React, { useState } from "react";
|
|
|
|
import { FormattedMessage } from "react-intl";
|
2019-06-19 14:40:52 +00:00
|
|
|
|
|
|
|
import { IMessage, MessageContext } from "./";
|
2020-06-23 11:47:30 +00:00
|
|
|
import { useStyles } from "./styles";
|
2019-06-19 14:40:52 +00:00
|
|
|
|
|
|
|
interface Message extends IMessage {
|
|
|
|
key: string;
|
|
|
|
}
|
|
|
|
|
2020-06-23 11:47:30 +00:00
|
|
|
export const MessageManager = props => {
|
|
|
|
const { children } = props;
|
|
|
|
|
|
|
|
const [message, setMessage] = useState<Message>({
|
|
|
|
key: "0",
|
|
|
|
onUndo: undefined,
|
|
|
|
status: "info",
|
|
|
|
text: ""
|
|
|
|
});
|
|
|
|
const [opened, setOpened] = useState(false);
|
|
|
|
|
|
|
|
const classes = useStyles({});
|
|
|
|
const {
|
|
|
|
action,
|
|
|
|
autohide = 3000,
|
|
|
|
title,
|
|
|
|
text,
|
|
|
|
key,
|
|
|
|
onUndo,
|
|
|
|
status = "info"
|
|
|
|
} = message;
|
2019-06-19 14:40:52 +00:00
|
|
|
|
2020-06-23 11:47:30 +00:00
|
|
|
const queue = [];
|
|
|
|
|
|
|
|
const handleClose = (_, reason) => {
|
2019-06-19 14:40:52 +00:00
|
|
|
if (reason === "clickaway") {
|
|
|
|
return;
|
|
|
|
}
|
2020-06-23 11:47:30 +00:00
|
|
|
setOpened(false);
|
|
|
|
};
|
|
|
|
|
|
|
|
const processQueue = () => {
|
|
|
|
if (queue.length > 0) {
|
|
|
|
setMessage(queue.shift());
|
|
|
|
setOpened(true);
|
|
|
|
}
|
2019-06-19 14:40:52 +00:00
|
|
|
};
|
|
|
|
|
2020-06-23 11:47:30 +00:00
|
|
|
const handleExited = () => {
|
|
|
|
processQueue();
|
2019-06-19 14:40:52 +00:00
|
|
|
};
|
|
|
|
|
2020-06-23 11:47:30 +00:00
|
|
|
const pushMessage = (message: IMessage) => {
|
|
|
|
queue.push({
|
2019-06-19 14:40:52 +00:00
|
|
|
key: new Date().getTime(),
|
|
|
|
...message
|
|
|
|
});
|
|
|
|
|
2020-06-23 11:47:30 +00:00
|
|
|
if (opened) {
|
|
|
|
setOpened(false);
|
2019-06-19 14:40:52 +00:00
|
|
|
} else {
|
2020-06-23 11:47:30 +00:00
|
|
|
processQueue();
|
2019-06-19 14:40:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-06-23 11:47:30 +00:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Snackbar
|
|
|
|
key={key}
|
|
|
|
anchorOrigin={{
|
|
|
|
horizontal: "right",
|
|
|
|
vertical: "top"
|
|
|
|
}}
|
|
|
|
open={opened}
|
|
|
|
autoHideDuration={autohide}
|
|
|
|
onClose={handleClose}
|
|
|
|
onExited={handleExited}
|
|
|
|
ContentProps={{
|
|
|
|
"aria-describedby": "message-id"
|
|
|
|
}}
|
|
|
|
className={classNames(classes.snackbar, {
|
|
|
|
[classes.error]: status === "error",
|
|
|
|
[classes.success]: status === "success",
|
|
|
|
[classes.warning]: status === "warning"
|
|
|
|
})}
|
|
|
|
message={
|
|
|
|
<span id="message-id" data-tc="notification">
|
|
|
|
{title && (
|
|
|
|
<Typography variant="h5" style={{ fontWeight: "bold" }}>
|
|
|
|
{title}
|
|
|
|
</Typography>
|
|
|
|
)}
|
|
|
|
<Typography
|
|
|
|
className={status === "info" ? classes.textInfo : classes.text}
|
|
|
|
>
|
2019-08-27 13:29:00 +00:00
|
|
|
{text}
|
2020-06-23 11:47:30 +00:00
|
|
|
</Typography>
|
|
|
|
</span>
|
|
|
|
}
|
|
|
|
title={title}
|
|
|
|
action={[
|
|
|
|
!!onUndo ? (
|
|
|
|
<Button
|
|
|
|
key="undo"
|
|
|
|
color="default"
|
|
|
|
size="small"
|
|
|
|
onClick={handleClose as any}
|
|
|
|
data-tc="button-undo"
|
2019-06-19 14:40:52 +00:00
|
|
|
>
|
2020-06-23 11:47:30 +00:00
|
|
|
<FormattedMessage
|
|
|
|
defaultMessage="Undo"
|
|
|
|
description="snackbar button undo"
|
|
|
|
/>
|
|
|
|
</Button>
|
|
|
|
) : (
|
|
|
|
undefined
|
|
|
|
),
|
|
|
|
!!action ? (
|
|
|
|
<Button
|
|
|
|
key="action"
|
|
|
|
color="default"
|
|
|
|
size="small"
|
|
|
|
onClick={() => {
|
|
|
|
action();
|
|
|
|
handleClose(null, null);
|
|
|
|
}}
|
|
|
|
data-tc="button-action"
|
|
|
|
>
|
|
|
|
<FormattedMessage
|
|
|
|
defaultMessage="Action"
|
|
|
|
description="snackbar button action"
|
|
|
|
/>
|
|
|
|
</Button>
|
|
|
|
) : (
|
|
|
|
undefined
|
|
|
|
),
|
|
|
|
<IconButton
|
|
|
|
key="close"
|
|
|
|
aria-label="Close"
|
|
|
|
color="inherit"
|
|
|
|
onClick={handleClose as any}
|
|
|
|
className={classes.closeBtn}
|
|
|
|
>
|
|
|
|
<CloseIcon />
|
|
|
|
</IconButton>,
|
|
|
|
<div className={classes.progressBarContainer} key="progressBar">
|
|
|
|
<div
|
|
|
|
className={classNames(classes.progressBar, {
|
|
|
|
[classes.progressBarActive]: opened,
|
|
|
|
[classes.progressBarSuccess]: status === "success",
|
|
|
|
[classes.progressBarWarning]: status === "warning",
|
|
|
|
[classes.progressBarError]: status === "error"
|
|
|
|
})}
|
|
|
|
style={{ ["--animationTime" as any]: `${autohide}ms` }}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
]}
|
|
|
|
/>
|
|
|
|
<MessageContext.Provider value={pushMessage}>
|
|
|
|
{children}
|
|
|
|
</MessageContext.Provider>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2019-06-19 14:40:52 +00:00
|
|
|
export default MessageManager;
|