418 lines
9.1 KiB
JavaScript
418 lines
9.1 KiB
JavaScript
import React, { useState, useRef, useEffect, useContext } from "react"
|
|
|
|
import { useHistory } from "react-router-dom"
|
|
import { format } from "date-fns"
|
|
//import openSocket from "socket.io-client"
|
|
import { socket } from "../../services/socket"
|
|
import useSound from "use-sound"
|
|
|
|
import Popover from "@material-ui/core/Popover"
|
|
//import IconButton from "@material-ui/core/IconButton";
|
|
import List from "@material-ui/core/List"
|
|
import ListItem from "@material-ui/core/ListItem"
|
|
import ListItemText from "@material-ui/core/ListItemText"
|
|
import { makeStyles } from "@material-ui/core/styles"
|
|
//import Badge from "@material-ui/core/Badge";
|
|
//import ChatIcon from "@material-ui/icons/Chat";
|
|
|
|
import TicketListItem from "../TicketListItem"
|
|
import { i18n } from "../../translate/i18n"
|
|
import useTickets from "../../hooks/useTickets"
|
|
import alertSound from "../../assets/sound.mp3"
|
|
import { AuthContext } from "../../context/Auth/AuthContext"
|
|
|
|
import api from "../../services/api";
|
|
import toastError from "../../errors/toastError";
|
|
|
|
const useStyles = makeStyles(theme => ({
|
|
tabContainer: {
|
|
overflowY: "auto",
|
|
maxHeight: 350,
|
|
...theme.scrollbarStyles,
|
|
},
|
|
popoverPaper: {
|
|
width: "100%",
|
|
maxWidth: 350,
|
|
marginLeft: theme.spacing(2),
|
|
marginRight: theme.spacing(1),
|
|
[theme.breakpoints.down("sm")]: {
|
|
maxWidth: 270,
|
|
},
|
|
},
|
|
noShadow: {
|
|
boxShadow: "none !important",
|
|
},
|
|
}))
|
|
|
|
|
|
let _fifo
|
|
|
|
// const onlineEmitter = async (socket, user) => {
|
|
|
|
// try {
|
|
// clearInterval(_fifo);
|
|
|
|
// socket.emit("online", user.id)
|
|
|
|
// } catch (error) {
|
|
// console.log('error on onlineEmitter: ', error)
|
|
// }
|
|
// finally {
|
|
// _fifo = setInterval(onlineEmitter, 3000);
|
|
// }
|
|
// }
|
|
|
|
// _fifo = setInterval(onlineEmitter, 3000);
|
|
|
|
|
|
|
|
|
|
const NotificationsPopOver = () => {
|
|
const classes = useStyles()
|
|
|
|
const history = useHistory()
|
|
const { user } = useContext(AuthContext)
|
|
const ticketIdUrl = +history.location.pathname.split("/")[2]
|
|
const ticketIdRef = useRef(ticketIdUrl)
|
|
const anchorEl = useRef()
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
const [notifications, setNotifications] = useState([])
|
|
|
|
const [, setDesktopNotifications] = useState([])
|
|
|
|
const { tickets } = useTickets({ withUnreadMessages: "true" })
|
|
const [play] = useSound(alertSound)
|
|
const soundAlertRef = useRef()
|
|
|
|
const historyRef = useRef(history)
|
|
|
|
const { handleLogout } = useContext(AuthContext)
|
|
const [settings, setSettings] = useState([]);
|
|
// const [lastRef] = useState(+history.location.pathname.split("/")[2])
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
soundAlertRef.current = play
|
|
|
|
if (!("Notification" in window)) {
|
|
|
|
} else {
|
|
Notification.requestPermission()
|
|
}
|
|
}, [play])
|
|
|
|
useEffect(() => {
|
|
setNotifications(tickets)
|
|
}, [tickets])
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
|
|
ticketIdRef.current = ticketIdUrl
|
|
}, [ticketIdUrl])
|
|
|
|
useEffect(() => {
|
|
const fetchSession = async () => {
|
|
try {
|
|
const { data } = await api.get('/settings')
|
|
setSettings(data.settings)
|
|
} catch (err) {
|
|
toastError(err)
|
|
}
|
|
}
|
|
fetchSession()
|
|
}, [])
|
|
|
|
const getSettingValue = (key) => {
|
|
const { value } = settings.find((s) => s.key === key)
|
|
return value
|
|
}
|
|
|
|
useEffect(() => {
|
|
|
|
//const socket = openSocket(process.env.REACT_APP_BACKEND_URL)
|
|
|
|
socket.on("reload_page", (data) => {
|
|
|
|
if (user.id === data.userId) {
|
|
|
|
window.location.reload(true)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
socket.on("onlineStatus", (data) => {
|
|
|
|
if (data.action === "logout") {
|
|
|
|
|
|
|
|
if (`${user.id}` === data.userOnlineTime['userId']) {
|
|
|
|
socket.emit("online", { logoutUserId: user.id })
|
|
handleLogout()
|
|
}
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
// socket.on("isOnline", (data) => {
|
|
|
|
// if (data.action === "online") {
|
|
|
|
// if (data.userId === user.id) {
|
|
|
|
// socket.emit("online", user.id)
|
|
// }
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
|
|
if (user.profile === 'user') {
|
|
|
|
if (_fifo) {
|
|
clearInterval(_fifo)
|
|
}
|
|
|
|
_fifo = setInterval(() => {
|
|
socket.emit("online", user.id)
|
|
}, 3000)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
socket.removeAllListeners('reload_page');
|
|
socket.removeAllListeners('onlineStatus');
|
|
}
|
|
}, [user.id, handleLogout, user.profile])
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
//const socket = openSocket(process.env.REACT_APP_BACKEND_URL)
|
|
|
|
const onConnectNotifications = () => {
|
|
socket.emit("joinNotification")
|
|
}
|
|
|
|
onConnectNotifications()
|
|
|
|
socket.on("connect", onConnectNotifications)
|
|
|
|
const onTicketNotifications = data => {
|
|
if (data.action === "updateUnread" || data.action === "delete") {
|
|
|
|
|
|
|
|
setNotifications(prevState => {
|
|
const ticketIndex = prevState.findIndex(t => t.id === data.ticketId)
|
|
if (ticketIndex !== -1) {
|
|
prevState.splice(ticketIndex, 1)
|
|
return [...prevState]
|
|
}
|
|
return prevState
|
|
})
|
|
|
|
setDesktopNotifications(prevState => {
|
|
const notfiticationIndex = prevState.findIndex(
|
|
n => n.tag === String(data.ticketId)
|
|
)
|
|
if (notfiticationIndex !== -1) {
|
|
prevState[notfiticationIndex].close()
|
|
prevState.splice(notfiticationIndex, 1)
|
|
return [...prevState]
|
|
}
|
|
return prevState
|
|
})
|
|
}
|
|
}
|
|
|
|
socket.on("ticket", onTicketNotifications)
|
|
|
|
const onAppMessageNotifications = data => {
|
|
if (
|
|
data.action === "create" &&
|
|
!data.message.read &&
|
|
(data.ticket.userId === user?.id || !data.ticket.userId)
|
|
) {
|
|
|
|
setNotifications(prevState => {
|
|
// prevState.forEach((e)=>{
|
|
//
|
|
// })
|
|
|
|
const ticketIndex = prevState.findIndex(t => t.id === data.ticket.id)
|
|
if (ticketIndex !== -1) {
|
|
|
|
prevState[ticketIndex] = data.ticket
|
|
return [...prevState]
|
|
}
|
|
|
|
return [data.ticket, ...prevState]
|
|
})
|
|
|
|
const shouldNotNotificate = (data.message.ticketId === ticketIdRef.current && document.visibilityState === "visible") ||
|
|
(data.ticket.userId && data.ticket.userId !== user?.id) ||
|
|
data.ticket.isGroup || !data.ticket.userId
|
|
|
|
if (shouldNotNotificate) return
|
|
|
|
handleNotifications(data)
|
|
}
|
|
}
|
|
|
|
socket.on("appMessage", onAppMessageNotifications)
|
|
|
|
socket.on('notifyPeding', data => {
|
|
if (settings?.length > 0 && getSettingValue('notificationTransferQueue') === 'enabled') handleNotifications("", data);
|
|
});
|
|
|
|
return () => {
|
|
socket.off('connect', onConnectNotifications);
|
|
socket.off('ticket', onTicketNotifications);
|
|
socket.off('appMessage', onAppMessageNotifications);
|
|
socket.removeAllListeners('notifyPeding');
|
|
}
|
|
}, [user, settings])
|
|
|
|
const handleNotifications = (data, notify) => {
|
|
let isQueue = false;
|
|
if (!notify) {
|
|
const { message, contact, ticket } = data
|
|
|
|
const options = {
|
|
body: `${message.body} - ${format(new Date(), "HH:mm")}`,
|
|
icon: contact.profilePicUrl,
|
|
tag: ticket.id,
|
|
renotify: true,
|
|
}
|
|
|
|
const notification = new Notification(
|
|
`${i18n.t("tickets.notification.message")} ${contact.name}`,
|
|
options
|
|
)
|
|
|
|
notification.onclick = e => {
|
|
e.preventDefault()
|
|
window.focus()
|
|
historyRef.current.push(`/tickets/${ticket.id}`)
|
|
}
|
|
|
|
setDesktopNotifications(prevState => {
|
|
const notfiticationIndex = prevState.findIndex(
|
|
n => n.tag === notification.tag
|
|
)
|
|
if (notfiticationIndex !== -1) {
|
|
prevState[notfiticationIndex] = notification
|
|
return [...prevState]
|
|
}
|
|
return [notification, ...prevState]
|
|
})
|
|
} else {
|
|
user.queues.forEach(queue => {
|
|
if (queue.id === notify.data?.queue?.id) {
|
|
isQueue = true;
|
|
}
|
|
})
|
|
if (!isQueue) {
|
|
return;
|
|
} else {
|
|
const notification = new Notification(`${i18n.t("tickets.notification.messagePeding")} ${notify.data?.queue?.name}`);
|
|
notification.onclick = e => {
|
|
e.preventDefault()
|
|
window.focus()
|
|
historyRef.current.push(`/tickets`)
|
|
}
|
|
|
|
setDesktopNotifications(prevState => {
|
|
const notfiticationIndex = prevState.findIndex(
|
|
n => n.tag === notification.tag
|
|
)
|
|
if (notfiticationIndex !== -1) {
|
|
prevState[notfiticationIndex] = notification
|
|
return [...prevState]
|
|
}
|
|
return [notification, ...prevState]
|
|
})
|
|
}
|
|
}
|
|
soundAlertRef.current()
|
|
}
|
|
|
|
// const handleClick = () => {
|
|
// setIsOpen(prevState => !prevState);
|
|
// };
|
|
|
|
const handleClickAway = () => {
|
|
setIsOpen(false)
|
|
}
|
|
|
|
const NotificationTicket = ({ children }) => {
|
|
return <div onClick={handleClickAway}>{children}</div>
|
|
}
|
|
|
|
return (
|
|
<>
|
|
{/* <IconButton
|
|
onClick={handleClick}
|
|
// buttonRef={anchorEl}
|
|
ref={anchorEl}
|
|
aria-label="Open Notifications"
|
|
color="inherit"
|
|
>
|
|
<Badge badgeContent={notifications.length} color="secondary">
|
|
<ChatIcon />
|
|
</Badge>
|
|
</IconButton> */}
|
|
<Popover
|
|
disableScrollLock
|
|
open={isOpen}
|
|
anchorEl={anchorEl.current}
|
|
anchorOrigin={{
|
|
vertical: "bottom",
|
|
horizontal: "right",
|
|
}}
|
|
transformOrigin={{
|
|
vertical: "top",
|
|
horizontal: "right",
|
|
}}
|
|
classes={{ paper: classes?.popoverPaper }}
|
|
onClose={handleClickAway}
|
|
>
|
|
<List dense className={classes?.tabContainer}>
|
|
{notifications.length === 0 ? (
|
|
<ListItem>
|
|
<ListItemText>{i18n.t("notifications.noTickets")}</ListItemText>
|
|
</ListItem>
|
|
) : (
|
|
|
|
notifications.map(ticket => (
|
|
<NotificationTicket key={ticket.id}>
|
|
<TicketListItem ticket={ticket} />
|
|
</NotificationTicket>
|
|
))
|
|
)}
|
|
</List>
|
|
|
|
|
|
</Popover>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default NotificationsPopOver
|