update MessageManager

This commit is contained in:
AlicjaSzu 2020-06-23 13:47:30 +02:00
parent f4d570c7e5
commit b3eb13a785
8 changed files with 279 additions and 90 deletions

View file

@ -0,0 +1,5 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="16" fill="#F5FAFB"/>
<rect x="10.2726" y="9.00024" width="17.9987" height="1.79987" transform="rotate(45 10.2726 9.00024)" fill="#FE6D76"/>
<rect x="23" y="10.2727" width="17.9987" height="1.79987" transform="rotate(135 23 10.2727)" fill="#FE6D76"/>
</svg>

After

Width:  |  Height:  |  Size: 380 B

View file

@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 32C24.8366 32 32 24.8366 32 16C32 7.16344 24.8366 0 16 0C7.16344 0 0 7.16344 0 16C0 24.8366 7.16344 32 16 32ZM15 20V8H17V20H15ZM15 24V22H17V24H15Z" fill="#CAD8DF"/>
</svg>

After

Width:  |  Height:  |  Size: 321 B

View file

@ -0,0 +1,4 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="16" fill="#F5FAFB"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M23.9167 10.306L12.5417 23L7 16.0699L8.48477 14.8326L12.611 20.0641L22.4919 9L23.9167 10.306Z" fill="#60DAA0"/>
</svg>

After

Width:  |  Height:  |  Size: 312 B

View file

@ -0,0 +1,5 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="16" fill="#F5FAFB"/>
<rect x="10.2726" y="9.00024" width="17.9987" height="1.79987" transform="rotate(45 10.2726 9.00024)" fill="#D98E1D"/>
<rect x="23" y="10.2727" width="17.9987" height="1.79987" transform="rotate(135 23 10.2727)" fill="#D98E1D"/>
</svg>

After

Width:  |  Height:  |  Size: 380 B

View file

@ -3,60 +3,72 @@ import IconButton from "@material-ui/core/IconButton";
import Snackbar from "@material-ui/core/Snackbar";
import Typography from "@material-ui/core/Typography";
import CloseIcon from "@material-ui/icons/Close";
import React from "react";
import classNames from "classnames";
import React, { useState } from "react";
import { FormattedMessage } from "react-intl";
import { IMessage, MessageContext } from "./";
import { useStyles } from "./styles";
interface Message extends IMessage {
key: string;
}
interface MessageManagerState {
message: Message;
opened: boolean;
}
export class MessageManager extends React.Component<{}, MessageManagerState> {
state: MessageManagerState = {
message: { key: "0", onUndo: undefined, text: "" },
opened: false
};
queue = [];
export const MessageManager = props => {
const { children } = props;
handleClose = (_, reason) => {
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;
const queue = [];
const handleClose = (_, reason) => {
if (reason === "clickaway") {
return;
}
this.setState({ opened: false });
setOpened(false);
};
handleExited = () => {
this.processQueue();
const processQueue = () => {
if (queue.length > 0) {
setMessage(queue.shift());
setOpened(true);
}
};
pushMessage = (message: IMessage) => {
this.queue.push({
const handleExited = () => {
processQueue();
};
const pushMessage = (message: IMessage) => {
queue.push({
key: new Date().getTime(),
...message
});
if (this.state.opened) {
this.setState({ opened: false });
if (opened) {
setOpened(false);
} else {
this.processQueue();
processQueue();
}
};
processQueue = () => {
if (this.queue.length > 0) {
this.setState({
message: this.queue.shift(),
opened: true
});
}
};
render() {
const { autohide = 3000, title, text, key, onUndo } = this.state.message;
return (
<>
<Snackbar
@ -65,21 +77,30 @@ export class MessageManager extends React.Component<{}, MessageManagerState> {
horizontal: "right",
vertical: "top"
}}
open={this.state.opened}
open={opened}
autoHideDuration={autohide}
onClose={this.handleClose}
onExited={this.handleExited}
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-test="notification">
<span id="message-id" data-tc="notification">
{title && (
<Typography variant="h5" style={{ marginBottom: "1rem" }}>
<Typography variant="h5" style={{ fontWeight: "bold" }}>
{title}
</Typography>
)}
<Typography
className={status === "info" ? classes.textInfo : classes.text}
>
{text}
</Typography>
</span>
}
title={title}
@ -87,12 +108,34 @@ export class MessageManager extends React.Component<{}, MessageManagerState> {
!!onUndo ? (
<Button
key="undo"
color="secondary"
color="default"
size="small"
onClick={this.handleClose as any}
data-test="button-undo"
onClick={handleClose as any}
data-tc="button-undo"
>
UNDO
<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
@ -101,17 +144,29 @@ export class MessageManager extends React.Component<{}, MessageManagerState> {
key="close"
aria-label="Close"
color="inherit"
onClick={this.handleClose as any}
onClick={handleClose as any}
className={classes.closeBtn}
>
<CloseIcon />
</IconButton>
</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={this.pushMessage}>
{this.props.children}
<MessageContext.Provider value={pushMessage}>
{children}
</MessageContext.Provider>
</>
);
}
}
};
export default MessageManager;

View file

@ -1,10 +1,12 @@
import { createContext } from "react";
export interface IMessage {
action?: () => void;
autohide?: number;
title?: string;
text: string;
onUndo?: () => void;
status?: "success" | "error" | "info" | "warning";
}
export type IMessageContext = (message: IMessage) => void;
export const MessageContext = createContext<IMessageContext>(undefined);

View file

@ -0,0 +1,114 @@
import errorIcon from "@assets/images/error-icon.svg";
import infoIcon from "@assets/images/info-icon.svg";
import successIcon from "@assets/images/success-icon.svg";
import warningIcon from "@assets/images/warning-icon.svg";
import { makeStyles } from "@material-ui/core/styles";
import { darken } from "@material-ui/core/styles/colorManipulator";
const successColor = "#60DAA0";
const warningColor = "#FFB84E";
const infoColor = "#CAD8DF";
export const useStyles = makeStyles(
theme => ({
"@keyframes bar": {
from: { transform: "translateX(-100%)" },
to: { transform: "translateX(0)" }
},
closeBtn: {
position: "absolute",
right: 0,
top: 0
},
error: {
"& > div": {
"& button span": {
color: "#fff"
},
"&:before": {
backgroundImage: `url(${errorIcon})`
},
backgroundColor: theme.palette.error.main,
color: "#fff"
}
},
progressBar: {
backgroundColor: infoColor,
height: 8,
transform: "translateX(-100%)",
width: "100%"
},
progressBarActive: {
animation: `$bar var(--animationTime) ease both`
},
progressBarContainer: {
borderRadius: "0 0 4px 4px",
bottom: 0,
left: 0,
overflow: "hidden",
position: "absolute",
width: "calc(100%)"
},
progressBarError: {
backgroundColor: darken(theme.palette.error.main, 0.2)
},
progressBarSuccess: {
backgroundColor: darken(successColor, 0.2)
},
progressBarWarning: {
backgroundColor: darken(warningColor, 0.2)
},
snackbar: {
"& > div": {
"&:before": {
backgroundImage: `url(${infoIcon})`,
backgroundRepeat: "no-repeat",
backgroundSize: "contain",
content: "''",
display: "block",
height: 32,
left: 15,
position: "absolute",
top: 13,
width: 32
},
paddingLeft: 60,
position: "relative"
}
},
success: {
"& > div": {
"& button span": {
color: "#fff"
},
"&:before": {
backgroundImage: `url(${successIcon})`
},
backgroundColor: successColor,
color: "#fff"
}
},
text: {
color: "#fff",
paddingTop: 5
},
textInfo: {
paddingTop: 5
},
warning: {
"& > div": {
"& button span": {
color: "#fff"
},
"&:before": {
backgroundImage: `url(${warningIcon})`
},
backgroundColor: warningColor,
color: "#fff"
}
}
}),
{ name: "MessageManager" }
);

View file

@ -343,7 +343,9 @@ export default (colors: IThemeColors): Theme =>
color: colors.font.default
}
},
alignSelf: "baseline"
display: "block",
paddingBottom: 15,
paddingLeft: 0
},
message: {
fontSize: 16
@ -353,8 +355,7 @@ export default (colors: IThemeColors): Theme =>
boxShadow:
"0 6px 10px 0px rgba(0, 0, 0, 0.15), 0 1px 18px 0px rgba(0, 0, 0, 0.12), 0 3px 5px -1px rgba(0, 0, 0, 0.10)",
color: colors.font.default,
display: "grid",
gridTemplateColumns: "1fr 56px",
display: "block",
maxWidth: 480
}
},