mirror of
https://github.com/cheveguerra/whaticket-community.git
synced 2026-04-18 11:49:19 +00:00
new chat with material ui
This commit is contained in:
Binary file not shown.
@@ -19,7 +19,7 @@ const fileStorage = multer.diskStorage({
|
||||
cb(null, "public");
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, new Date().getTime() + "-" + file.originalname);
|
||||
cb(null, new Date().getTime() + "-" + file.originalname.replace(/\s/g, ""));
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -5,19 +5,22 @@ const Sequelize = require("sequelize");
|
||||
exports.getContacts = async (req, res) => {
|
||||
try {
|
||||
const contacts = await Contact.findAll({
|
||||
include: { model: Message, attributes: [] },
|
||||
include: {
|
||||
model: Message,
|
||||
attributes: ["messageBody"],
|
||||
},
|
||||
attributes: {
|
||||
include: [
|
||||
[
|
||||
Sequelize.literal(`(
|
||||
SELECT COUNT(*)
|
||||
FROM messages AS message
|
||||
WHERE
|
||||
message.contactId = contact.id
|
||||
AND
|
||||
message.read = 0
|
||||
|
||||
)`),
|
||||
SELECT COUNT(*)
|
||||
FROM messages AS message
|
||||
WHERE
|
||||
message.contactId = contact.id
|
||||
AND
|
||||
message.read = 0
|
||||
|
||||
)`),
|
||||
"unreadMessages",
|
||||
],
|
||||
],
|
||||
|
||||
@@ -81,15 +81,7 @@ exports.getContactMessages = async (req, res, next) => {
|
||||
|
||||
const serializedMessages = contactMessages.map(message => {
|
||||
return {
|
||||
id: message.id,
|
||||
createdAt: message.createdAt,
|
||||
updatedAt: message.updatedAt,
|
||||
messageBody: message.messageBody,
|
||||
userId: message.userId,
|
||||
ack: message.ack,
|
||||
read: message.read,
|
||||
mediaType: message.mediaType,
|
||||
contactId: message.contactId,
|
||||
...message.dataValues,
|
||||
mediaUrl: `${
|
||||
message.mediaUrl
|
||||
? `http://localhost:8080/public/${message.mediaUrl}`
|
||||
@@ -117,7 +109,7 @@ exports.postCreateContactMessage = async (req, res, next) => {
|
||||
const contact = await Contact.findByPk(contactId);
|
||||
if (media) {
|
||||
const newMedia = MessageMedia.fromFilePath(req.file.path);
|
||||
message.mediaUrl = req.file.filename;
|
||||
message.mediaUrl = req.file.filename.replace(/\s/g, "");
|
||||
if (newMedia.mimetype) {
|
||||
message.mediaType = newMedia.mimetype.split("/")[0];
|
||||
} else {
|
||||
@@ -143,7 +135,14 @@ exports.postCreateContactMessage = async (req, res, next) => {
|
||||
|
||||
io.to(contactId).emit("appMessage", {
|
||||
action: "create",
|
||||
message: newMessage,
|
||||
message: {
|
||||
...newMessage.dataValues,
|
||||
mediaUrl: `${
|
||||
message.mediaUrl
|
||||
? `http://localhost:8080/public/${message.mediaUrl}`
|
||||
: ""
|
||||
}`,
|
||||
},
|
||||
});
|
||||
await setMessagesAsRead(contactId);
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"WABrowserId":"\"E9dnt9Mm/JiFDCMJQHkXBw==\"","WASecretBundle":"{\"key\":\"fHTKtoDcxidboASIs5WV5JKyRrF+SfMktqHXmq/KBJU=\",\"encKey\":\"FrM3OnnEbuEr1JrtKypw5CPSc6rSD5bjbOGstv8ijk4=\",\"macKey\":\"fHTKtoDcxidboASIs5WV5JKyRrF+SfMktqHXmq/KBJU=\"}","WAToken1":"\"Q+xBrzEsm9SAVo3hRyKwC3L/kvNfieq45Jt6/pFePbw=\"","WAToken2":"\"1@WlcfjMFEzc0c9JcHHHAK5BfaDDxigchRdN+GrHmVWsix+b7Od5d9Ls21/JC5ojCqbFBwnzQ5zZ/Fbg==\""}
|
||||
{"WABrowserId":"\"E9dnt9Mm/JiFDCMJQHkXBw==\"","WASecretBundle":"{\"key\":\"fHTKtoDcxidboASIs5WV5JKyRrF+SfMktqHXmq/KBJU=\",\"encKey\":\"FrM3OnnEbuEr1JrtKypw5CPSc6rSD5bjbOGstv8ijk4=\",\"macKey\":\"fHTKtoDcxidboASIs5WV5JKyRrF+SfMktqHXmq/KBJU=\"}","WAToken1":"\"9leF1nILpG4UaO0PWCoKA48h8dSn8UdIPNYZg3bpZv4=\"","WAToken2":"\"1@6OzeSH6s5Y8ozcOu4+l2N7wfaSk6C5Aop8h2BN08xAvvuGCfcuMzctLlOMNDaSw1j2qfFNM4CGjKdA==\""}
|
||||
@@ -184,7 +184,7 @@ const ContactsList = ({ selectedContact, setSelectedContact }) => {
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={contact.name}
|
||||
secondary="last contact message..."
|
||||
secondary={contact.messages[0].messageBody || "oio"}
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
{contact.unreadMessages > 0 && (
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
import React from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import api from "../../../../util/api";
|
||||
import { Picker } from "emoji-mart";
|
||||
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import Paper from "@material-ui/core/Paper";
|
||||
import InputBase from "@material-ui/core/InputBase";
|
||||
import CircularProgress from "@material-ui/core/CircularProgress";
|
||||
import { green } from "@material-ui/core/colors";
|
||||
|
||||
import AttachFileIcon from "@material-ui/icons/AttachFile";
|
||||
import MoodIcon from "@material-ui/icons/Mood";
|
||||
import SendIcon from "@material-ui/icons/Send";
|
||||
import CancelIcon from "@material-ui/icons/Cancel";
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
|
||||
newMessageBox: {
|
||||
background: "#eee",
|
||||
display: "flex",
|
||||
position: "relative",
|
||||
padding: "10px 13px",
|
||||
borderTopLeftRadius: 0,
|
||||
borderTopRightRadius: 0,
|
||||
@@ -35,33 +37,201 @@ const useStyles = makeStyles(theme => ({
|
||||
width: "80%",
|
||||
},
|
||||
|
||||
sendMessageIcon: {
|
||||
opacity: "80%",
|
||||
sendMessageIcons: {
|
||||
color: "grey",
|
||||
margin: 4,
|
||||
alignSelf: "middle",
|
||||
cursor: "pointer",
|
||||
"&:hover": {
|
||||
opacity: "70%",
|
||||
},
|
||||
},
|
||||
|
||||
viewMediaInputWrapper: {
|
||||
display: "flex",
|
||||
padding: "10px 13px",
|
||||
position: "relative",
|
||||
borderTopLeftRadius: 0,
|
||||
borderTopRightRadius: 0,
|
||||
borderBottomLeftRadius: 0,
|
||||
justifyContent: "space-between",
|
||||
backgroundColor: "#eee",
|
||||
},
|
||||
|
||||
emojiBox: {
|
||||
position: "absolute",
|
||||
bottom: 50,
|
||||
borderTop: "1px solid #e8e8e8",
|
||||
},
|
||||
|
||||
circleLoading: {
|
||||
color: green[500],
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: "50%",
|
||||
marginTop: 6,
|
||||
marginBottom: 6,
|
||||
marginLeft: -12,
|
||||
},
|
||||
}));
|
||||
|
||||
const MessagesInput = () => {
|
||||
const MessagesInput = ({ selectedContact }) => {
|
||||
const classes = useStyles();
|
||||
const contactId = selectedContact.id;
|
||||
const userId = localStorage.getItem("userId");
|
||||
const username = localStorage.getItem("username");
|
||||
const token = localStorage.getItem("token");
|
||||
|
||||
return (
|
||||
<Paper variant="outlined" className={classes.newMessageBox}>
|
||||
<MoodIcon className={classes.sendMessageIcon} />
|
||||
<AttachFileIcon className={classes.sendMessageIcon} />
|
||||
<div className={classes.messageInputWrapper}>
|
||||
<InputBase
|
||||
className={classes.messageInput}
|
||||
placeholder="Escreva uma mensagem"
|
||||
const mediaInitialState = { preview: "", raw: "", name: "" };
|
||||
const [media, setMedia] = useState(mediaInitialState);
|
||||
const [inputMessage, setInputMessage] = useState("");
|
||||
const [showEmoji, setShowEmoji] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
setInputMessage("");
|
||||
setShowEmoji(false);
|
||||
setMedia({});
|
||||
};
|
||||
}, [selectedContact]);
|
||||
|
||||
const handleChangeInput = e => {
|
||||
setInputMessage(e.target.value);
|
||||
};
|
||||
|
||||
const handleAddEmoji = e => {
|
||||
let emoji = e.native;
|
||||
setInputMessage(prevState => prevState + emoji);
|
||||
};
|
||||
|
||||
const handleChangeMedia = e => {
|
||||
if (e.target.files.length) {
|
||||
setMedia({
|
||||
preview: URL.createObjectURL(e.target.files[0]),
|
||||
raw: e.target.files[0],
|
||||
name: e.target.files[0].name,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleInputPaste = e => {
|
||||
if (e.clipboardData.files[0]) {
|
||||
setMedia({
|
||||
preview: URL.createObjectURL(e.clipboardData.files[0]),
|
||||
raw: e.clipboardData.files[0],
|
||||
name: e.clipboardData.files[0].name,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleUploadMedia = async e => {
|
||||
setLoading(true);
|
||||
e.preventDefault();
|
||||
const formData = new FormData();
|
||||
formData.append("media", media.raw);
|
||||
formData.append("userId", userId);
|
||||
formData.append("messageBody", media.name);
|
||||
|
||||
try {
|
||||
await api.post(`/messages/${contactId}`, formData, {
|
||||
headers: { Authorization: "Bearer " + token },
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
alert(err);
|
||||
}
|
||||
setLoading(false);
|
||||
setMedia(mediaInitialState);
|
||||
};
|
||||
|
||||
const handleSendMessage = async () => {
|
||||
if (inputMessage.trim() === "") return;
|
||||
const message = {
|
||||
read: 1,
|
||||
userId: userId,
|
||||
mediaUrl: "",
|
||||
messageBody: `${username}: ${inputMessage.trim()}`,
|
||||
};
|
||||
try {
|
||||
await api.post(`/messages/${contactId}`, message, {
|
||||
headers: { Authorization: "Bearer " + token },
|
||||
});
|
||||
} catch (err) {
|
||||
alert(err);
|
||||
}
|
||||
setInputMessage("");
|
||||
setShowEmoji(false);
|
||||
};
|
||||
|
||||
if (media.preview)
|
||||
return (
|
||||
<Paper variant="outlined" className={classes.viewMediaInputWrapper}>
|
||||
<CancelIcon
|
||||
className={classes.sendMessageIcons}
|
||||
onClick={e => setMedia(mediaInitialState)}
|
||||
/>
|
||||
</div>
|
||||
<SendIcon className={classes.sendMessageIcon} />
|
||||
</Paper>
|
||||
);
|
||||
<span>
|
||||
{media.name}
|
||||
{/* <img src={media.preview} alt=""></img> */}
|
||||
</span>
|
||||
{loading ? (
|
||||
<div>
|
||||
<CircularProgress className={classes.circleLoading} />
|
||||
</div>
|
||||
) : null}
|
||||
<SendIcon
|
||||
className={classes.sendMessageIcons}
|
||||
onClick={handleUploadMedia}
|
||||
/>
|
||||
</Paper>
|
||||
);
|
||||
else {
|
||||
return (
|
||||
<Paper variant="outlined" className={classes.newMessageBox}>
|
||||
<MoodIcon
|
||||
className={classes.sendMessageIcons}
|
||||
onClick={e => setShowEmoji(prevState => !prevState)}
|
||||
/>
|
||||
{showEmoji ? (
|
||||
<div className={classes.emojiBox}>
|
||||
<Picker
|
||||
perLine={16}
|
||||
showPreview={false}
|
||||
showSkinTones={false}
|
||||
onSelect={handleAddEmoji}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<label htmlFor="upload-button" className={classes.sendMessageIcons}>
|
||||
<AttachFileIcon />
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
id="upload-button"
|
||||
style={{ display: "none" }}
|
||||
onChange={handleChangeMedia}
|
||||
/>
|
||||
<div className={classes.messageInputWrapper}>
|
||||
<InputBase
|
||||
className={classes.messageInput}
|
||||
placeholder="Escreva uma mensagem"
|
||||
value={inputMessage}
|
||||
onChange={handleChangeInput}
|
||||
onPaste={handleInputPaste}
|
||||
onKeyPress={e => {
|
||||
if (e.key === "Enter") {
|
||||
handleSendMessage();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<SendIcon
|
||||
className={classes.sendMessageIcons}
|
||||
onClick={handleSendMessage}
|
||||
/>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default MessagesInput;
|
||||
|
||||
@@ -129,6 +129,12 @@ const useStyles = makeStyles(theme => ({
|
||||
boxShadow: "0 2px 2px #808888",
|
||||
},
|
||||
|
||||
textContentItem: {
|
||||
alignSelf: "middle",
|
||||
overflowWrap: "break-word",
|
||||
padding: "3px 80px 6px 6px",
|
||||
},
|
||||
|
||||
messageMedia: {
|
||||
objectFit: "cover",
|
||||
width: 250,
|
||||
@@ -139,11 +145,6 @@ const useStyles = makeStyles(theme => ({
|
||||
borderBottomRightRadius: 8,
|
||||
},
|
||||
|
||||
textContentItem: {
|
||||
overflowWrap: "break-word",
|
||||
padding: "0px 60px 10px 0px",
|
||||
},
|
||||
|
||||
timestamp: {
|
||||
fontSize: 11,
|
||||
position: "absolute",
|
||||
@@ -168,6 +169,15 @@ const useStyles = makeStyles(theme => ({
|
||||
alignSelf: "center",
|
||||
marginLeft: "0px",
|
||||
},
|
||||
|
||||
ackIcons: {
|
||||
fontSize: 18,
|
||||
},
|
||||
|
||||
ackDoneAllIcon: {
|
||||
color: green[500],
|
||||
fontSize: 18,
|
||||
},
|
||||
}));
|
||||
|
||||
const MessagesList = ({ selectedContact }) => {
|
||||
@@ -264,8 +274,9 @@ const MessagesList = ({ selectedContact }) => {
|
||||
setMessagesList(prevState => {
|
||||
let aux = [...prevState];
|
||||
let messageIndex = aux.findIndex(message => message.id === id);
|
||||
aux[messageIndex].ack = message.ack;
|
||||
|
||||
if (messageIndex) {
|
||||
aux[messageIndex].ack = message.ack;
|
||||
}
|
||||
return aux;
|
||||
});
|
||||
};
|
||||
@@ -307,16 +318,18 @@ const MessagesList = ({ selectedContact }) => {
|
||||
|
||||
const renderMessageAck = message => {
|
||||
if (message.ack === 0) {
|
||||
return <AccessTimeIcon fontSize="small" />;
|
||||
return <AccessTimeIcon fontSize="small" className={classes.ackIcons} />;
|
||||
}
|
||||
if (message.ack === 1) {
|
||||
return <DoneIcon fontSize="small" />;
|
||||
return <DoneIcon fontSize="small" className={classes.ackIcons} />;
|
||||
}
|
||||
if (message.ack === 2) {
|
||||
return <DoneAllIcon fontSize="small" />;
|
||||
return <DoneAllIcon fontSize="small" className={classes.ackIcons} />;
|
||||
}
|
||||
if (message.ack === 3) {
|
||||
return <DoneAllIcon fontSize="small" color="primary" />;
|
||||
return (
|
||||
<DoneAllIcon fontSize="small" className={classes.ackDoneAllIcon} />
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -372,10 +385,9 @@ const MessagesList = ({ selectedContact }) => {
|
||||
|
||||
const renderMessages = () => {
|
||||
if (messagesList.length > 0) {
|
||||
let viewMessagesList = [];
|
||||
messagesList.forEach((message, index) => {
|
||||
const viewMessagesList = messagesList.map((message, index) => {
|
||||
if (message.userId === 0) {
|
||||
viewMessagesList.push(
|
||||
return [
|
||||
renderDailyTimestamps(message, index),
|
||||
<div className={classes.messageLeft} key={message.id}>
|
||||
{message.mediaUrl && checkMessaageMedia(message)}
|
||||
@@ -387,10 +399,10 @@ const MessagesList = ({ selectedContact }) => {
|
||||
.format("HH:mm")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
</div>,
|
||||
];
|
||||
} else {
|
||||
viewMessagesList.push(
|
||||
return [
|
||||
renderDailyTimestamps(message, index),
|
||||
<div className={classes.messageRight} key={message.id}>
|
||||
{message.mediaUrl && checkMessaageMedia(message)}
|
||||
@@ -403,8 +415,8 @@ const MessagesList = ({ selectedContact }) => {
|
||||
{renderMessageAck(message)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
</div>,
|
||||
];
|
||||
}
|
||||
});
|
||||
return viewMessagesList;
|
||||
|
||||
Reference in New Issue
Block a user