saleor-dashboard/src/components/messages/MessageManager.tsx

173 lines
4.3 KiB
TypeScript
Raw Normal View History

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;