feat: added markdown styles in messaages

feat: added option to show / hide agent name
This commit is contained in:
canove
2020-11-29 13:37:55 -03:00
parent 36098bf12d
commit ce1a0f48e2
10 changed files with 106 additions and 32 deletions

View File

@@ -15,11 +15,11 @@
"formik": "^2.2.0",
"i18next": "^19.8.2",
"i18next-browser-languagedetector": "^6.0.1",
"markdown-to-jsx": "^7.1.0",
"mic-recorder-to-mp3": "^2.2.2",
"qrcode.react": "^1.0.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-linkify": "^1.0.0-alpha",
"react-modal-image": "^2.5.0",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.3",

View File

@@ -12,9 +12,10 @@ import Button from "@material-ui/core/Button";
import Paper from "@material-ui/core/Paper";
import { i18n } from "../../translate/i18n";
import LinkifyWithTargetBlank from "../LinkifyWithTargetBlank";
import ContactModal from "../ContactModal";
import ContactDrawerSkeleton from "../ContactDrawerSkeleton";
import MarkdownWrapper from "../MarkdownWrapper";
const drawerWidth = 320;
@@ -149,11 +150,9 @@ const ContactDrawer = ({ open, handleDrawerClose, contact, loading }) => {
className={classes.contactExtraInfo}
>
<InputLabel>{info.name}</InputLabel>
<LinkifyWithTargetBlank>
<Typography noWrap style={{ paddingTop: 2 }}>
{info.value}
</Typography>
</LinkifyWithTargetBlank>
<Typography component="div" noWrap style={{ paddingTop: 2 }}>
<MarkdownWrapper>{info.value}</MarkdownWrapper>
</Typography>
</Paper>
))}
</Paper>

View File

@@ -1,14 +0,0 @@
import React from "react";
import Linkify from "react-linkify";
const componentDecorator = (href, text, key) => (
<a href={href} key={key} target="_blank" rel="noopener noreferrer">
{text}
</a>
);
const LinkifyWithTargetBlank = ({ children }) => {
return <Linkify componentDecorator={componentDecorator}>{children}</Linkify>;
};
export default LinkifyWithTargetBlank;

View File

@@ -0,0 +1,46 @@
import React from "react";
import Markdown from "markdown-to-jsx";
import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles(theme => ({
markdownP: {
marginBlockStart: 0,
marginBlockEnd: 0,
},
}));
const CustomLink = ({ children, ...props }) => (
<a {...props} target="_blank" rel="noopener noreferrer">
{children}
</a>
);
const MarkdownWrapper = ({ children }) => {
const classes = useStyles();
const boldRegex = /\*(.*?)\*/g;
if (children && boldRegex.test(children)) {
children = children.replace(boldRegex, "**$1**");
}
return (
<Markdown
options={{
disableParsingRawHTML: true,
overrides: {
a: { component: CustomLink },
p: {
props: {
className: classes.markdownP,
},
},
},
}}
>
{children}
</Markdown>
);
};
export default MarkdownWrapper;

View File

@@ -20,6 +20,7 @@ import ClearIcon from "@material-ui/icons/Clear";
import MicIcon from "@material-ui/icons/Mic";
import CheckCircleOutlineIcon from "@material-ui/icons/CheckCircleOutline";
import HighlightOffIcon from "@material-ui/icons/HighlightOff";
import { FormControlLabel, Switch } from "@material-ui/core";
import { i18n } from "../../translate/i18n";
import api from "../../services/api";
@@ -175,6 +176,17 @@ const MessageInput = ({ ticketStatus }) => {
ReplyMessageContext
);
const [signMessage, setSignMessage] = useState(false);
const storedSignOption = localStorage.getItem("signOption");
useEffect(() => {
if (storedSignOption === "true") setSignMessage(true);
}, [storedSignOption]);
useEffect(() => {
localStorage.setItem("signOption", signMessage);
}, [signMessage]);
useEffect(() => {
inputRef.current.focus();
}, [replyingMessage]);
@@ -251,7 +263,9 @@ const MessageInput = ({ ticketStatus }) => {
read: 1,
fromMe: true,
mediaUrl: "",
body: `${username}: ${inputMessage.trim()}`,
body: signMessage
? `*${username}:*\n${inputMessage.trim()}`
: inputMessage.trim(),
quotedMsg: replyingMessage,
};
try {
@@ -433,6 +447,22 @@ const MessageInput = ({ ticketStatus }) => {
<AttachFileIcon className={classes.sendMessageIcons} />
</IconButton>
</label>
<FormControlLabel
style={{ marginRight: 7, color: "gray" }}
label={i18n.t("messagesInput.signMessage")}
labelPlacement="start"
control={
<Switch
size="small"
checked={signMessage}
onChange={() => {
setSignMessage(prevState => !prevState);
}}
name="showAllTickets"
color="primary"
/>
}
/>
<div className={classes.messageInputWrapper}>
<InputBase
inputRef={input => {

View File

@@ -21,7 +21,7 @@ import {
GetApp,
} from "@material-ui/icons";
import LinkifyWithTargetBlank from "../LinkifyWithTargetBlank";
import MarkdownWrapper from "../MarkdownWrapper";
import ModalImageCors from "../ModalImageCors";
import MessageOptionsMenu from "../MessageOptionsMenu";
import whatsBackground from "../../assets/wa-background.png";
@@ -556,7 +556,7 @@ const MessagesList = ({ ticketId, isGroup, setReplyingMessage }) => {
const viewMessagesList = messagesList.map((message, index) => {
if (!message.fromMe) {
return (
<LinkifyWithTargetBlank key={message.id}>
<React.Fragment key={message.id}>
{renderDailyTimestamps(message, index)}
{renderMessageDivider(message, index)}
<div className={classes.messageLeft}>
@@ -578,17 +578,17 @@ const MessagesList = ({ ticketId, isGroup, setReplyingMessage }) => {
{message.mediaUrl && checkMessageMedia(message)}
<div className={classes.textContentItem}>
{message.quotedMsg && renderQuotedMessage(message)}
{message.body}
<MarkdownWrapper>{message.body}</MarkdownWrapper>
<span className={classes.timestamp}>
{format(parseISO(message.createdAt), "HH:mm")}
</span>
</div>
</div>
</LinkifyWithTargetBlank>
</React.Fragment>
);
} else {
return (
<LinkifyWithTargetBlank key={message.id}>
<React.Fragment key={message.id}>
{renderDailyTimestamps(message, index)}
{renderMessageDivider(message, index)}
<div className={classes.messageRight}>
@@ -616,14 +616,14 @@ const MessagesList = ({ ticketId, isGroup, setReplyingMessage }) => {
/>
)}
{message.quotedMsg && renderQuotedMessage(message)}
{message.body}
<MarkdownWrapper>{message.body}</MarkdownWrapper>
<span className={classes.timestamp}>
{format(parseISO(message.createdAt), "HH:mm")}
{renderMessageAck(message)}
</span>
</div>
</div>
</LinkifyWithTargetBlank>
</React.Fragment>
);
}
});

View File

@@ -18,6 +18,7 @@ import { i18n } from "../../translate/i18n";
import api from "../../services/api";
import ButtonWithSpinner from "../ButtonWithSpinner";
import MarkdownWrapper from "../MarkdownWrapper";
const useStyles = makeStyles(theme => ({
ticket: {
@@ -143,6 +144,7 @@ const TicketListItem = ({ ticket }) => {
></Avatar>
</ListItemAvatar>
<ListItemText
disableTypography
primary={
<span className={classes.contactNameWrapper}>
<Typography
@@ -185,7 +187,11 @@ const TicketListItem = ({ ticket }) => {
variant="body2"
color="textSecondary"
>
{ticket.lastMessage || <br />}
{ticket.lastMessage ? (
<MarkdownWrapper>{ticket.lastMessage}</MarkdownWrapper>
) : (
<br />
)}
</Typography>
<Badge

View File

@@ -287,6 +287,7 @@ const messages = {
messagesInput: {
placeholderOpen: "Type a message",
placeholderClosed: "Reopen or accept this ticket to send a message.",
signMessage: "Sign",
},
contactDrawer: {
header: "Contact details",
@@ -323,6 +324,8 @@ const messages = {
},
},
backendErrors: {
ERR_NO_OTHER_WHATSAPP:
"There must be at lest one default WhatsApp connection.",
ERR_NO_DEF_WAPP_FOUND:
"No default WhatsApp found. Check connections page.",
ERR_WAPP_NOT_INITIALIZED:

View File

@@ -292,6 +292,7 @@ const messages = {
placeholderOpen: "Escribe un mensaje",
placeholderClosed:
"Vuelva a abrir o acepte este ticket para enviar un mensaje.",
signMessage: "Firmar",
},
contactDrawer: {
header: "Detalles del contacto",
@@ -329,6 +330,8 @@ const messages = {
},
},
backendErrors: {
ERR_NO_OTHER_WHATSAPP:
"Debe haber al menos una conexión de WhatsApp predeterminada.",
ERR_NO_DEF_WAPP_FOUND:
"No se encontró WhatsApp predeterminado. Verifique la página de conexiones.",
ERR_WAPP_NOT_INITIALIZED:

View File

@@ -290,6 +290,7 @@ const messages = {
placeholderOpen: "Digite uma mensagem",
placeholderClosed:
"Reabra ou aceite esse ticket para enviar uma mensagem.",
signMessage: "Assinar",
},
contactDrawer: {
header: "Dados do contato",
@@ -302,8 +303,7 @@ const messages = {
delete: "Deletar",
transfer: "Transferir",
confirmationModal: {
title: "Deletar o ticket #",
titleFrom: "do contato ",
title: "Deletar o ticket do contato",
message:
"Atenção! Todas as mensagens relacionadas ao ticket serão perdidas.",
},
@@ -327,6 +327,7 @@ const messages = {
},
},
backendErrors: {
ERR_NO_OTHER_WHATSAPP: "Deve haver pelo menos um WhatsApp padrão.",
ERR_NO_DEF_WAPP_FOUND:
"Nenhum WhatsApp padrão encontrado. Verifique a página de conexões.",
ERR_WAPP_NOT_INITIALIZED: