diff --git a/TEST_SERVER1/whats/app.js b/TEST_SERVER1/whats/app.js index f8c030e..82416ed 100644 --- a/TEST_SERVER1/whats/app.js +++ b/TEST_SERVER1/whats/app.js @@ -885,11 +885,15 @@ async function handleMessage(msg) { if (msg.fromMe) { + console.log('MSG FROM ME') + msgContact = await client.getContactById(msg.to) } else { + console.log('MSG FROM CLIENT') + console.log('################# RECEIVING MESSAGE FROM: ', msg.from, ' to ', msg.to) msgContact = await msg.getContact() @@ -912,10 +916,10 @@ async function handleMessage(msg) { msgContact: msgContact, chat: chat, quotedMsg: quotedMsg ? quotedMsg.id.id : null, - media: media + media: media, + getContactById: msg.fromMe ? await client.getContactById(msg.to) : await client.getContactById(msg.from) } - socketIo.emit("message_create", data) } diff --git a/backend/package.json b/backend/package.json index 748415c..1c450d6 100644 --- a/backend/package.json +++ b/backend/package.json @@ -17,6 +17,7 @@ "license": "MIT", "dependencies": { "@sentry/node": "^5.29.2", + "@socket.io/redis-adapter": "^7.2.0", "@types/fluent-ffmpeg": "^2.1.21", "@types/pino": "^6.3.4", "axios": "^1.2.3", @@ -41,12 +42,13 @@ "pino": "^6.9.0", "pino-pretty": "^9.1.1", "qrcode-terminal": "^0.12.0", + "redis": "^4.6.13", "reflect-metadata": "^0.1.13", "sequelize": "^5.22.3", "sequelize-cli": "^5.5.1", "sequelize-typescript": "^1.1.0", "sharp": "^0.32.5", - "socket.io": "^3.0.5", + "socket.io": "^4.7.5", "socket.io-client": "^4.5.4", "uuid": "^8.3.2", "whatsapp-web.js": "github:pedroslopez/whatsapp-web.js", @@ -54,6 +56,7 @@ "yup": "^0.32.8" }, "devDependencies": { + "@types/lodash": "4.14", "@types/bcryptjs": "^2.4.2", "@types/bluebird": "^3.5.32", "@types/cookie-parser": "^1.4.2", diff --git a/backend/src/controllers/MessageController.ts b/backend/src/controllers/MessageController.ts index 9555e14..37259da 100644 --- a/backend/src/controllers/MessageController.ts +++ b/backend/src/controllers/MessageController.ts @@ -1,5 +1,4 @@ import { Request, Response } from "express"; -import whatsappOfficialAPI from "../helpers/WhatsappOfficialAPI"; import SetTicketMessagesAsRead from "../helpers/SetTicketMessagesAsRead"; import { getIO } from "../libs/socket"; @@ -22,6 +21,7 @@ import Whatsapp from "../models/Whatsapp"; import checkLastClientMsg24hs from "../helpers/CheckLastClientMsg24hs"; import AppError from "../errors/AppError"; import { get } from "../helpers/RedisClient"; +import createApiClientWhatsOfficial from "../helpers/WhatsappOfficialAPI"; type IndexQuery = { pageNumber: string; @@ -36,7 +36,7 @@ type MessageData = { params: any; }; -export const index = async (req: Request, res: Response): Promise => { +export const index = async (req: Request, res: Response): Promise => { const { ticketId } = req.params; const { pageNumber } = req.query as IndexQuery; @@ -123,7 +123,12 @@ export const store = async (req: Request, res: Response): Promise => { } } else { try { - const { wabaId }: any = await Whatsapp.findByPk(whatsappId); + const { wabaId, whatsappOfficialToken }: any = + await Whatsapp.findByPk(whatsappId); + + const whatsappOfficialAPI = createApiClientWhatsOfficial( + whatsappOfficialToken + ); const { data } = await whatsappOfficialAPI.get( `/${process.env.VERSION}/${wabaId}/message_templates?language=pt_BR` diff --git a/backend/src/controllers/TicketController.ts b/backend/src/controllers/TicketController.ts index 284998d..6d31a5c 100644 --- a/backend/src/controllers/TicketController.ts +++ b/backend/src/controllers/TicketController.ts @@ -114,7 +114,7 @@ export const index = async (req: Request, res: Response): Promise => { withUnreadMessages, unlimited, searchParamContent - }); + }); return res .status(200) diff --git a/backend/src/controllers/WhatsAppController.ts b/backend/src/controllers/WhatsAppController.ts index 3a0dda6..d6c2077 100644 --- a/backend/src/controllers/WhatsAppController.ts +++ b/backend/src/controllers/WhatsAppController.ts @@ -35,14 +35,16 @@ import ShowUserService from "../services/UserServices/ShowUserService"; import fs from "fs"; import receiveWhatsAppMediaOfficialAPI from "../helpers/ReceiveWhatsAppMediaOfficialAPI"; - -import whatsappOfficialAPI from "../helpers/WhatsappOfficialAPI"; + import whatsappOfficialNumberInfo from "../helpers/WhatsappOfficialNumberInfo"; import { getSettingValue } from "../helpers/WhaticketSettings"; import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber"; import SettingTicket from "../models/SettingTicket"; import { Op } from "sequelize"; -import { del, get, set } from "../helpers/RedisClient"; +import { del, get, getKeysByPattern, set, setCBPWhatsappOfficial } from "../helpers/RedisClient"; + +import axios from "axios"; + interface WhatsappData { name: string; @@ -215,6 +217,48 @@ export const weebhook = async ( return res.sendStatus(500); } + if( + req?.body?.entry?.length > 0 && + req?.body?.entry[0]?.changes?.length > 0 && + req?.body?.entry[0]?.changes?.length > 0 && + req?.body?.entry[0]?.changes[0]?.value?.statuses?.length>0 && + req?.body?.entry[0]?.changes[0]?.value?.statuses[0]?.recipient_id && + req?.body?.entry[0]?.changes[0]?.value?.statuses[0]?.conversation?.origin?.type){ + + const company_phone = req?.body?.entry[0]?.changes[0]?.value?.metadata?.display_phone_number + const client_phone = req?.body?.entry[0]?.changes[0]?.value?.statuses[0]?.recipient_id + const conversation_type = req?.body?.entry[0]?.changes[0]?.value?.statuses[0].conversation.origin.type + const billable = req?.body?.entry[0]?.changes[0]?.value?.statuses[0].pricing.billable + const pricing_model = req?.body?.entry[0]?.changes[0]?.value?.statuses[0].pricing.pricing_model + const conversation_type_category = req?.body?.entry[0]?.changes[0]?.value?.statuses[0].pricing.category + const msg_id = req?.body?.entry[0]?.changes[0]?.value?.statuses[0].id + + const _contact_to_exist = await get({ + key: "whatsapp:*", + value: `${company_phone}` + }); + + if(_contact_to_exist){ + + const lst_services_cbp = await getKeysByPattern(company_phone, client_phone, conversation_type_category) + + if(lst_services_cbp && lst_services_cbp.length > 0){ + for(const item of lst_services_cbp){ + if(!item.split(':').includes(conversation_type_category)){ + await setCBP(msg_id, company_phone, client_phone, conversation_type_category, billable, pricing_model) + } + } + }else{ + await setCBP(msg_id, company_phone, client_phone, conversation_type_category, billable, pricing_model) + + } + + console.log('_contact_to_exist: ', _contact_to_exist) + } + + + } + // MESSAGE if (req.body.object) { if ( @@ -288,7 +332,8 @@ export const weebhook = async ( let filename = await receiveWhatsAppMediaOfficialAPI( mediaId, - whatsapp.phoneNumberId + whatsapp.phoneNumberId, + whatsapp.whatsappOfficialToken ); if (!filename) throw new AppError("There was an error"); @@ -377,9 +422,11 @@ export const store = async (req: Request, res: Response): Promise => { } else if (!isOfficial) { phoneNumberId = ""; wabaId = ""; - number = ""; + //number = ""; + } + if(!number){ + number = getNumberFromName(name) } - let invalidPhoneName = validatePhoneName(name); if (invalidPhoneName) { @@ -479,9 +526,11 @@ export const update = async ( } else if (!isOfficial) { whatsappData.phoneNumberId = ""; whatsappData.wabaId = ""; - whatsappData.number = ""; + //whatsappData.number = ""; + } + if(!whatsappData?.number){ + whatsappData.number = getNumberFromName(whatsappData.name) } - const { whatsapp, oldDefaultWhatsapp } = await UpdateWhatsAppService({ whatsappData, whatsappId @@ -626,3 +675,56 @@ const checkWhatsAppData = ({ return { message: "urlApi is required!" }; } }; + +async function setCBP(msg_id: any, company_phone: any, client_phone: any, conversation_type_category: any, billable:string, pricing_model:string) { + const message = await Message.findByPk(msg_id) + + if (message) { + await setCBPWhatsappOfficial(company_phone, client_phone, conversation_type_category, msg_id, `${message.ticketId}`) + + await sendToAPIUsage(msg_id, + company_phone, + client_phone, + conversation_type_category, + `${message.ticketId}`, + billable, + pricing_model + ) + } +} + + + +async function sendToAPIUsage(msg_id: any, company_phone: any, client_phone: any, conversation_type_category: any, ticketId: any, billable:string, pricing_model:string) { + const data = JSON.stringify({ + "companyId": process.env.COMPANY_ID || company_phone, + "companyPhone": company_phone, + "clientPhone": client_phone, + "provider": "meta", + "product": "whatsapp", + "type": conversation_type_category, + "msgId": msg_id, + "ticketId": `${ticketId}`, + "ticketUrl": `${process.env.FRONTEND_URL}/tickets/${ticketId}`, + "billable": billable, + "pricing_model": pricing_model + }); + + const config = { + method: 'post', + url: 'http://172.31.187.24:6008/api/v1/billing/usage-whatsapp', + headers: { + 'Authorization': 'Bearer 2ivck10D3o9qAZi0pkKudVDl9bdEVXY2s8gdxZ0jYgL1DZWTgDz6wDiIjlWgYmJtVOoqf0b42ZTLBRrfo8WoAaScRsujz3jQUNXdchSg0o43YilZGmVhheGJNAeIQRknHEll4nRJ7avcFgmDGoYbEey7TSC8EHS4Z3gzeufYYSfnKNDBwwzBURIQrTOxYFe3tBHsGOzwnuD2lU5tnEx7tr2XRO4zRNYeNY4lMBOFM0mRuyAe4kuqTrKXmJ8As200', + 'Content-Type': 'application/json' + }, + data: data + }; + + try { + const response = await axios(config); + console.log('Response from whatsapp api usage: ',JSON.stringify(response.data)); + } catch (error) { + console.log('Error on try register the whatsapp usage: ', error); + } + +} \ No newline at end of file diff --git a/backend/src/database/migrations/20240507184134-add-identifier-to-users.ts b/backend/src/database/migrations/20240507184134-add-identifier-to-users.ts new file mode 100644 index 0000000..7a783dc --- /dev/null +++ b/backend/src/database/migrations/20240507184134-add-identifier-to-users.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Users", "identifier", { + type: DataTypes.STRING, + allowNull: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Users", "identifier"); + } +}; \ No newline at end of file diff --git a/backend/src/database/migrations/20240610183159-add-column-whatsappOfficialToken-to-whatsapp.ts b/backend/src/database/migrations/20240610183159-add-column-whatsappOfficialToken-to-whatsapp.ts new file mode 100644 index 0000000..bf5a724 --- /dev/null +++ b/backend/src/database/migrations/20240610183159-add-column-whatsappOfficialToken-to-whatsapp.ts @@ -0,0 +1,14 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Whatsapps", "whatsappOfficialToken", { + type: DataTypes.STRING, + allowNull: true + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Whatsapps", "whatsappOfficialToken"); + } +}; diff --git a/backend/src/helpers/ReceiveWhatsAppMediaOfficialAPI.ts b/backend/src/helpers/ReceiveWhatsAppMediaOfficialAPI.ts index fec1aa9..5cf3fc3 100644 --- a/backend/src/helpers/ReceiveWhatsAppMediaOfficialAPI.ts +++ b/backend/src/helpers/ReceiveWhatsAppMediaOfficialAPI.ts @@ -10,7 +10,6 @@ import { import { writeFile } from "fs"; -import whatsappOfficialAPI from "./WhatsappOfficialAPI"; import path, { join } from "path"; import { promisify } from "util"; @@ -18,14 +17,20 @@ import mime from "mime"; import fs from "fs"; import { response } from "express"; +import createApiClientWhatsOfficial from "./WhatsappOfficialAPI"; const writeFileAsync = promisify(writeFile); async function receiveWhatsAppMediaOfficialAPI( mediaId: string, - phoneNumberId: string + phoneNumberId: string, + whatsappOfficialToken: string ) { try { + const whatsappOfficialAPI = createApiClientWhatsOfficial( + whatsappOfficialToken + ); + const { data } = await whatsappOfficialAPI.get( `/${process.env.VERSION}/${mediaId}?phone_number_id=${phoneNumberId}` ); @@ -33,7 +38,7 @@ async function receiveWhatsAppMediaOfficialAPI( if (data && data?.url) { const config: any = { headers: { - Authorization: `Bearer ${process.env.TOKEN}` + Authorization: `Bearer ${whatsappOfficialToken}` }, responseType: "arraybuffer" }; @@ -44,7 +49,7 @@ async function receiveWhatsAppMediaOfficialAPI( const ext = response.headers["content-type"].split("/")[1]; - const filename_ext = `${filename}.${ext}`; + const filename_ext = `${filename}.${ext}`; const destPath = path.join( __dirname, diff --git a/backend/src/helpers/RedisClient.ts b/backend/src/helpers/RedisClient.ts index 5c7c6d0..58df68b 100644 --- a/backend/src/helpers/RedisClient.ts +++ b/backend/src/helpers/RedisClient.ts @@ -158,6 +158,46 @@ export async function findObject( return result; } +export async function setCBPWhatsappOfficial( + company_phone:string, + client_phone:string, + conversation_type:string, + msg_id: string, + ticketId?: string +) { + const key = `company_phone:${company_phone}:client_phone:${client_phone}:conversation_type:${conversation_type}`; + const result = await redis.hmset( + key, + "company_phone", + company_phone, + "client_phone", + client_phone, + "conversation_type", + conversation_type, + "msg_id", + msg_id, + "ticketId", + ticketId + ); + + await redis.expire(key, 86400); +} + + +export async function getKeysByPattern(company_phone:string, client_phone:string, conversation_type:string,) { + const pattern = `company_phone:${company_phone}:client_phone:${client_phone}:conversation_type:${conversation_type}*`; + const keys = []; + let cursor = "0"; + + do { + const result = await redis.scan(cursor, "MATCH", pattern, "COUNT", 100); + cursor = result[0]; + keys.push(...result[1]); + } while (cursor !== "0"); + + return keys; +} + export async function deleteObject( whatsappId: string, contactId: string, diff --git a/backend/src/helpers/SchedulingNotifySendMessage.ts b/backend/src/helpers/SchedulingNotifySendMessage.ts index 01f1c0b..d75a903 100644 --- a/backend/src/helpers/SchedulingNotifySendMessage.ts +++ b/backend/src/helpers/SchedulingNotifySendMessage.ts @@ -104,16 +104,16 @@ const monitor = async () => { stdout = stdout[1].trim().split(/\s+/); // DISK SPACE MONITORING - const io = getIO(); - io.emit("diskSpaceMonit", { - action: "update", - diskSpace: { - size: stdout[1], - used: stdout[2], - available: stdout[3], - use: stdout[4] - } - }); + // const io = getIO(); + // io.emit("diskSpaceMonit", { + // action: "update", + // diskSpace: { + // size: stdout[1], + // used: stdout[2], + // available: stdout[3], + // use: stdout[4] + // } + // }); let data: any = {}; diff --git a/backend/src/helpers/SetMessageAsRead.ts b/backend/src/helpers/SetMessageAsRead.ts index d29d297..e7aef63 100644 --- a/backend/src/helpers/SetMessageAsRead.ts +++ b/backend/src/helpers/SetMessageAsRead.ts @@ -3,9 +3,7 @@ import { getWbot } from "../libs/wbot"; import Message from "../models/Message" import Ticket from "../models/Ticket"; import Whatsapp from "../models/Whatsapp"; -import endPointQuery from "./old_EndPointQuery"; - -import whatsappOfficialAPI from "./WhatsappOfficialAPI"; +import endPointQuery from "./old_EndPointQuery"; export async function setMessageAsRead(ticket: Ticket) { if (ticket?.phoneNumberId) { diff --git a/backend/src/helpers/WhatsappOfficialAPI.ts b/backend/src/helpers/WhatsappOfficialAPI.ts index 03b27a4..3412751 100644 --- a/backend/src/helpers/WhatsappOfficialAPI.ts +++ b/backend/src/helpers/WhatsappOfficialAPI.ts @@ -3,14 +3,28 @@ import https from "https" import http from "http" -const api = axios.create({ - baseURL: process.env.URL_WHATSAPP_API, - headers: { - Accept: "application/json", - Authorization: `Bearer ${process.env.TOKEN}` - }, - httpAgent: new http.Agent({ keepAlive: true }), - httpsAgent: new https.Agent({ keepAlive: true }) -}); +// const api = axios.create({ +// baseURL: process.env.URL_WHATSAPP_API, +// headers: { +// Accept: "application/json", +// Authorization: `Bearer ${process.env.TOKEN}` +// }, +// httpAgent: new http.Agent({ keepAlive: true }), +// httpsAgent: new https.Agent({ keepAlive: true }) +// }); -export default api; +// export default api; + +const createApiClientWhatsOfficial = (token: string) => { + return axios.create({ + baseURL: process.env.URL_WHATSAPP_API, + headers: { + Accept: "application/json", + Authorization: `Bearer ${token}` + }, + httpAgent: new http.Agent({ keepAlive: true }), + httpsAgent: new https.Agent({ keepAlive: true }) + }); +}; + +export default createApiClientWhatsOfficial; diff --git a/backend/src/helpers/WhatsappOfficialNumberInfo.ts b/backend/src/helpers/WhatsappOfficialNumberInfo.ts index 77ae2b3..9e08ea2 100644 --- a/backend/src/helpers/WhatsappOfficialNumberInfo.ts +++ b/backend/src/helpers/WhatsappOfficialNumberInfo.ts @@ -1,7 +1,15 @@ -import whatsappOfficialAPI from "./WhatsappOfficialAPI"; +import Whatsapp from "../models/Whatsapp"; +import createApiClientWhatsOfficial from "./WhatsappOfficialAPI"; async function whatsappOfficialNumberInfo(wabaId: string) { try { + const { whatsappOfficialToken }: any = await Whatsapp.findOne({ + where: { wabaId } + }); + + const whatsappOfficialAPI = createApiClientWhatsOfficial( + whatsappOfficialToken + ); const { data } = await whatsappOfficialAPI.get( `/${process.env.VERSION}/${wabaId}/phone_numbers` ); diff --git a/backend/src/helpers/controllByNumber.ts b/backend/src/helpers/controllByNumber.ts index d74afa4..6ffad64 100644 --- a/backend/src/helpers/controllByNumber.ts +++ b/backend/src/helpers/controllByNumber.ts @@ -1,37 +1,58 @@ +import { values } from "sequelize/types/lib/operators"; +import Ticket from "../models/Ticket"; import { get, set } from "./RedisClient"; +import { getIO } from "../libs/socket"; +import UpdateTicketService from "../services/TicketServices/UpdateTicketService"; +import { v4 as uuidv4 } from "uuid"; async function controllByNumber() { - let tickets = await get({ key: "remote:ticketId*", parse: false }); + let tickets = await get({ key: "remote:ticketId*", parse: false }); if (!tickets) return { ticketIds: [], tickets: null }; let controll: any[] = []; for (const ticket of tickets) { - let match = ticket.match(/"whatsappId":(\d+)/); - let whatsappId = match ? match[1] : null; + let match = ticket?.match(/"whatsappId":(\d+)/); + let whatsappId = match ? match[1] : null; const whatsapp = await get({ key: `whatsapp:${whatsappId}` }); - match = whatsapp.match(/"number":"(\d+)"/); - let number = match ? match[1] : null; + match = whatsapp?.match(/"number":"(\d+)"/); + let number = match ? match[1] : null; - match = ticket.match(/"id":(\d+)/); - let ticketId = match ? match[1] : null; + match = ticket?.match(/"id":(\d+)/); + let ticketId = match ? match[1] : null; number = JSON.parse(number); - ticketId = JSON.parse(ticketId); + ticketId = JSON.parse(ticketId); - const index = controll.findIndex((c: any) => c.number == number); + const index = controll?.findIndex((c: any) => c.number == number); if (index == -1) { - controll.push({ ticketId, number }); + controll?.push({ ticketId, number }); } } - const ticketIds = controll.map((c: any) => c.ticketId); + const ticketIds = controll?.map((c: any) => c.ticketId); + + //console.log("=======> ticketIds: ", ticketIds); + + for (const ticketId of ticketIds) { + const ticket: any = await Ticket.findByPk(ticketId); + if(ticket){ + const { status } = ticket; + + if (status && status == "pending") { + await UpdateTicketService({ + ticketData: { statusChatEnd: uuidv4() }, + ticketId: ticket.id + }); + } + } + } set(`remote:controll`, JSON.stringify(ticketIds)); diff --git a/backend/src/helpers/sendWhatsAppMessageOfficialAPI.ts b/backend/src/helpers/sendWhatsAppMessageOfficialAPI.ts index ec87574..91d9967 100644 --- a/backend/src/helpers/sendWhatsAppMessageOfficialAPI.ts +++ b/backend/src/helpers/sendWhatsAppMessageOfficialAPI.ts @@ -1,3 +1,4 @@ +import { where } from "sequelize"; import { getIO } from "../libs/socket"; import Contact from "../models/Contact"; import Ticket from "../models/Ticket"; @@ -5,8 +6,9 @@ import { isValidMsg, verifyMessage } from "../services/WbotServices/wbotMessageListener"; - -import whatsappOfficialAPI from "./WhatsappOfficialAPI"; +import { get } from "./RedisClient"; +import createApiClientWhatsOfficial from "./WhatsappOfficialAPI"; +import Whatsapp from "../models/Whatsapp"; async function sendWhatsAppMessageOfficialAPI( ticket: Ticket, @@ -52,8 +54,15 @@ async function sendWhatsAppMessageOfficialAPI( return; } - console.log("SEND MESSAGE: ", JSON.stringify(data, null,2)); - + const { whatsappOfficialToken }: any = await Whatsapp.findOne({ + where: { phoneNumberId } + }); + + console.log("SEND MESSAGE: ", JSON.stringify(data, null, 2)); + const whatsappOfficialAPI = createApiClientWhatsOfficial( + whatsappOfficialToken + ); + whatsappOfficialAPI .post(`/${process.env.VERSION}/${phoneNumberId}/messages`, data) .then(response => { diff --git a/backend/src/helpers/sendWhatsMediaOfficialAPI.ts b/backend/src/helpers/sendWhatsMediaOfficialAPI.ts index d2c6390..dff553e 100644 --- a/backend/src/helpers/sendWhatsMediaOfficialAPI.ts +++ b/backend/src/helpers/sendWhatsMediaOfficialAPI.ts @@ -12,13 +12,14 @@ import { import ffmpeg from "fluent-ffmpeg"; import fs from "fs"; -import whatsappOfficialAPI from "./WhatsappOfficialAPI"; import path from "path"; import { convertAudioToOgg } from "../helpers/ConvertAudio"; import { bytesToMB } from "./BytesToMB"; import isThisHour from "date-fns/esm/isThisHour/index"; import AppError from "../errors/AppError"; +import createApiClientWhatsOfficial from "./WhatsappOfficialAPI"; +import Whatsapp from "../models/Whatsapp"; async function sendWhatsMediaOfficialAPI( ticket: Ticket, @@ -79,6 +80,14 @@ async function sendWhatsMediaOfficialAPI( return; } + const { whatsappOfficialToken }: any = await Whatsapp.findOne({ + where: { phoneNumberId } + }); + + const whatsappOfficialAPI = createApiClientWhatsOfficial( + whatsappOfficialToken + ); + whatsappOfficialAPI .post(`/${process.env.VERSION}/${phoneNumberId}/messages`, data) .then(response => { diff --git a/backend/src/libs/socket.ts b/backend/src/libs/socket.ts index 65382d6..291ceaa 100644 --- a/backend/src/libs/socket.ts +++ b/backend/src/libs/socket.ts @@ -3,6 +3,9 @@ import { Server } from "http"; import AppError from "../errors/AppError"; import { logger } from "../utils/logger"; +import { createAdapter } from "@socket.io/redis-adapter"; +import { createClient } from 'redis'; + import { v4 as uuidv4 } from "uuid"; import ListUserParamiterService from "../services/UserServices/ListUserParamiterService"; import { @@ -27,6 +30,7 @@ import { } from "../services/WbotServices/wbotMessageListener"; import { join } from "path"; import Whatsapp from "../models/Whatsapp"; +import { get } from "../helpers/RedisClient" let count: number = 0; let listOnline: any[] = []; @@ -42,16 +46,32 @@ let dateTime = splitDateTime( new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR })) ); -export const initIO = (httpServer: Server): SocketIO => { + +const pubClient = createClient({ url: 'redis://172.31.187.29:6379' }); +const subClient = pubClient.duplicate(); + + +pubClient.connect().catch(console.error); +subClient.connect().catch(console.error); + + +export const initIO = (httpServer: Server): SocketIO => { + io = new SocketIO(httpServer, { cors: { - origin: process.env.FRONTEND_URL + origin: process.env.FRONTEND_URL, + //allowedHeaders: ["my-custom-header"], + //credentials: true }, - maxHttpBufferSize: 1e8 - }); + maxHttpBufferSize: 1e8, + // pingInterval: 25000, + // pingTimeout: 60000, + // adapter: createAdapter(pubClient, subClient) + }); + io.on("connection", socket => { - logger.info("Client Connected"); + logger.info("Client Connected"); socket.on("joinWhatsSession", (whatsappId: string) => { logger.info(`A client joined a joinWhatsSession channel: ${whatsappId}`); @@ -107,6 +127,7 @@ export const initIO = (httpServer: Server): SocketIO => { socket.on("online", (userId: any) => { // console.log('userId: ', userId) + return obj.uuid = uuidv4(); if (userId.logoutUserId) { @@ -233,13 +254,18 @@ export const initIO = (httpServer: Server): SocketIO => { if (rooms && rooms.size == 2 && ![...rooms][1].startsWith("session_")) return; - let whatsappIds: any = await Whatsapp.findAll({ - attributes: ["id"], - raw: true + let whatsappIds = await get({ + key: "whatsapp:*", + parse: true }); + // let whatsappIds: any = await Whatsapp.findAll({ + // attributes: ["id"], + // raw: true + // }); + if (whatsappIds && whatsappIds.length > 0) { - whatsappIds = whatsappIds.map((e: any) => `${e.id}`); + // whatsappIds = whatsappIds.map((e: any) => `${e.id}`); console.log( "whatsappIds whatsappIds whatsappIds whatsappIds whatsappIds: ", diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index a7e3d47..1be891d 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -51,6 +51,9 @@ class User extends Model { @Column transferToOtherQueues: boolean; + @Column + identifier: string; + @Default("admin") @Column profile: string; diff --git a/backend/src/models/Whatsapp.ts b/backend/src/models/Whatsapp.ts index 28cae6a..60ff078 100644 --- a/backend/src/models/Whatsapp.ts +++ b/backend/src/models/Whatsapp.ts @@ -87,6 +87,9 @@ class Whatsapp extends Model { @UpdatedAt updatedAt: Date; + @Column + whatsappOfficialToken: string; + @HasMany(() => Ticket) tickets: Ticket[]; diff --git a/backend/src/services/TicketServices/FindOrCreateTicketService.ts b/backend/src/services/TicketServices/FindOrCreateTicketService.ts index fb14349..9ab8cdd 100644 --- a/backend/src/services/TicketServices/FindOrCreateTicketService.ts +++ b/backend/src/services/TicketServices/FindOrCreateTicketService.ts @@ -60,10 +60,11 @@ const FindOrCreateTicketService = async ( order: [["updatedAt", "DESC"]] }); - if (ticket) { + if (ticket) { await ticket.update({ status: "pending", userId: null, + queueId: null, unreadMessages }); } @@ -96,7 +97,12 @@ const FindOrCreateTicketService = async ( if (!ticket) { let status = "pending"; - if (queues.length > 1 && !botInfo.isOnQueue && !queueId) { + if ( + queues.length > 1 && + !botInfo.isOnQueue && + !queueId && + !groupContact + ) { status = "queueChoice"; } diff --git a/backend/src/services/TicketServices/FindOrCreateTicketServiceBot.ts b/backend/src/services/TicketServices/FindOrCreateTicketServiceBot.ts index 866d13d..8b13c40 100644 --- a/backend/src/services/TicketServices/FindOrCreateTicketServiceBot.ts +++ b/backend/src/services/TicketServices/FindOrCreateTicketServiceBot.ts @@ -6,173 +6,165 @@ import Ticket from "../../models/Ticket"; import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService"; import ShowTicketService from "./ShowTicketService"; import AppError from "../../errors/AppError"; -import { userInfo } from "os"; +import { userInfo } from "os"; import ShowQueueService from "../QueueService/ShowQueueService"; import UpdateTicketService from "./UpdateTicketService"; import { getSettingValue } from "../../helpers/WhaticketSettings" import ListWhatsAppsNumber from "../WhatsappService/ListWhatsAppsNumber" +import { getSettingValue } from "../../helpers/WhaticketSettings"; +import ListWhatsAppsNumber from "../WhatsappService/ListWhatsAppsNumber"; const FindOrCreateTicketServiceBot = async ( - contact: Contact, - whatsappId: number, - unreadMessages: number, - groupContact?: Contact + contact: Contact, + whatsappId: number, + unreadMessages: number, + groupContact?: Contact ): Promise => { + try { + // let ticket = await Ticket.findOne({ + // where: { + // status: { + // [Op.or]: ["open", "pending", "queueChoice"] + // }, + // contactId: groupContact ? groupContact.id : contact.id + // } + // }); - try { + let ticket; - // let ticket = await Ticket.findOne({ - // where: { - // status: { - // [Op.or]: ["open", "pending", "queueChoice"] - // }, - // contactId: groupContact ? groupContact.id : contact.id - // } - // }); + if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") { + let whats = await ListWhatsAppsNumber(whatsappId); - let ticket; - - if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") { - - let whats = await ListWhatsAppsNumber(whatsappId); - - ticket = await Ticket.findOne({ - where: { - status: { - [Op.or]: ["open", "pending", "queueChoice"] - }, - contactId: groupContact ? groupContact.id : contact.id, - whatsappId: { [Op.in]: whats.whatsapps.map((w: any) => w.id) } - } - }); - } else { - ticket = await Ticket.findOne({ - where: { - status: { - [Op.or]: ["open", "pending", "queueChoice"] - }, - contactId: groupContact ? groupContact.id : contact.id - } - }); + ticket = await Ticket.findOne({ + where: { + status: { + [Op.or]: ["open", "pending", "queueChoice"] + }, + contactId: groupContact ? groupContact.id : contact.id, + whatsappId: { [Op.in]: whats.whatsapps.map((w: any) => w.id) } } - - const { queues, greetingMessage, phoneNumberId } = - await ShowWhatsAppService(whatsappId); - - - //Habilitar esse caso queira usar o bot - const botInfo = await BotIsOnQueue('botqueue') - // const botInfo = { isOnQueue: false } - - - - if (ticket) { - await ticket.update({ unreadMessages }); + }); + } else { + ticket = await Ticket.findOne({ + where: { + status: { + [Op.or]: ["open", "pending", "queueChoice"] + }, + contactId: groupContact ? groupContact.id : contact.id } - - // if (!ticket && groupContact) { - // ticket = await Ticket.findOne({ - // where: { - // contactId: groupContact.id - // }, - // order: [["updatedAt", "DESC"]] - // }); - - - - // if (ticket) { - - // await ticket.update({ - // status: "pending", - // userId: null, - // unreadMessages - // }); - // } - // } - - if (!ticket && !groupContact) { - - console.log('BOT CREATING OR REOPENING THE TICKET') - - ticket = await Ticket.findOne({ - where: { - contactId: contact.id, - userId: botInfo.userIdBot, - whatsappId: whatsappId - }, - order: [["updatedAt", "DESC"]] - }); - - if (ticket) { - - await ticket.update({ - status: "open", - userId: botInfo.userIdBot, - unreadMessages - }); - - console.log('lxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') - - await dialogFlowStartContext(contact, ticket, botInfo); - - } - } - - let created = false - - if (!ticket) { - - created = true - - let status = "open" - - if (queues.length > 1 && !botInfo.isOnQueue) { - status = "queueChoice" - } - - ticket = await Ticket.create({ - contactId: groupContact ? groupContact.id : contact.id, - status: status, - userId: botInfo.userIdBot, - isGroup: !!groupContact, - unreadMessages, - whatsappId, - phoneNumberId - }); - - console.log('yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy') - - await dialogFlowStartContext(contact, ticket, botInfo); - - } - - ticket = await ShowTicketService(ticket.id); - - return { ticket, created }; - - } catch (error: any) { - console.error('===> Error on FindOrCreateTicketServiceBot.ts file: \n', error) - throw new AppError(error.message); + }); } + + const { queues, greetingMessage, phoneNumberId } = + await ShowWhatsAppService(whatsappId); + + //Habilitar esse caso queira usar o bot + const botInfo = await BotIsOnQueue("botqueue"); + // const botInfo = { isOnQueue: false } + + if (ticket) { + await ticket.update({ unreadMessages }); + } + + // if (!ticket && groupContact) { + // ticket = await Ticket.findOne({ + // where: { + // contactId: groupContact.id + // }, + // order: [["updatedAt", "DESC"]] + // }); + + // if (ticket) { + + // await ticket.update({ + // status: "pending", + // userId: null, + // unreadMessages + // }); + // } + // } + + if (!ticket && !groupContact) { + console.log("BOT CREATING OR REOPENING THE TICKET"); + + ticket = await Ticket.findOne({ + where: { + contactId: contact.id, + userId: botInfo.userIdBot, + whatsappId: whatsappId + }, + order: [["updatedAt", "DESC"]] + }); + + if (ticket) { + await ticket.update({ + status: "open", + userId: botInfo.userIdBot, + unreadMessages + }); + + console.log("lxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + + await dialogFlowStartContext(contact, ticket, botInfo); + } + } + + let created = false; + + if (!ticket) { + created = true; + + let status = "open"; + + if (queues.length > 1 && !botInfo.isOnQueue) { + status = "queueChoice"; + } + + ticket = await Ticket.create({ + contactId: groupContact ? groupContact.id : contact.id, + status: status, + userId: botInfo.userIdBot, + isGroup: !!groupContact, + unreadMessages, + whatsappId, + phoneNumberId + }); + + console.log("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); + + await dialogFlowStartContext(contact, ticket, botInfo); + } + + ticket = await ShowTicketService(ticket.id); + + return { ticket, created }; + } catch (error: any) { + console.error( + "===> Error on FindOrCreateTicketServiceBot.ts file: \n", + error + ); + throw new AppError(error.message); + } }; export default FindOrCreateTicketServiceBot; -async function dialogFlowStartContext(contact: Contact, ticket: Ticket, botInfo: any) { +async function dialogFlowStartContext( + contact: Contact, + ticket: Ticket, + botInfo: any +) { + let msg: any = { type: "chat", from: `${contact.number}@c.us`, body: "0" }; - let msg: any = { type: 'chat', from: `${contact.number}@c.us`, body: '0' }; + let queue = await ShowQueueService(botInfo.botQueueId); - let queue = await ShowQueueService(botInfo.botQueueId); + await UpdateTicketService({ + ticketData: { queueId: queue.id }, + ticketId: ticket.id + }); - await UpdateTicketService({ - ticketData: { queueId: queue.id }, - ticketId: ticket.id - }); + ticket = await ShowTicketService(ticket.id); - ticket = await ShowTicketService(ticket.id); - - // await sendDialogflowAnswer(ticket.whatsappId, ticket, msg, contact, false); - + // await sendDialogflowAnswer(ticket.whatsappId, ticket, msg, contact, false); } - diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index 044a3e7..948a412 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -469,13 +469,11 @@ const verifyMediaMessage = async ( phoneNumberId: msg?.phoneNumberId, fromAgent: false }; - // if ( - // messageData.mediaType === "video" || - // (messageData.mediaType === "audio" && - // getSettingValue("blockAudioVideoMedia")?.value === "enabled") - // ) { - // mediaAuthorized = false; - // } + if(getSettingValue('blockAudioVideoMedia')?.value === 'enabled'){ + if( messageData.mediaType === 'video' || messageData.mediaType === 'audio' ){ + mediaAuthorized = false; + } + } if (msg?.fromMe) { messageData = { ...messageData, fromAgent: true }; } @@ -648,7 +646,6 @@ const verifyMessage = async ( quotedMsgId: quotedMsg, phoneNumberId: msg?.phoneNumberId }; - if (msg?.fromMe) { const botInfo = await BotIsOnQueue("botqueue"); @@ -686,6 +683,12 @@ const verifyQueue = async ( ticket: Ticket, contact: Contact ) => { + + if(ticket?.isGroup){ + + return + } + const { queues, greetingMessage } = await ShowWhatsAppService(wbot.id!); let selectedOption = null; @@ -1017,7 +1020,7 @@ const handleMessage = async ( try { let msgContact: any = wbot.msgContact; - // let groupContact: Contact | undefined; + let groupContact: Contact | undefined; if (msg.fromMe) { // messages sent automatically by wbot have a special character in front of it @@ -1057,18 +1060,21 @@ const handleMessage = async ( // console.log('----------> chat: ', JSON.parse(JSON.stringify(chat))) - // if (chat.isGroup) { - // let msgGroupContact; - // if (msg.fromMe) { - // msgGroupContact = await wbot.getContactById(msg.to); - // } else { - // msgGroupContact = await wbot.getContactById(msg.from); - // } + console - // groupContact = await verifyContact(msgGroupContact); - // } + if (chat.isGroup) { + // let msgGroupContact; + // if (msg.fromMe) { + // msgGroupContact = await wbot.getContactById(msg.to); + // } else { + // msgGroupContact = await wbot.getContactById(msg.from); + // } + + groupContact = await verifyContact(wbot.getContactById); + } + const whatsapp = await ShowWhatsAppService(wbot.id!); const unreadMessages = msg.fromMe ? 0 : chat.unreadCount; @@ -1091,12 +1097,12 @@ const handleMessage = async ( const _botInfo = await BotIsOnQueue("botqueue"); - if (_botInfo.isOnQueue) { + if (_botInfo.isOnQueue && !chat.isGroup) { let ticket_obj: any = await FindOrCreateTicketServiceBot( contact, wbot.id!, - unreadMessages - // groupContact + unreadMessages, + groupContact ); ticket = ticket_obj.ticket; @@ -1115,8 +1121,8 @@ const handleMessage = async ( ticket = await FindOrCreateTicketService( contact, wbot.id!, - unreadMessages - // groupContact + unreadMessages, + groupContact ); } diff --git a/frontend/package.json b/frontend/package.json index 681cd4b..d30e4f4 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -43,7 +43,7 @@ "yup": "^0.32.8" }, "scripts": { - "start": "react-scripts start", + "start": "PORT=3331 react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" diff --git a/frontend/src/components/MessagesList/index.js b/frontend/src/components/MessagesList/index.js index 7e9126c..60b7a71 100644 --- a/frontend/src/components/MessagesList/index.js +++ b/frontend/src/components/MessagesList/index.js @@ -1,7 +1,9 @@ import React, { useContext, useState, useEffect, useReducer, useRef } from "react" import { isSameDay, parseISO, format } from "date-fns" -import openSocket from "socket.io-client" +//import openSocket from "socket.io-client" +import { socket } from "../../services/socket" + import clsx from "clsx" import { AuthContext } from "../../context/Auth/AuthContext" @@ -34,7 +36,7 @@ import whatsBackground from "../../assets/wa-background.png" import api from "../../services/api" import toastError from "../../errors/toastError" -import { countTicketMsgContext } from "../../context/CountTicketMsgProvider/CountTicketMsgProvider" +import { countTicketMsgContext } from "../../context/CountTicketMsgProvider/CountTicketMsgProvider" const useStyles = makeStyles((theme) => ({ messagesListWrapper: { @@ -438,11 +440,18 @@ const MessagesList = ({ ticketId, isGroup }) => { }, [pageNumber, ticketId]) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on("connect", () => socket.emit("joinChatBox", ticketId)) + const onConnectMessagesList = () => { + socket.emit("joinChatBox", ticketId) + } - socket.on("appMessage", (data) => { + onConnectMessagesList() + + socket.on("connect", onConnectMessagesList) + + const onAppMessageMessagesList = (data) => { + if (+data.message.ticketId !== +ticketId) return if (data.action === "create") { @@ -454,10 +463,14 @@ const MessagesList = ({ ticketId, isGroup }) => { if (data.action === "update") { dispatch({ type: "UPDATE_MESSAGE", payload: data.message }) } - }) + } + + socket.on("appMessage", onAppMessageMessagesList) return () => { - socket.disconnect() + socket.emit("leaveChatBox", ticketId) + socket.off("connect", onConnectMessagesList) + socket.off("appMessage", onAppMessageMessagesList) } }, [ticketId]) @@ -949,4 +962,4 @@ const MessagesList = ({ ticketId, isGroup }) => { ) } -export default MessagesList \ No newline at end of file +export default MessagesList diff --git a/frontend/src/components/NotificationsPopOver/index.js b/frontend/src/components/NotificationsPopOver/index.js index 1e46dd1..d3dae05 100644 --- a/frontend/src/components/NotificationsPopOver/index.js +++ b/frontend/src/components/NotificationsPopOver/index.js @@ -2,7 +2,8 @@ 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 openSocket from "socket.io-client" +import { socket } from "../../services/socket" import useSound from "use-sound" import Popover from "@material-ui/core/Popover" @@ -115,24 +116,24 @@ const NotificationsPopOver = () => { useEffect(() => { const fetchSession = async () => { - try { - const { data } = await api.get('/settings') - setSettings(data.settings) - } catch (err) { - toastError(err) - } + try { + const { data } = await api.get('/settings') + setSettings(data.settings) + } catch (err) { + toastError(err) + } } fetchSession() - }, []) + }, []) - const getSettingValue = (key) => { + const getSettingValue = (key) => { const { value } = settings.find((s) => s.key === key) return value - } + } useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) socket.on("reload_page", (data) => { @@ -193,7 +194,8 @@ const NotificationsPopOver = () => { return () => { - socket.disconnect() + socket.removeAllListeners('reload_page'); + socket.removeAllListeners('onlineStatus'); } }, [user.id, handleLogout, user.profile]) @@ -201,12 +203,17 @@ const NotificationsPopOver = () => { useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on("connect", () => socket.emit("joinNotification")) + const onConnectNotifications = () => { + socket.emit("joinNotification") + } + onConnectNotifications() - socket.on("ticket", data => { + socket.on("connect", onConnectNotifications) + + const onTicketNotifications = data => { if (data.action === "updateUnread" || data.action === "delete") { @@ -232,25 +239,18 @@ const NotificationsPopOver = () => { return prevState }) } - }) - - socket.on("appMessage", data => { - + } + 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)=>{ // // }) @@ -265,8 +265,6 @@ const NotificationsPopOver = () => { 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 @@ -275,20 +273,25 @@ const NotificationsPopOver = () => { handleNotifications(data) } - }) + } - socket.on('notifyPeding', data =>{ - if(settings?.length > 0 && getSettingValue('notificationTransferQueue') === 'enabled') handleNotifications("", data); + socket.on("appMessage", onAppMessageNotifications) + + socket.on('notifyPeding', data => { + if (settings?.length > 0 && getSettingValue('notificationTransferQueue') === 'enabled') handleNotifications("", data); }); return () => { - socket.disconnect() + socket.off('connect', onConnectNotifications); + socket.off('ticket', onTicketNotifications); + socket.off('appMessage', onAppMessageNotifications); + socket.removeAllListeners('notifyPeding'); } }, [user, settings]) - const handleNotifications = (data, notify) => { + const handleNotifications = (data, notify) => { let isQueue = false; - if(!notify){ + if (!notify) { const { message, contact, ticket } = data const options = { @@ -301,14 +304,14 @@ const NotificationsPopOver = () => { const notification = new Notification( `${i18n.t("tickets.notification.message")} ${contact.name}`, options - ) - - notification.onclick = e => { - e.preventDefault() + ) + + notification.onclick = e => { + e.preventDefault() window.focus() historyRef.current.push(`/tickets/${ticket.id}`) } - + setDesktopNotifications(prevState => { const notfiticationIndex = prevState.findIndex( n => n.tag === notification.tag @@ -319,15 +322,15 @@ const NotificationsPopOver = () => { } return [notification, ...prevState] }) - }else{ - user.queues.forEach(queue =>{ - if(queue.id === notify.data?.queue?.id){ + } else { + user.queues.forEach(queue => { + if (queue.id === notify.data?.queue?.id) { isQueue = true; } }) - if(!isQueue){ + if (!isQueue) { return; - }else { + } else { const notification = new Notification(`${i18n.t("tickets.notification.messagePeding")} ${notify.data?.queue?.name}`); notification.onclick = e => { e.preventDefault() @@ -346,7 +349,7 @@ const NotificationsPopOver = () => { return [notification, ...prevState] }) } - } + } soundAlertRef.current() } @@ -387,10 +390,10 @@ const NotificationsPopOver = () => { vertical: "top", horizontal: "right", }} - classes={{ paper: classes.popoverPaper }} + classes={{ paper: classes?.popoverPaper }} onClose={handleClickAway} > - + {notifications.length === 0 ? ( {i18n.t("notifications.noTickets")} diff --git a/frontend/src/components/PositionModal/index.js b/frontend/src/components/PositionModal/index.js index 4489f8d..537b7cf 100644 --- a/frontend/src/components/PositionModal/index.js +++ b/frontend/src/components/PositionModal/index.js @@ -3,7 +3,8 @@ import React, { useState, useEffect, useRef, useContext } from "react" import * as Yup from "yup" import { Formik, Form, Field } from "formik" import { toast } from "react-toastify" -import openSocket from 'socket.io-client' +//import openSocket from 'socket.io-client' +import { socket } from "../../services/socket" import { makeStyles, @@ -50,8 +51,8 @@ const useStyles = makeStyles((theme) => ({ })) const PositionSchema = Yup.object().shape({ - name: Yup.string() - .required("Required"), + name: Yup.string() + .required("Required"), }) const PositionModal = ({ @@ -65,14 +66,14 @@ const PositionModal = ({ const isMounted = useRef(true) const initialState = { - name: "", + name: "", } const [position, setPosition] = useState(initialState) // const [selectedQueueIds, setSelectedQueueIds] = useState([]) const { setting } = useContext(AuthContext) const [settings, setSettings] = useState(setting) - + useEffect(() => { return () => { @@ -86,9 +87,9 @@ const PositionModal = ({ useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on('settings', (data) => { + const onSettingsPosition = (data) => { if (data.action === 'update') { setSettings((prevState) => { const aux = [...prevState] @@ -97,10 +98,12 @@ const PositionModal = ({ return aux }) } - }) + } + + socket.on('settings', onSettingsPosition) return () => { - socket.disconnect() + socket.off("settings", onSettingsPosition) } }, []) @@ -140,7 +143,7 @@ const PositionModal = ({ const handleSavePosition = async (values) => { try { - + if (positionId) { await api.put(`/positions/${positionId}`, values) handleClose() @@ -153,7 +156,7 @@ const PositionModal = ({ handleClose() toast.success("Cargo salvo com sucesso") } - + } catch (err) { toastError(err) } @@ -200,7 +203,7 @@ const PositionModal = ({ className={classes.textField} fullWidth /> - + {/*
{ ((settings && getSettingValue('quickAnswerByQueue') === 'enabled')) && ( diff --git a/frontend/src/components/QrcodeModal/index.js b/frontend/src/components/QrcodeModal/index.js index dcca527..4c8bd23 100644 --- a/frontend/src/components/QrcodeModal/index.js +++ b/frontend/src/components/QrcodeModal/index.js @@ -1,6 +1,8 @@ import React, { useEffect, useState, useContext } from "react"; import QRCode from "qrcode.react"; -import openSocket from "socket.io-client"; +//import openSocket from "socket.io-client"; +import { socket } from "../../services/socket"; + import toastError from "../../errors/toastError"; import { Dialog, DialogContent, Paper, Typography } from "@material-ui/core"; @@ -31,9 +33,9 @@ const QrcodeModal = ({ open, onClose, whatsAppId }) => { useEffect(() => { if (!whatsAppId) return; - const socket = openSocket(process.env.REACT_APP_BACKEND_URL); + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL); - socket.on("whatsappSession", data => { + const onWhatsAppSessionQrCode = data => { if (data.action === "update" && data.session.id === whatsAppId) { setQrCode(data.session.qrcode); } @@ -42,21 +44,23 @@ const QrcodeModal = ({ open, onClose, whatsAppId }) => { onClose(); } - if (data.action === "error") { + if (data.action === "error") { - console.log('user.profile: ', user.profile) + console.log('user.profile: ', user.profile) - if(user.profile === 'master'){ + if (user.profile === 'master') { alert(data.msg) - } - + } + } - }); + } + + socket.on("whatsappSession", onWhatsAppSessionQrCode); return () => { - socket.disconnect(); + socket.off("whatsappSession", onWhatsAppSessionQrCode); }; }, [whatsAppId, onClose, user.profile]); diff --git a/frontend/src/components/QueueModal/index.js b/frontend/src/components/QueueModal/index.js index eb82ee8..776f68d 100644 --- a/frontend/src/components/QueueModal/index.js +++ b/frontend/src/components/QueueModal/index.js @@ -23,8 +23,8 @@ import { IconButton, InputAdornment } from "@material-ui/core" import { Colorize } from "@material-ui/icons" import { AuthContext } from '../../context/Auth/AuthContext' -import openSocket from 'socket.io-client' - +//import openSocket from 'socket.io-client' +import { socket } from "../../services/socket" const useStyles = makeStyles(theme => ({ @@ -92,9 +92,9 @@ const QueueModal = ({ open, onClose, queueId }) => { }, [setting]) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on('settings', (data) => { + const onSettingsQueueModal = (data) => { if (data.action === 'update') { setSettings((prevState) => { const aux = [...prevState] @@ -103,10 +103,12 @@ const QueueModal = ({ open, onClose, queueId }) => { return aux }) } - }) + } + + socket.on('settings', onSettingsQueueModal) return () => { - socket.disconnect() + socket.off("settings", onSettingsQueueModal) } }, []) diff --git a/frontend/src/components/QuickAnswersModal/index.js b/frontend/src/components/QuickAnswersModal/index.js index 10008f8..748c3ce 100644 --- a/frontend/src/components/QuickAnswersModal/index.js +++ b/frontend/src/components/QuickAnswersModal/index.js @@ -3,8 +3,8 @@ import React, { useState, useEffect, useRef, useContext } from "react" import * as Yup from "yup" import { Formik, Form, Field } from "formik" import { toast } from "react-toastify" -import openSocket from 'socket.io-client' - +//import openSocket from 'socket.io-client' +import { socket } from "../../services/socket" import { makeStyles, @@ -79,7 +79,7 @@ const QuickAnswersModal = ({ const [quickAnswer, setQuickAnswer] = useState(initialState) const [selectedQueueIds, setSelectedQueueIds] = useState([]) const { user, setting, getSettingValue } = useContext(AuthContext) - const [settings, setSettings] = useState(setting) + const [settings, setSettings] = useState(setting) useEffect(() => { return () => { @@ -92,18 +92,18 @@ const QuickAnswersModal = ({ }, [setting]) useEffect(() => { - + setSelectedQueueIds([]) - if (open && selectedQueueIds.length === 0 && !quickAnswerId) { + if (open && selectedQueueIds.length === 0 && !quickAnswerId) { setSelectedQueueIds(user.queues.map(q => q.id)) } }, [open,]) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on('settings', (data) => { + const onSettingsQuickAnswersModal = (data) => { if (data.action === 'update') { setSettings((prevState) => { const aux = [...prevState] @@ -112,14 +112,16 @@ const QuickAnswersModal = ({ return aux }) } - }) + } + + socket.on('settings', onSettingsQuickAnswersModal) return () => { - socket.disconnect() + socket.off("settings", onSettingsQuickAnswersModal) } }, []) - useEffect(() => { + useEffect(() => { // setSelectedQueueIds([]) @@ -139,7 +141,7 @@ const QuickAnswersModal = ({ if (isMounted.current) { setQuickAnswer(data) - if (data?.queues) { + if (data?.queues) { const quickQueueIds = data.queues?.map((queue) => queue.id) setSelectedQueueIds(quickQueueIds) } diff --git a/frontend/src/components/StatusChatEndModal/index.js b/frontend/src/components/StatusChatEndModal/index.js index 1c18884..765aedb 100644 --- a/frontend/src/components/StatusChatEndModal/index.js +++ b/frontend/src/components/StatusChatEndModal/index.js @@ -3,8 +3,8 @@ import React, { useState, useEffect, useRef, useContext } from "react" import * as Yup from "yup" import { Formik, Form, Field } from "formik" import { toast } from "react-toastify" -import openSocket from 'socket.io-client' - +//import openSocket from 'socket.io-client' +import { socket } from "../../services/socket" import { makeStyles, @@ -91,9 +91,9 @@ const StatusChatEndModal = ({ useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on('settings', (data) => { + const onSettingsStatusChatEndModal = (data) => { if (data.action === 'update') { setSettings((prevState) => { const aux = [...prevState] @@ -102,10 +102,12 @@ const StatusChatEndModal = ({ return aux }) } - }) + } + + socket.on('settings', onSettingsStatusChatEndModal) return () => { - socket.disconnect() + socket.off("settings", onSettingsStatusChatEndModal) } }, []) diff --git a/frontend/src/components/Ticket/index.js b/frontend/src/components/Ticket/index.js index dbf78bf..fd7efce 100644 --- a/frontend/src/components/Ticket/index.js +++ b/frontend/src/components/Ticket/index.js @@ -2,7 +2,9 @@ import React, { useState, useEffect } from "react" import { useParams, useHistory } from "react-router-dom" import { toast } from "react-toastify" -import openSocket from "socket.io-client" +//import openSocket from "socket.io-client" +import { socket } from "../../services/socket" + import clsx from "clsx" import { Paper, makeStyles } from "@material-ui/core" @@ -132,22 +134,32 @@ const Ticket = () => { }, []) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on("connect", () => socket.emit("joinChatBox", ticketId)) + const onConnectTicket = () => socket.emit("joinChatBox", ticketId) + + onConnectTicket() + + socket.on("connect", onConnectTicket) + + const onTicketTicket = (data) => { + const isSameTicket = +data?.ticket?.id === +ticketId || +data.ticketId === +ticketId + if (!isSameTicket) return - socket.on("ticket", (data) => { if (data.action === "update") { setTicket(data.ticket) } - if (data.action === "delete") { + if (data.action === "deleteForever") { + console.log('delete forever') toast.success("Ticket deleted sucessfully.") history.push("/tickets") } - }) + } - socket.on("contact", (data) => { + socket.on("ticket", onTicketTicket) + + const onContactTicket = (data) => { if (data.action === "update") { setContact((prevState) => { if (prevState.id === data.contact?.id) { @@ -156,9 +168,11 @@ const Ticket = () => { return prevState }) } - }) + } - socket.on("remoteTickesControllIdleOpen", (data) => { + socket.on("contact", onContactTicket) + + const onRemoteTicketsControllIdleOpenTicket = (data) => { if (data.action === "update") { let url_ticketId try { @@ -175,10 +189,15 @@ const Ticket = () => { console.log('error on try do the send seen: ', error) } } - }) + } + + socket.on("remoteTickesControllIdleOpen", onRemoteTicketsControllIdleOpenTicket) return () => { - socket.disconnect() + socket.off("connect", onConnectTicket) + socket.off("ticket", onTicketTicket) + socket.off("contact", onContactTicket) + socket.off("remoteTickesControllIdleOpen", onRemoteTicketsControllIdleOpenTicket) } }, [ticketId, history]) diff --git a/frontend/src/components/TicketListItem/index.js b/frontend/src/components/TicketListItem/index.js index 417b9d1..55b5196 100644 --- a/frontend/src/components/TicketListItem/index.js +++ b/frontend/src/components/TicketListItem/index.js @@ -22,7 +22,8 @@ import MarkdownWrapper from "../MarkdownWrapper" import { Tooltip } from "@material-ui/core" import { AuthContext } from "../../context/Auth/AuthContext" import toastError from "../../errors/toastError" -import openSocket from 'socket.io-client' +//import openSocket from 'socket.io-client' +import { socket } from "../../services/socket" const useStyles = makeStyles(theme => ({ ticket: { @@ -151,17 +152,18 @@ const TicketListItem = ({ ticket, remoteTicketsControll, settings }) => { useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on('remoteTickesControll', (data) => { + const onRemoteTickesControllTicketListItem = (data) => { console.log('REMOTE TICKETS CONTROLL UPDATE2: ', data.tickets) if (data.action === 'update') { setRemoteTicketsControll(data.tickets) } - }) + } + socket.on('remoteTickesControll', onRemoteTickesControllTicketListItem) - socket.on('settings', (data) => { + const onSettingsTicketListItem = (data) => { if (data.action === 'update') { setSettings((prevState) => { const aux = [...prevState] @@ -170,11 +172,13 @@ const TicketListItem = ({ ticket, remoteTicketsControll, settings }) => { return aux }) } - }) + } + socket.on('settings', onSettingsTicketListItem) return () => { - socket.disconnect() + socket.off('remoteTickesControll', onRemoteTickesControllTicketListItem); + socket.off('settings', onSettingsTicketListItem); } }, []) diff --git a/frontend/src/components/TicketsList/index.js b/frontend/src/components/TicketsList/index.js index a481700..20ebe2f 100644 --- a/frontend/src/components/TicketsList/index.js +++ b/frontend/src/components/TicketsList/index.js @@ -1,7 +1,7 @@ import React, { useState, useEffect, useReducer, useContext } from "react" - -import openSocket from "socket.io-client" +//import openSocket from "socket.io-client" +import { socket } from "../../services/socket" import { makeStyles } from "@material-ui/core/styles" import List from "@material-ui/core/List" @@ -243,27 +243,29 @@ const TicketsList = (props) => { // if (tab=='search')return - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) const shouldUpdateTicket = ticket => + (status === ticket.status) && (!ticket.userId || ticket.userId === user?.id || showAll) && (!ticket.queueId || selectedQueueIds.indexOf(ticket.queueId) > -1) const notBelongsToUserQueues = ticket => ticket.queueId && selectedQueueIds.indexOf(ticket.queueId) === -1 - socket.on("connect", () => { + const onConnectTicketList = () => { if (status) { socket.emit("joinTickets", status) } else { socket.emit("joinNotification") } + } - }) + onConnectTicketList() + socket.on("connect", onConnectTicketList) - - socket.on("ticket", data => { + const onTicketTicketList = data => { if (data.action === "updateUnread") { @@ -292,10 +294,11 @@ const TicketsList = (props) => { if (data.action === "delete") { dispatch({ type: "DELETE_TICKET", payload: data.ticketId }) } - }) + } + socket.on("ticket", onTicketTicketList) - socket.on("appMessage", data => { + const onAppMessageTicketList = data => { if (data.action === "create" && shouldUpdateTicket(data.ticket)) { @@ -307,7 +310,9 @@ const TicketsList = (props) => { payload: data, }) } - }) + } + + socket.on("appMessage", onAppMessageTicketList) socket.on("contact", data => { if (data.action === "update") { @@ -318,16 +323,16 @@ const TicketsList = (props) => { } }) - - socket.on('remoteTickesControll', (data) => { + const onRemoteTickesControllTicketList = (data) => { console.log('REMOTE TICKETS CONTROLL UPDATE 1: ', data.tickets) if (data.action === 'update') { setRemoteTicketsControll(data.tickets) } - }) + } + socket.on('remoteTickesControll', onRemoteTickesControllTicketList) - socket.on('settings', (data) => { + const onSettingsTicketList = (data) => { if (data.action === 'update') { setSettings((prevState) => { const aux = [...prevState] @@ -336,11 +341,17 @@ const TicketsList = (props) => { return aux }) } - }) + } + socket.on('settings', onSettingsTicketList) return () => { - socket.disconnect() + socket.off("ticket", onTicketTicketList) + socket.off('appMessage', onAppMessageTicketList); + socket.removeAllListeners("contact") + socket.off('connect', onConnectTicketList); + socket.off('settings', onSettingsTicketList); + socket.off('remoteTickesControll', onRemoteTickesControllTicketList); } }, [status, showAll, user, selectedQueueIds, tab]) @@ -349,7 +360,7 @@ const TicketsList = (props) => { if (typeof updateCount === "function") { updateCount(ticketsList.length) } - if (ticketsList && status === "pending"){ + if (ticketsList && status === "pending") { setTickets(ticketsList) } // else{ diff --git a/frontend/src/components/TicketsManager/index.js b/frontend/src/components/TicketsManager/index.js index 19b922b..4699948 100644 --- a/frontend/src/components/TicketsManager/index.js +++ b/frontend/src/components/TicketsManager/index.js @@ -19,7 +19,6 @@ import FindInPageIcon from '@material-ui/icons/FindInPage' import FormControlLabel from "@material-ui/core/FormControlLabel" import Switch from "@material-ui/core/Switch" -import openSocket from "socket.io-client" import NewTicketModal from "../NewTicketModal" import TicketsList from "../TicketsList" @@ -153,7 +152,7 @@ const TicketsManager = () => { const [openCount, setOpenCount] = useState(0) const [pendingCount, setPendingCount] = useState(0) - const userQueueIds = user.queues.map((q) => q.id) + const userQueueIds = user?.queues?.map((q) => q?.id) const [selectedQueueIds, setSelectedQueueIds] = useState(userQueueIds || []) const [showContentSearch, setShowContentSearch] = useState(false) @@ -178,9 +177,9 @@ const TicketsManager = () => { }, [setting]) useEffect(() => { - if (user.profile.toUpperCase() === "ADMIN" || - user.profile.toUpperCase() === "SUPERVISOR" || - user.profile.toUpperCase() === "MASTER") { + if (user?.profile?.toUpperCase() === "ADMIN" || + user?.profile?.toUpperCase() === "SUPERVISOR" || + user?.profile?.toUpperCase() === "MASTER") { setShowAllTickets(true) } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -193,21 +192,21 @@ const TicketsManager = () => { setTabOption(tab) - }, [tab, setTabOption]) + }, [tab, setTabOption]) useEffect(() => { if (settings?.length > 0 && getSettingValue('waitingTimeTickets') !== 'enabled') return - const calculateAverageTime = () => { + const calculateAverageTime = () => { if (tickets.length > 0) { const now = new Date() const differenceTime = tickets?.map(ticket => { - const createdAt = new Date(ticket.createdAt) + const createdAt = new Date(ticket?.createdAt) const difference = now - createdAt return difference }) - const sumDifferences = differenceTime.reduce((total, difference) => total + difference, 0) + const sumDifferences = differenceTime?.reduce((total, difference) => total + difference, 0) const averageTimeMilliseconds = sumDifferences / tickets?.length let hours = Math.floor(averageTimeMilliseconds / 3600000) const minutes = Math.floor((averageTimeMilliseconds % 3600000) / 60000) @@ -222,10 +221,10 @@ const TicketsManager = () => { } else return '00:00' } - setWaitingTime(calculateAverageTime()) + setWaitingTime(calculateAverageTime()) const intervalId = setInterval(() => { - setWaitingTime(calculateAverageTime()) + setWaitingTime(calculateAverageTime()) }, 10000) return () => clearInterval(intervalId) diff --git a/frontend/src/components/TransferTicketModal/index.js b/frontend/src/components/TransferTicketModal/index.js index 02acdfc..5f2671e 100644 --- a/frontend/src/components/TransferTicketModal/index.js +++ b/frontend/src/components/TransferTicketModal/index.js @@ -1,6 +1,7 @@ import React, { useState, useContext, useMemo, useEffect } from "react" import { useHistory } from "react-router-dom" -import openSocket from "socket.io-client" +//import openSocket from "socket.io-client" +import { socket } from "../../services/socket" import Button from "@material-ui/core/Button" import Dialog from "@material-ui/core/Dialog" @@ -110,9 +111,9 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => { useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on('settings', (data) => { + const onSettingsTransferTicketModal = (data) => { console.log('settings updated ----------------------------xxxxxxxxxxxx') if (data.action === 'update') { @@ -123,10 +124,12 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => { return aux }) } - }) + } + + socket.on('settings', onSettingsTransferTicketModal) return () => { - socket.disconnect() + socket.off("settings", onSettingsTransferTicketModal) } }, []) @@ -194,7 +197,7 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => { const { data } = await api.get(`/users/all`, { params: { userId: user.id }, }) - + setUsers(data.users) setQueuesByWhats(data.queues) setQueues(data.queues) @@ -228,7 +231,7 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => { {i18n.t("transferTicketModal.title")} - + {/* {i18n.t("transferTicketModal.fieldQueueLabel")} */} {'Usuário'} @@ -247,7 +250,7 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => { ))} - + {i18n.t("transferTicketModal.fieldQueuePlaceholder")} @@ -259,7 +262,7 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => { required >   - {queues.map((queue) => ( + {queues?.map((queue) => ( { useEffect(() => { const token = localStorage.getItem('token') - ;(async () => { - if (token) { - try { - const { data } = await api.post('/auth/refresh_token') - api.defaults.headers.Authorization = `Bearer ${data.token}` - setIsAuth(true) - setUser(data.user) - } catch (err) { - toastError(err) + ; (async () => { + if (token) { + try { + const { data } = await api.post('/auth/refresh_token') + api.defaults.headers.Authorization = `Bearer ${data.token}` + setIsAuth(true) + setUser(data.user) + } catch (err) { + toastError(err) + } } - } - setLoading(false) - })() + setLoading(false) + })() }, []) useEffect(() => { @@ -90,7 +91,7 @@ const useAuth = () => { }, []) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) socket.on('user', (data) => { if (data.action === 'update' && data.user.id === user.id) { @@ -98,7 +99,7 @@ const useAuth = () => { } }) - socket.on('settings', (data) => { + const onSettingsAuth = (data) => { if (data.action === 'update') { setSetting((prevState) => { const aux = [...prevState] @@ -107,10 +108,13 @@ const useAuth = () => { return aux }) } - }) + } + + socket.on('settings', onSettingsAuth) return () => { - socket.disconnect() + socket.removeAllListeners('user'); + socket.off('settings', onSettingsAuth); } }, [user]) @@ -135,7 +139,7 @@ const useAuth = () => { const handleLogout = async () => { setLoading(true) - try { + try { await api.delete(`/auth/logout/${user.id}`); setIsAuth(false) diff --git a/frontend/src/hooks/useWhatsApps/index.js b/frontend/src/hooks/useWhatsApps/index.js index 1360ac1..fe4da0a 100644 --- a/frontend/src/hooks/useWhatsApps/index.js +++ b/frontend/src/hooks/useWhatsApps/index.js @@ -1,5 +1,7 @@ import { useState, useEffect, useReducer } from "react"; -import openSocket from "socket.io-client"; +//import openSocket from "socket.io-client"; +import { socket } from "../../services/socket"; + import toastError from "../../errors/toastError"; @@ -30,7 +32,7 @@ const reducer = (state, action) => { if (whatsAppIndex !== -1) { - if ('disabled' in whatsApp) { + if ('disabled' in whatsApp) { state[whatsAppIndex].disabled = whatsApp.disabled } else { @@ -126,7 +128,7 @@ const useWhatsApps = () => { }, []); useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL); + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL); socket.on("whatsapp", data => { if (data.action === "update") { @@ -158,7 +160,9 @@ const useWhatsApps = () => { return () => { - socket.disconnect(); + socket.removeAllListeners('whatsapp'); + socket.removeAllListeners('whatsappSession'); + socket.removeAllListeners('whatsappSessionMonit'); }; }, []); diff --git a/frontend/src/layout/MainListItems.js b/frontend/src/layout/MainListItems.js index 3f04337..09be3ec 100644 --- a/frontend/src/layout/MainListItems.js +++ b/frontend/src/layout/MainListItems.js @@ -31,7 +31,8 @@ import { i18n } from '../translate/i18n' import { WhatsAppsContext } from '../context/WhatsApp/WhatsAppsContext' import { AuthContext } from '../context/Auth/AuthContext' import { Can } from '../components/Can' -import openSocket from 'socket.io-client' +//import openSocket from 'socket.io-client' +import { socket } from '../services/socket' import api from '../services/api' @@ -118,9 +119,9 @@ const MainListItems = (props) => { } useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on('settings', (data) => { + const onSettingsMainListItem = (data) => { if (data.action === 'update') { setSettings((prevState) => { const aux = [...prevState] @@ -129,10 +130,12 @@ const MainListItems = (props) => { return aux }) } - }) + } + + socket.on('settings', onSettingsMainListItem) return () => { - socket.disconnect() + socket.off('settings', onSettingsMainListItem); } }, []) diff --git a/frontend/src/pages/Campaign/index.js b/frontend/src/pages/Campaign/index.js index 0cae436..db78005 100644 --- a/frontend/src/pages/Campaign/index.js +++ b/frontend/src/pages/Campaign/index.js @@ -1,7 +1,8 @@ import React, { useState, useCallback, useEffect, useReducer, useContext } from 'react' -import { toast } from 'react-toastify' +import { toast } from 'react-toastify' -import openSocket from 'socket.io-client' +//import openSocket from 'socket.io-client' +import { socket } from '../../services/socket' import { makeStyles } from '@material-ui/core/styles' import { green } from '@material-ui/core/colors' @@ -13,11 +14,11 @@ import { IconButton, Table, TableHead, - Paper, + Paper, } from '@material-ui/core' import { - Edit, - DeleteOutline, + Edit, + DeleteOutline, // Restore } from '@material-ui/icons' @@ -26,7 +27,7 @@ import MainHeader from '../../components/MainHeader' import MainHeaderButtonsWrapper from '../../components/MainHeaderButtonsWrapper' import Title from '../../components/Title' import TableRowSkeleton from '../../components/TableRowSkeleton' - + import CampaignModal from '../../components/CampaignModal' import ConfirmationModal from '../../components/ConfirmationModal' import QrcodeModal from '../../components/QrcodeModal' @@ -51,7 +52,7 @@ const reducer = (state, action) => { const campaigns = action.payload return [...state, ...campaigns] } - if (action.type === "UPDATE_CAMPAIGNS") { + if (action.type === "UPDATE_CAMPAIGNS") { const campaign = action.payload const campaignIndex = state.findIndex((c) => c.id === campaign.id) @@ -109,7 +110,7 @@ const useStyles = makeStyles((theme) => ({ buttonProgress: { color: green[500], }, -})) +})) const Campaign = () => { //-------- @@ -124,7 +125,7 @@ const Campaign = () => { const [qrModalOpen, setQrModalOpen] = useState(false) const [selectedCampaign, setSelectedCampaign] = useState(null) const [confirmModalOpen, setConfirmModalOpen] = useState(false) - + const [campaigns, dispatch] = useReducer(reducer, []) const [loading, setLoading] = useState(true) @@ -152,7 +153,7 @@ const Campaign = () => { const delayDebounceFn = setTimeout(() => { const fetchContacts = async () => { - try { + try { const { data } = await apiBroker.get('/campaign', { params: { @@ -160,7 +161,7 @@ const Campaign = () => { baseURL: process.env.REACT_APP_BACKEND_URL_PRIVATE, identifier: 'campaign' } - }) + }) dispatch({ type: "LOAD_CAMPAIGNS", payload: data.campaign }) setLoading(false) @@ -174,7 +175,7 @@ const Campaign = () => { }, 500) return () => clearTimeout(delayDebounceFn) }, [user.id]) - + const handleOpenCampaignModal = () => { setSelectedCampaign(null) @@ -184,12 +185,12 @@ const Campaign = () => { const handleCloseCampaignModal = useCallback(() => { setCampaignModalOpen(false) setSelectedCampaign(null) - }, [setSelectedCampaign, setCampaignModalOpen]) + }, [setSelectedCampaign, setCampaignModalOpen]) - const handleStart = async (campaign) => { + const handleStart = async (campaign) => { try { - const { data } = await apiBroker.post(`/campaign/start/${campaign.id}`) + const { data } = await apiBroker.post(`/campaign/start/${campaign.id}`) dispatch({ type: "UPDATE_CAMPAIGNS", payload: data.campaign }) @@ -200,10 +201,10 @@ const Campaign = () => { } } - const handleStop = async (campaign) => { + const handleStop = async (campaign) => { try { - const { data } = await apiBroker.post(`/campaign/stop/${campaign.id}`) + const { data } = await apiBroker.post(`/campaign/stop/${campaign.id}`) dispatch({ type: "UPDATE_CAMPAIGNS", payload: data.campaign }) @@ -245,7 +246,7 @@ const Campaign = () => { setConfirmModalOpen(true) } - const handleSubmitConfirmationModal = async () => { + const handleSubmitConfirmationModal = async () => { if (confirmModalInfo.action === 'delete') { try { @@ -293,13 +294,12 @@ const Campaign = () => { )} ) - } + } useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - - socket.on("contactsBulkInsertOnQueueStatus", (data) => { + const onContactsBulkCampaing = (data) => { if (data.action === 'update') { if (String(data.insertOnQueue.adminId) === String(user.id)) { @@ -312,19 +312,24 @@ const Campaign = () => { } } - }) + } - socket.on('campaign', (data) => { + socket.on("contactsBulkInsertOnQueueStatus", onContactsBulkCampaing) + + const onCampaignCampaign = (data) => { if (data.action === 'update') { dispatch({ type: "UPDATE_CAMPAIGNS", payload: data.campaign }) } - }) + } + + socket.on('campaign', onCampaignCampaign) + - return () => { - socket.disconnect() + socket.off("campaign", onCampaignCampaign) + socket.off("contactsBulkInsertOnQueueStatus", onContactsBulkCampaing) } }, [user.id]) diff --git a/frontend/src/pages/Connections/index.js b/frontend/src/pages/Connections/index.js index e4055e6..2df93ec 100644 --- a/frontend/src/pages/Connections/index.js +++ b/frontend/src/pages/Connections/index.js @@ -2,7 +2,8 @@ import React, { useState, useCallback, useEffect, useContext } from 'react' import { toast } from 'react-toastify' import { format, parseISO } from 'date-fns' -import openSocket from 'socket.io-client' +//import openSocket from 'socket.io-client' +import { socket } from '../../services/socket' import { makeStyles } from '@material-ui/core/styles' import { green, red, yellow, grey } from '@material-ui/core/colors' @@ -144,7 +145,7 @@ const Connections = () => { const [selectedWhatsApp, setSelectedWhatsApp] = useState(null) const [confirmModalOpen, setConfirmModalOpen] = useState(false) - const [diskSpaceInfo, setDiskSpaceInfo] = useState({}) + const [diskSpaceInfo, setDiskSpaceInfo] = useState({}) const [settings, setSettings] = useState([]) @@ -388,7 +389,7 @@ const Connections = () => { getSettingValue('whatsaAppCloudApi') === 'disabled') && ( - + )} {whatsApp.status === 'OPENING' && !whatsApp.isOfficial && ( @@ -433,7 +434,7 @@ const Connections = () => { try { await api.post(`/restartwhatsappsession/0`, { params: { status: 'status' }, - }) + }) setClicks((buttons) => buttons.map((e) => { @@ -451,15 +452,17 @@ const Connections = () => { }, []) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on('diskSpaceMonit', (data) => { + const onDiskSpaceMonitConnections = (data) => { if (data.action === 'update') { setDiskSpaceInfo(data.diskSpace) } - }) + } - socket.on('settings', (data) => { + socket.on('diskSpaceMonit', onDiskSpaceMonitConnections) + + const onSettingsConnections = (data) => { if (data.action === 'update') { setSettings((prevState) => { const aux = [...prevState] @@ -468,10 +471,13 @@ const Connections = () => { return aux }) } - }) + } + + socket.on('settings', onSettingsConnections) return () => { - socket.disconnect() + socket.off("settings", onSettingsConnections) + socket.off("diskSpaceMonit", onDiskSpaceMonitConnections) } }, []) diff --git a/frontend/src/pages/Contacts/index.js b/frontend/src/pages/Contacts/index.js index 6a3a616..95e4acb 100644 --- a/frontend/src/pages/Contacts/index.js +++ b/frontend/src/pages/Contacts/index.js @@ -1,5 +1,6 @@ import React, { useState, useEffect, useReducer, useCallback, useContext } from "react" -import openSocket from "socket.io-client" +//import openSocket from "socket.io-client" +import { socket } from "../../services/socket" import { toast } from "react-toastify" import { useHistory } from "react-router-dom" @@ -260,9 +261,9 @@ const Contacts = () => { }, [searchParam, pageNumber]) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on("contactsBulkInsertOnQueueStatus", (data) => { + const onContactsBulkContacts = (data) => { if (data.action === 'update') { if (String(data.insertOnQueue.adminId) === String(user.id)) { @@ -278,9 +279,11 @@ const Contacts = () => { } } - }) + } - socket.on("contact", (data) => { + socket.on("contactsBulkInsertOnQueueStatus", onContactsBulkContacts) + + const onContactContacts = (data) => { if (data.action === "update" || data.action === "create") { dispatch({ type: "UPDATE_CONTACTS", payload: data.contact }) } @@ -288,10 +291,13 @@ const Contacts = () => { if (data.action === "delete") { dispatch({ type: "DELETE_CONTACT", payload: +data.contactId }) } - }) + } + + socket.on("contact", onContactContacts) return () => { - socket.disconnect() + socket.off("contact", onContactContacts) + socket.off("contactsBulkInsertOnQueueStatus", onContactsBulkContacts) } }, [user, history]) @@ -536,7 +542,7 @@ const Contacts = () => { open={contactModalOpen} onClose={handleCloseContactModal} aria-labelledby="form-dialog-title" - contactId={selectedContactId} + contactId={selectedContactId} > { const { data } = await api.get("/reports/user/services", { params: { userId: null, startDate: dateToday, endDate: dateToday, userQueues: selectedQueue }, - }) + }) dispatch({ type: "RESET" }) dispatch({ type: "LOAD_QUERY", payload: data.usersProfile }) @@ -301,7 +302,7 @@ const Dashboard = () => { }) setTicketStatusChatEnd(ticketStatusChatEndData.reportStatusChatEnd) - + } catch (err) { } @@ -356,46 +357,54 @@ const Dashboard = () => { useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on("ticketStatus", (data) => { + const onTicketsStatusDashboard = (data) => { if (data.action === "update") { setStatus("") setStatus(data.ticketStatus.status) } - }) + } - socket.on("onlineStatus", (data) => { + socket.on("ticketStatus", onTicketsStatusDashboard) + + const onOnlineStatusDashboard = (data) => { if (data.action === "logout" || data.action === "update") { dispatch({ type: "UPDATE_STATUS_ONLINE", payload: data.userOnlineTime }) } else if (data.action === "delete") { dispatch({ type: "DELETE_USER_STATUS", payload: data.userOnlineTime }) } - }) + } - socket.on("user", (data) => { + socket.on("onlineStatus", onOnlineStatusDashboard) + + const onUserDashboard = (data) => { if (data.action === "delete") { dispatch({ type: "DELETE_USER", payload: +data.userId }) } - }) + } + + socket.on("user", onUserDashboard) return () => { - socket.disconnect() + socket.off("user", onUserDashboard) + socket.off("onlineStatus", onOnlineStatusDashboard) + socket.off("ticketStatus", onTicketsStatusDashboard) } }, []) - + const handleSelectedQueue = useCallback((queueSelected) => { - if(queueSelected !== 'All'){ + if (queueSelected !== 'All') { const queueIndex = user?.queues?.findIndex((q) => q.id === parseInt(queueSelected)); const queueIds = [] queueIds.push(user?.queues[queueIndex]?.id); setSelectedQueue(queueIds); - }else{ + } else { const queueIds = user?.queues?.map((queue) => queue.id); setSelectedQueue(queueIds); } - },[user, setSelectedQueue]) + }, [user, setSelectedQueue]) useEffect(() => { if (ticketStatusChange === "") return @@ -532,7 +541,7 @@ const Dashboard = () => { - + diff --git a/frontend/src/pages/Position/index.js b/frontend/src/pages/Position/index.js index 5eb50ea..2f53053 100644 --- a/frontend/src/pages/Position/index.js +++ b/frontend/src/pages/Position/index.js @@ -1,5 +1,6 @@ import React, { useState, useContext, useEffect, useReducer } from "react" -import openSocket from "socket.io-client" +//import openSocket from "socket.io-client" +import { socket } from "../../services/socket" import { Button, @@ -125,9 +126,9 @@ const Position = () => { }, [searchParam, pageNumber]) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on("position", (data) => { + const onPositionPosition = (data) => { if (data.action === "update" || data.action === "create") { dispatch({ type: "UPDATE_POSITIONS", payload: data.position }) } @@ -138,10 +139,12 @@ const Position = () => { payload: +data.positionId, }) } - }) + } + + socket.on("position", onPositionPosition) return () => { - socket.disconnect() + socket.off("position", onPositionPosition) } }, []) diff --git a/frontend/src/pages/Queues/index.js b/frontend/src/pages/Queues/index.js index a2ffea1..0ea309d 100644 --- a/frontend/src/pages/Queues/index.js +++ b/frontend/src/pages/Queues/index.js @@ -1,6 +1,7 @@ import React, { useEffect, useReducer, useState, useContext } from 'react' -import openSocket from 'socket.io-client' +//import openSocket from 'socket.io-client' +import { socket } from '../../services/socket' import { Button, @@ -91,7 +92,7 @@ const reducer = (state, action) => { const Queues = () => { const classes = useStyles() - const { user, setting, getSettingValue } = useContext(AuthContext) + const { user, setting, getSettingValue } = useContext(AuthContext) const [queues, dispatch] = useReducer(reducer, []) const [loading, setLoading] = useState(false) @@ -120,12 +121,12 @@ const Queues = () => { setLoading(false) } })() - }, []) + }, []) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on('queue', (data) => { + const onQueueQueues = (data) => { if (data.action === 'update' || data.action === 'create') { dispatch({ type: 'UPDATE_QUEUES', payload: data.queue }) } @@ -133,9 +134,11 @@ const Queues = () => { if (data.action === 'delete') { dispatch({ type: 'DELETE_QUEUE', payload: data.queueId }) } - }) + } - socket.on('settings', (data) => { + socket.on('queue', onQueueQueues) + + const onSettingsQueues = (data) => { if (data.action === 'update') { setSettings((prevState) => { const aux = [...prevState] @@ -144,10 +147,13 @@ const Queues = () => { return aux }) } - }) + } + + socket.on('settings', onSettingsQueues) return () => { - socket.disconnect() + socket.off("settings", onSettingsQueues) + socket.off("queue", onQueueQueues) } }, []) diff --git a/frontend/src/pages/QuickAnswers/index.js b/frontend/src/pages/QuickAnswers/index.js index 5a71233..6c4b5d5 100644 --- a/frontend/src/pages/QuickAnswers/index.js +++ b/frontend/src/pages/QuickAnswers/index.js @@ -1,5 +1,6 @@ import React, { useState, useContext, useEffect, useReducer } from "react" -import openSocket from "socket.io-client" +//import openSocket from "socket.io-client" +import { socket } from "../../services/socket" import { Button, @@ -125,9 +126,9 @@ const QuickAnswers = () => { }, [searchParam, pageNumber]) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on("quickAnswer", (data) => { + const onQuickAnswerQuickAnswers = (data) => { if (data.action === "update" || data.action === "create") { dispatch({ type: "UPDATE_QUICK_ANSWERS", payload: data.quickAnswer }) } @@ -138,10 +139,11 @@ const QuickAnswers = () => { payload: +data.quickAnswerId, }) } - }) + } + socket.on("quickAnswer", onQuickAnswerQuickAnswers) return () => { - socket.disconnect() + socket.off("quickAnswer", onQuickAnswerQuickAnswers) } }, []) diff --git a/frontend/src/pages/Report/index.js b/frontend/src/pages/Report/index.js index 269f30f..1049857 100644 --- a/frontend/src/pages/Report/index.js +++ b/frontend/src/pages/Report/index.js @@ -18,7 +18,8 @@ import MaterialTable from 'material-table' import LogoutIcon from '@material-ui/icons/CancelOutlined' import apiBroker from "../../services/apiBroker" import fileDownload from 'js-file-download' -import openSocket from "socket.io-client" +//import openSocket from "socket.io-client" +import { socket } from "../../services/socket" import { i18n } from "../../translate/i18n" import Switch from '@mui/material/Switch' @@ -239,7 +240,7 @@ let columnsData = [ { title: `Espera`, field: 'waiting_time' }, { title: `Mensagens`, field: 'messagesToFilter', searchable: true, hidden: true }, { title: `Link`, field: 'link', searchable: false, hidden: true, export: true }, -] +] let columnsDataSuper = [ { title: `Tipo`, field: 'isRemote' }, @@ -381,10 +382,10 @@ const Report = () => { const tickets = data.tickets.map(ticket => { ticket.isRemote = ticket.isRemote ? 'Remoto' : 'Comum'; return ({ - ...ticket, - messagesToFilter: ticket.messages.map(message => message.body).join(' '), - link: `${process.env.REACT_APP_FRONTEND_URL}/tickets/${ticket.id}` - }) + ...ticket, + messagesToFilter: ticket.messages.map(message => message.body).join(' '), + link: `${process.env.REACT_APP_FRONTEND_URL}/tickets/${ticket.id}` + }) }) dispatchQ({ type: "LOAD_QUERY", payload: tickets }) setHasMore(data.hasMore) @@ -591,9 +592,9 @@ const Report = () => { useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on("queryOnQueueStatus", (data) => { + const onQueryOnQueueStatusReport = (data) => { if (data.action === 'update') { if (String(data.queryOnQueue.adminId) === String(userA.id)) { @@ -604,35 +605,39 @@ const Report = () => { } } - }) + } + + socket.on("queryOnQueueStatus", onQueryOnQueueStatusReport) + + const onOnlineStatusReport = (data) => { + + let date = new Date().toLocaleDateString('pt-BR').split('/') + let dateToday = `${date[2]}-${date[1]}-${date[0]}` + + if (data.action === "logout" || (data.action === "update" && + ((`${startDate}` === `${endDate}`) && (`${endDate}` === `${dateToday}`) && (`${startDate}` === `${dateToday}`)))) { + + dispatchQ({ type: "UPDATE_STATUS_ONLINE", payload: data.userOnlineTime }) + + } + else if (data.action === "delete") { + dispatchQ({ type: "DELETE_USER_STATUS", payload: data.userOnlineTime }) + } + + } + + const onUserReport = (data) => { + + if (data.action === "delete") { + dispatch({ type: "DELETE_USER", payload: +data.userId }) + } + } if (reportOption === '2') { + socket.on("onlineStatus", onOnlineStatusReport) - socket.on("onlineStatus", (data) => { - - let date = new Date().toLocaleDateString('pt-BR').split('/') - let dateToday = `${date[2]}-${date[1]}-${date[0]}` - - if (data.action === "logout" || (data.action === "update" && - ((`${startDate}` === `${endDate}`) && (`${endDate}` === `${dateToday}`) && (`${startDate}` === `${dateToday}`)))) { - - dispatchQ({ type: "UPDATE_STATUS_ONLINE", payload: data.userOnlineTime }) - - } - else if (data.action === "delete") { - dispatchQ({ type: "DELETE_USER_STATUS", payload: data.userOnlineTime }) - } - - }) - - socket.on("user", (data) => { - - if (data.action === "delete") { - dispatch({ type: "DELETE_USER", payload: +data.userId }) - } - }) - + socket.on("user", onUserReport) } else if (reportOption === "1") { @@ -641,7 +646,9 @@ const Report = () => { } return () => { - socket.disconnect() + socket.off("onlineStatus", onOnlineStatusReport) + socket.off("user", onUserReport) + socket.off("queryOnQueueStatus", onQueryOnQueueStatusReport) } @@ -687,7 +694,7 @@ const Report = () => { const renderSwitch = (param) => { - if(userA.profile !== 'supervisor'){ + if (userA.profile !== 'supervisor') { switch (param) { case 'empty': return ( @@ -880,7 +887,7 @@ const Report = () => { <> { useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - - socket.on("schedulingNotify", (data) => { - + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + const onSchedulingNotifySchedulesRemider = (data) => { setLoading(true) @@ -228,10 +226,12 @@ const SchedulesReminder = () => { setLoading(false) - }) + } + + socket.on("schedulingNotify", onSchedulingNotifySchedulesRemider) return () => { - socket.disconnect() + socket.off("schedulingNotify", onSchedulingNotifySchedulesRemider) } }, []) @@ -300,9 +300,9 @@ const SchedulesReminder = () => { - useEffect(() => { + useEffect(() => { - if (!loading) { + if (!loading) { setData(query.map(({ scheduleReminder, ...others }) => ( { diff --git a/frontend/src/pages/Settings/index.js b/frontend/src/pages/Settings/index.js index 5dc6bbc..6490aaa 100644 --- a/frontend/src/pages/Settings/index.js +++ b/frontend/src/pages/Settings/index.js @@ -1,5 +1,6 @@ import React, { useState, useEffect, useContext } from 'react' -import openSocket from 'socket.io-client' +//import openSocket from 'socket.io-client' +import { socket } from '../../services/socket.js' import { makeStyles } from '@material-ui/core/styles' import Paper from '@material-ui/core/Paper' @@ -124,9 +125,9 @@ const Settings = () => { useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on('settings', (data) => { + const onSettingsSettings = (data) => { console.log('settings updated ----------------------------') if (data.action === 'update') { @@ -137,10 +138,12 @@ const Settings = () => { return aux }) } - }) + } + + socket.on('settings', onSettingsSettings) return () => { - socket.disconnect() + socket.off("settings", onSettingsSettings) } }, []) @@ -179,7 +182,11 @@ const Settings = () => { } const getSettingValue = (key, _obj = false) => { - const { value, obj } = settings.find((s) => s.key === key) + //const { value, obj } = settings.find((s) => s.key === key) + const setting = settings.find((s) => s.key === key) + + const value = setting?.value || "" + const obj = setting?.obj || null if (_obj) return obj @@ -641,7 +648,7 @@ const Settings = () => { -
+ )} /> diff --git a/frontend/src/pages/StatusChatEnd/index.js b/frontend/src/pages/StatusChatEnd/index.js index 7424a9b..9a6b480 100644 --- a/frontend/src/pages/StatusChatEnd/index.js +++ b/frontend/src/pages/StatusChatEnd/index.js @@ -1,5 +1,6 @@ import React, { useState, useContext, useEffect, useReducer } from "react" -import openSocket from "socket.io-client" +//import openSocket from "socket.io-client" +import { socket } from "../../services/socket" import { Button, @@ -115,7 +116,7 @@ const StatusChatEnd = () => { const { data } = await api.get("/statusChatEnd", { params: { searchParam, pageNumber }, }) - + setChecked(data?.statusChatEnd?.map(s => s.isDefault ? true : false)) dispatch({ type: "LOAD_STATUS_CHAT_END", payload: data.statusChatEnd }) @@ -131,9 +132,9 @@ const StatusChatEnd = () => { }, [searchParam, pageNumber]) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on("statusChatEnd", (data) => { + const onStatusChatEndStatusChatEnd = (data) => { if (data.action === "update" || data.action === "create") { dispatch({ type: "UPDATE_STATUS_CHAT_END", payload: data.statusChatEnd }) } @@ -144,10 +145,12 @@ const StatusChatEnd = () => { payload: +data.statusChatEndId, }) } - }) + } + + socket.on("statusChatEnd", onStatusChatEndStatusChatEnd) return () => { - socket.disconnect() + socket.off("statusChatEnd", onStatusChatEndStatusChatEnd) } }, []) @@ -187,14 +190,14 @@ const StatusChatEnd = () => { } const handleChange = async (event, statusChatEnd, index) => { - + const newChecked = new Array(statusChatEnds.length).fill(false) newChecked[index] = event.target.checked setChecked(newChecked) try { const { id } = statusChatEnd - await api.put(`/statusChatEnd/${id}`, { isDefault: event.target.checked }) + await api.put(`/statusChatEnd/${id}`, { isDefault: event.target.checked }) toast.success("Status de encerramento padrão salvo com sucesso") } catch (error) { diff --git a/frontend/src/pages/Users/index.js b/frontend/src/pages/Users/index.js index c6c3af2..4a090e7 100644 --- a/frontend/src/pages/Users/index.js +++ b/frontend/src/pages/Users/index.js @@ -1,6 +1,7 @@ import React, { useState, useEffect, useReducer, useContext } from "react" import { toast } from "react-toastify" -import openSocket from "socket.io-client" +//import openSocket from "socket.io-client" +import { socket } from "../../services/socket" import { makeStyles } from "@material-ui/core/styles" import Paper from "@material-ui/core/Paper" @@ -165,9 +166,9 @@ const Users = () => { useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + //const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on("user", (data) => { + const onUserUsers = (data) => { if (data.action === "update" || data.action === "create") { dispatch({ type: "UPDATE_USERS", payload: data.user }) } @@ -175,10 +176,11 @@ const Users = () => { if (data.action === "delete") { dispatch({ type: "DELETE_USER", payload: +data.userId }) } - }) + } + socket.on("user", onUserUsers) - socket.on('settings', (data) => { + const onSettingsUsers = (data) => { if (data.action === 'update') { setSettings((prevState) => { const aux = [...prevState] @@ -187,10 +189,12 @@ const Users = () => { return aux }) } - }) + } + socket.on('settings', onSettingsUsers) return () => { - socket.disconnect() + socket.off("settings", onSettingsUsers) + socket.off("user", onUserUsers) } }, []) diff --git a/frontend/src/services/socket.js b/frontend/src/services/socket.js new file mode 100644 index 0000000..b54fe15 --- /dev/null +++ b/frontend/src/services/socket.js @@ -0,0 +1,14 @@ +import { io } from 'socket.io-client'; + +// "undefined" means the URL will be computed from the `window.location` object +const URL = process.env.REACT_APP_BACKEND_URL + +export const socket = io(URL, +//{ +// withCredentials: true, +// extraHeaders: { +// "my-custom-header": "abcd" +// }, + // transports: ['websocket', 'polling'] +//} +); \ No newline at end of file