diff --git a/backend/src/controllers/TicketController.ts b/backend/src/controllers/TicketController.ts index 43d5678..93b03c1 100644 --- a/backend/src/controllers/TicketController.ts +++ b/backend/src/controllers/TicketController.ts @@ -63,7 +63,7 @@ export const store = async (req: Request, res: Response): Promise => { const io = getIO(); io.to(ticket.status).emit("ticket", { - action: "create", + action: "update", ticket }); @@ -100,7 +100,7 @@ export const update = async ( } io.to(ticket.status).to("notification").to(ticketId).emit("ticket", { - action: "updateStatus", + action: "update", ticket }); diff --git a/backend/src/services/TicketServices/ListTicketsService.ts b/backend/src/services/TicketServices/ListTicketsService.ts index cc1938a..b616933 100644 --- a/backend/src/services/TicketServices/ListTicketsService.ts +++ b/backend/src/services/TicketServices/ListTicketsService.ts @@ -34,12 +34,6 @@ const ListTicketsService = async ({ userId, withUnreadMessages }: Request): Promise => { - // const user = await ShowUserService(userId); - - // const userQueueIds = user.queues.map(queue => queue.id); - - // console.log(userQueueIds); - let whereCondition: Filterable["where"] = { [Op.or]: [{ userId }, { status: "pending" }], queueId: { [Op.or]: [queueIds, null] } @@ -60,7 +54,7 @@ const ListTicketsService = async ({ ]; if (showAll === "true") { - whereCondition = {}; + whereCondition = { queueId: { [Op.or]: [queueIds, null] } }; } if (status) { @@ -92,6 +86,7 @@ const ListTicketsService = async ({ ]; whereCondition = { + ...whereCondition, [Op.or]: [ { "$contact.name$": where( diff --git a/frontend/src/components/Ticket/index.js b/frontend/src/components/Ticket/index.js index bf694ee..c2cdd37 100644 --- a/frontend/src/components/Ticket/index.js +++ b/frontend/src/components/Ticket/index.js @@ -90,7 +90,7 @@ const Ticket = () => { socket.on("connect", () => socket.emit("joinChatBox", ticketId)); socket.on("ticket", data => { - if (data.action === "updateStatus") { + if (data.action === "update") { setTicket(data.ticket); } diff --git a/frontend/src/components/TicketsList/index.js b/frontend/src/components/TicketsList/index.js index 6be0232..e8eb0e6 100644 --- a/frontend/src/components/TicketsList/index.js +++ b/frontend/src/components/TicketsList/index.js @@ -7,10 +7,8 @@ import Paper from "@material-ui/core/Paper"; import TicketListItem from "../TicketListItem"; import TicketsListSkeleton from "../TicketsListSkeleton"; -import TicketsListQueueSelect from "../TicketsListQueueSelect"; import useTickets from "../../hooks/useTickets"; -import { useLocalStorage } from "../../hooks/useLocalStorage"; import { i18n } from "../../translate/i18n"; import { ListSubheader } from "@material-ui/core"; import { AuthContext } from "../../context/Auth/AuthContext"; @@ -117,14 +115,14 @@ const reducer = (state, action) => { return [...state]; } - if (action.type === "UPDATE_TICKET_MESSAGES_COUNT") { - const { ticket, searchParam } = action.payload; + if (action.type === "UPDATE_TICKET_UNREAD_MESSAGES") { + const ticket = action.payload; const ticketIndex = state.findIndex(t => t.id === ticket.id); if (ticketIndex !== -1) { state[ticketIndex] = ticket; state.unshift(state.splice(ticketIndex, 1)[0]); - } else if (!searchParam) { + } else { state.unshift(ticket); } @@ -155,53 +153,40 @@ const reducer = (state, action) => { } }; -const TicketsList = ({ status, searchParam, showAll }) => { +const TicketsList = ({ status, searchParam, showAll, selectedQueueIds }) => { const classes = useStyles(); const [pageNumber, setPageNumber] = useState(1); const [ticketsList, dispatch] = useReducer(reducer, []); const { user } = useContext(AuthContext); - const [pendingSelectedQueueIds, setPendingSelectedQueueIds] = useLocalStorage( - "pendingSelectedQueues", - [] - ); - const [openSelectedQueueIds, setOpenSelectedQueueIds] = useLocalStorage( - "openSelectedQueues", - [] - ); useEffect(() => { dispatch({ type: "RESET" }); setPageNumber(1); - }, [ - status, - searchParam, - dispatch, - showAll, - openSelectedQueueIds, - pendingSelectedQueueIds, - ]); + }, [status, searchParam, dispatch, showAll, selectedQueueIds]); const { tickets, hasMore, loading } = useTickets({ pageNumber, searchParam, status, showAll, - queueIds: - status === "open" - ? JSON.stringify(openSelectedQueueIds) - : JSON.stringify(pendingSelectedQueueIds), + queueIds: JSON.stringify(selectedQueueIds), }); useEffect(() => { + if (!status && !searchParam) return; dispatch({ type: "LOAD_TICKETS", payload: tickets, }); - }, [tickets]); + }, [tickets, status, searchParam]); useEffect(() => { const socket = openSocket(process.env.REACT_APP_BACKEND_URL); + const shouldUpdateTicket = ticket => + (!ticket.userId || ticket.userId === user?.id || showAll) && + selectedQueueIds.indexOf(ticket.queueId) > -1; + socket.on("connect", () => { if (status) { socket.emit("joinTickets", status); @@ -218,10 +203,7 @@ const TicketsList = ({ status, searchParam, showAll }) => { }); } - if ( - (data.action === "updateStatus" || data.action === "create") && - (!data.ticket.userId || data.ticket.userId === user?.id || showAll) - ) { + if (data.action === "update" && shouldUpdateTicket(data.ticket)) { dispatch({ type: "UPDATE_TICKET", payload: data.ticket, @@ -234,16 +216,10 @@ const TicketsList = ({ status, searchParam, showAll }) => { }); socket.on("appMessage", data => { - if ( - data.action === "create" && - (!data.ticket.userId || data.ticket.userId === user?.id || showAll) - ) { + if (data.action === "create" && shouldUpdateTicket(data.ticket)) { dispatch({ - type: "UPDATE_TICKET_MESSAGES_COUNT", - payload: { - ticket: data.ticket, - searchParam, - }, + type: "UPDATE_TICKET_UNREAD_MESSAGES", + payload: data.ticket, }); } }); @@ -260,7 +236,7 @@ const TicketsList = ({ status, searchParam, showAll }) => { return () => { socket.disconnect(); }; - }, [status, showAll, user, searchParam]); + }, [status, showAll, user, selectedQueueIds]); const loadMore = () => { setPageNumber(prevState => prevState + 1); @@ -276,15 +252,6 @@ const TicketsList = ({ status, searchParam, showAll }) => { } }; - const handleSelectedQueues = values => { - if (status === "open") { - setOpenSelectedQueueIds(values); - } - if (status === "pending") { - setPendingSelectedQueueIds(values); - } - }; - return (
{ {ticketsList.length}
- )} {status === "pending" && ( @@ -318,11 +280,6 @@ const TicketsList = ({ status, searchParam, showAll }) => { {ticketsList.length} - )} {ticketsList.length === 0 && !loading ? ( diff --git a/frontend/src/components/TicketsManager/index.js b/frontend/src/components/TicketsManager/index.js index 1a24053..3471742 100644 --- a/frontend/src/components/TicketsManager/index.js +++ b/frontend/src/components/TicketsManager/index.js @@ -1,4 +1,4 @@ -import React, { useContext, useState } from "react"; +import React, { useContext, useEffect, useRef, useState } from "react"; import { makeStyles } from "@material-ui/core/styles"; import Paper from "@material-ui/core/Paper"; @@ -8,8 +8,7 @@ import Tabs from "@material-ui/core/Tabs"; import Tab from "@material-ui/core/Tab"; import MoveToInboxIcon from "@material-ui/icons/MoveToInbox"; import CheckBoxIcon from "@material-ui/icons/CheckBox"; -import IconButton from "@material-ui/core/IconButton"; -import AddIcon from "@material-ui/icons/Add"; + import FormControlLabel from "@material-ui/core/FormControlLabel"; import Switch from "@material-ui/core/Switch"; @@ -20,6 +19,9 @@ import TabPanel from "../TabPanel"; import { i18n } from "../../translate/i18n"; import { AuthContext } from "../../context/Auth/AuthContext"; import Can from "../Can"; +import TicketsQueueSelect from "../TicketsQueueSelect"; +import { Button } from "@material-ui/core"; +import { useLocalStorage } from "../../hooks/useLocalStorage"; const useStyles = makeStyles(theme => ({ ticketsWrapper: { @@ -48,17 +50,12 @@ const useStyles = makeStyles(theme => ({ width: 120, }, - ticketsListActions: { - flex: "none", - marginLeft: "auto", - }, - - searchBox: { - position: "relative", + ticketOptionsBox: { display: "flex", + justifyContent: "space-between", alignItems: "center", background: "#fafafa", - padding: "10px 13px", + padding: theme.spacing(1), }, serachInputWrapper: { @@ -67,6 +64,7 @@ const useStyles = makeStyles(theme => ({ display: "flex", borderRadius: 40, padding: 4, + marginRight: theme.spacing(1), }, searchIcon: { @@ -91,15 +89,34 @@ const TicketsManager = () => { const [newTicketModalOpen, setNewTicketModalOpen] = useState(false); const [showAllTickets, setShowAllTickets] = useState(false); const { user } = useContext(AuthContext); + const searchInputRef = useRef(); + const [selectedQueueIds, setSelectedQueueIds] = useLocalStorage( + "selectedQueueIds", + [] + ); - const handleSearchContact = e => { - if (e.target.value === "") { - setSearchParam(e.target.value.toLowerCase()); + useEffect(() => { + if (tab === "search") { + searchInputRef.current.focus(); + } + }, [tab]); + + let searchTimeout; + + const handleSearch = e => { + const searchedTerm = e.target.value.toLowerCase(); + + clearTimeout(searchTimeout); + + if (searchedTerm === "") { + setSearchParam(searchedTerm); setTab("open"); return; } - setSearchParam(e.target.value.toLowerCase()); - setTab("search"); + + searchTimeout = setTimeout(() => { + setSearchParam(searchedTerm); + }, 500); }; const handleChangeTab = (e, newValue) => { @@ -141,57 +158,78 @@ const TicketsManager = () => { /> - -
- - -
-
- ( - setShowAllTickets(prevState => !prevState)} - name="showAllTickets" - color="primary" - /> - } - /> - )} - /> - - setNewTicketModalOpen(true)} - style={{ marginLeft: 20 }} - > - - -
+ + {tab === "search" ? ( +
+ + +
+ ) : ( + <> + + ( + + setShowAllTickets(prevState => !prevState) + } + name="showAllTickets" + color="primary" + /> + } + /> + )} + /> + + )} + setSelectedQueueIds(values)} + />
- - + + - + - +
); diff --git a/frontend/src/components/TicketsListQueueSelect/index.js b/frontend/src/components/TicketsQueueSelect/index.js similarity index 91% rename from frontend/src/components/TicketsListQueueSelect/index.js rename to frontend/src/components/TicketsQueueSelect/index.js index b6ed048..a774eb2 100644 --- a/frontend/src/components/TicketsListQueueSelect/index.js +++ b/frontend/src/components/TicketsQueueSelect/index.js @@ -5,7 +5,7 @@ import FormControl from "@material-ui/core/FormControl"; import Select from "@material-ui/core/Select"; import { Checkbox, ListItemText } from "@material-ui/core"; -const TicketsListQueueSelect = ({ +const TicketsQueueSelect = ({ userQueues, selectedQueueIds = [], onChange, @@ -15,7 +15,7 @@ const TicketsListQueueSelect = ({ }; return ( -
+