diff --git a/backend/.wwebjs_auth/sessions.7z b/backend/.wwebjs_auth/sessions.7z deleted file mode 100644 index 5b8a9d6..0000000 Binary files a/backend/.wwebjs_auth/sessions.7z and /dev/null differ diff --git a/backend/package.json b/backend/package.json index 3aeb098..2d4de7c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -26,8 +26,10 @@ "express": "^4.17.1", "express-async-errors": "^3.1.1", "fast-folder-size": "^1.7.0", + "flat": "^5.0.2", "fs-extra": "^10.1.0", "http-graceful-shutdown": "^2.3.2", + "ioredis": "^5.2.3", "jsonwebtoken": "^8.5.1", "multer": "^1.4.2", "mysql2": "^2.2.5", diff --git a/backend/public/.gitkeep b/backend/public/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/backend/src/controllers/ContactController.ts b/backend/src/controllers/ContactController.ts index 536ba3a..c6d25d5 100644 --- a/backend/src/controllers/ContactController.ts +++ b/backend/src/controllers/ContactController.ts @@ -13,6 +13,12 @@ import CheckIsValidContact from "../services/WbotServices/CheckIsValidContact"; import GetProfilePicUrl from "../services/WbotServices/GetProfilePicUrl"; import AppError from "../errors/AppError"; + +import { searchContactCache } from '../helpers/ContactsCache' +import { off } from "process"; + + + type IndexQuery = { searchParam: string; pageNumber: string; @@ -30,12 +36,34 @@ interface ContactData { } export const index = async (req: Request, res: Response): Promise => { - const { searchParam, pageNumber } = req.query as IndexQuery; + let { searchParam, pageNumber } = req.query as IndexQuery; - const { contacts, count, hasMore } = await ListContactsService({ - searchParam, - pageNumber - }); + // TEST DEL + if (searchParam && searchParam.trim().length > 0) { + + try { + + console.log('QUERY CONTACTS FROM CACHE SEARCH PARAM: ', searchParam) + + const offset = 20 * (+pageNumber - 1); + + const data = await searchContactCache(searchParam, offset, 20) + + if (data) { + + console.log('QUERY CONTACTS FROM CACHE QUERY LENGTH: ', data.length) + + return res.json({ contacts: data, count: data.length, hasMore: data.length > 0 ? true : false }); + } + + } catch (error) { + console.log('There was an error on search ContactController.ts search cache: ', error) + } + + + } + + const { contacts, count, hasMore } = await ListContactsService({ searchParam, pageNumber }); return res.json({ contacts, count, hasMore }); }; @@ -58,8 +86,8 @@ export const store = async (req: Request, res: Response): Promise => { } await CheckIsValidContact(newContact.number); - const validNumber : any = await CheckContactNumber(newContact.number) - + const validNumber: any = await CheckContactNumber(newContact.number) + const profilePicUrl = await GetProfilePicUrl(validNumber); let name = newContact.name diff --git a/backend/src/controllers/SchedulingNotifyController.ts b/backend/src/controllers/SchedulingNotifyController.ts index f38ce90..6ca142b 100644 --- a/backend/src/controllers/SchedulingNotifyController.ts +++ b/backend/src/controllers/SchedulingNotifyController.ts @@ -8,7 +8,7 @@ import CreateSchedulingNotifyService from "../services/SchedulingNotifyServices // const test = await ListSchedulingNotifyContactService('5517988310949','2022-03-18','2022-03-19'); // const test = await ListSchedulingNotifyContactService('','2022-03-18','2022-03-19'); // const test = await ListSchedulingNotifyContactService('5517988310949'); -// console.log('$$$$$$$$$$$$$$$$$$$$$$$$$$ test:\n', test) +// @@ -40,7 +40,7 @@ export const createOrUpdateScheduleNotify = async (req: Request, res: Response): const scheduleData = req.body; - console.log(' +++++++++++ scheduleData: ', scheduleData) + const schedulingNotifyCreate = await CreateSchedulingNotifyService( { @@ -63,7 +63,7 @@ export const createOrUpdateScheduleNotify = async (req: Request, res: Response): export const remove = async ( req: Request, res: Response ): Promise => { - console.log('EEEEEEEEEEEEEEEEEEEEEEEEEEE') + const { scheduleId } = req.params; diff --git a/backend/src/controllers/TicketController.ts b/backend/src/controllers/TicketController.ts index a127959..8e8db5e 100644 --- a/backend/src/controllers/TicketController.ts +++ b/backend/src/controllers/TicketController.ts @@ -19,7 +19,9 @@ import ptBR from 'date-fns/locale/pt-BR'; import { splitDateTime } from "../helpers/SplitDateTime"; import format from 'date-fns/format'; +import ListTicketsServiceCache from "../services/TicketServices/ListTicketServiceCache"; +import { searchTicketCache, loadTicketsCache, } from '../helpers/TicketCache' @@ -89,19 +91,14 @@ export const index = async (req: Request, res: Response): Promise => { export const store = async (req: Request, res: Response): Promise => { const { contactId, status, userId }: TicketData = req.body; - - // naty - // console.log( - // `contactId: ${contactId} \n| status: ${status} \n| userId: ${userId}` - // ) - + // test del let ticket = await Ticket.findOne({ where: { contactId, status: 'queueChoice' } }); if (ticket) { await UpdateTicketService({ ticketData: { status: 'open', userId: userId, }, ticketId: ticket.id }); - console.log('TICKET QUEUE CHOICE !!!!!!!') + } else { ticket = await CreateTicketService({ contactId, status, userId }); @@ -145,7 +142,7 @@ export const show = async (req: Request, res: Response): Promise => { export const count = async (req: Request, res: Response): Promise => { - type indexQ = { status: string; date?: string; }; + // type indexQ = { status: string; date?: string; }; const { status, date } = req.query as IndexQuery const ticketCount = await CountTicketService(status, date); @@ -153,10 +150,7 @@ export const count = async (req: Request, res: Response): Promise => { return res.status(200).json(ticketCount); }; - - - - + export const update = async (req: Request, res: Response): Promise => { @@ -184,7 +178,7 @@ export const update = async (req: Request, res: Response): Promise => /////////////////////////////// - //console.log('------- scheduleData.farewellMessage: ', scheduleData.farewellMessage) + // if (scheduleData.farewellMessage) { const whatsapp = await ShowWhatsAppService(ticket.whatsappId); @@ -195,15 +189,11 @@ export const update = async (req: Request, res: Response): Promise => await SendWhatsAppMessage({ body: farewellMessage, ticket }); } } - - /////////////////////////////// - + // lembrete // agendamento if (scheduleData.statusChatEndId === '2' || scheduleData.statusChatEndId === '3') { - - console.log('*** schedulingDate: ', scheduleData.schedulingDate) - console.log('*** schedulingTime: ', scheduleData.schedulingTime) + if (isScheduling(scheduleData.schedulingDate, scheduleData.schedulingTime)) { console.log('*** É AGENDAMENTO!') @@ -255,9 +245,7 @@ export const update = async (req: Request, res: Response): Promise => const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }))) - if (userOldInfo.userId) { - - // console.log('FECHOU...') + if (userOldInfo.userId) { TicketEmiterSumOpenClosedByUser(userOldInfo.userId.toString(), dateToday.fullDate, dateToday.fullDate) diff --git a/backend/src/controllers/UserController.ts b/backend/src/controllers/UserController.ts index bc08d46..89327f2 100644 --- a/backend/src/controllers/UserController.ts +++ b/backend/src/controllers/UserController.ts @@ -112,11 +112,7 @@ export const show = async (req: Request, res: Response): Promise => { export const logoutUser = async (req: Request, res: Response): Promise => { const { userId } = req.params; - //const user = await ShowUserService(userId); - - console.log('userId: ', userId) - - //test del + await stopWhoIsOnlineMonitor() let onlineTime = { diff --git a/backend/src/controllers/WhatsAppController.ts b/backend/src/controllers/WhatsAppController.ts index d94af3c..253714d 100644 --- a/backend/src/controllers/WhatsAppController.ts +++ b/backend/src/controllers/WhatsAppController.ts @@ -123,9 +123,7 @@ export const remove = async ( removeDir(path.join(process.cwd(), '.wwebjs_auth', `session-bd_${whatsappId}`)) - removeWbot(+whatsappId); - - console.log('Deleteou o whatsapp service com id = ', whatsappId) + removeWbot(+whatsappId); const io = getIO(); io.emit("whatsapp", { diff --git a/backend/src/controllers/WhatsAppSessionController.ts b/backend/src/controllers/WhatsAppSessionController.ts index 716b81a..6cd2317 100644 --- a/backend/src/controllers/WhatsAppSessionController.ts +++ b/backend/src/controllers/WhatsAppSessionController.ts @@ -56,14 +56,7 @@ const remove = async (req: Request, res: Response): Promise => { const { whatsappId } = req.params; const whatsapp = await ShowWhatsAppService(whatsappId); - const wbot = getWbot(whatsapp.id); - - console.log( - 'Desconectou s whatsapp.id: ', whatsapp.id, - ' | PATH TO DELETE',path.join(process.cwd(),'.wwebjs_auth', `session-bd_${whatsapp.id}`) - ) - - //removeDir(path.join(process.cwd(),'.wwebjs_auth', `session-bd_${whatsapp.id}`)) + const wbot = getWbot(whatsapp.id); await wbot.logout(); diff --git a/backend/src/helpers/ContactsCache.ts b/backend/src/helpers/ContactsCache.ts new file mode 100644 index 0000000..d6a2838 --- /dev/null +++ b/backend/src/helpers/ContactsCache.ts @@ -0,0 +1,209 @@ + +import Redis from 'ioredis' +import { type } from 'os' +const unflatten = require('flat').unflatten +var flatten = require('flat') +import ListContactsServiceCache from "../services/ContactServices/ListContactsServiceCache" +import { redisConn } from './TicketCache' + + +const deleteContactsByIdCache = async (id: string | number) => { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + const contact_cache: any = await redis.hgetall(`contact:${id}`) + + try { + if (contact_cache && Object.keys(contact_cache).length > 0) { + + await redis.del(`contact:${id}`) + + console.log(`Contacts cache number ${contact_cache['number']} deleted!`) + } + else { + console.log('CONTACT CACHE NOT FOUND!') + } + } catch (error) { + console.log(`There was an error on deleteContactsByIdCache: ${error}`) + } + + redis.quit() +} + +const updateContactCache = async (hash: any, json_object: any) => { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + const pipeline = redis.pipeline() + + let entries = Object.entries(json_object) + + entries.forEach((e: any) => { + pipeline.hset(hash, e[0], e[1]) + }) + + await pipeline.exec(() => { console.log("Key/value inserted/updated") }); + + redis.quit() + +} + +const updateContactCacheById = async (id: string | number, update_fields: object | any) => { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + const contact_cache: any = await redis.hgetall(`contact:${id}`) + + try { + if (contact_cache && Object.keys(contact_cache).length > 0) { + + // await redis.del(`contact:${id}`) + + update_fields.escaped_name = escapeCharCache(update_fields.name) + + await updateContactCache(`contact:${id}`, update_fields) + + console.log(`CONTACT ${contact_cache['number']} CACHE WAS UPDATED!`) + } + else { + console.log('CONTACT CACHE NOT FOUND!') + } + } catch (error) { + console.log(`There was an error on updateContactCacheById: ${error}`) + } + + redis.quit() +} + +const createOrUpdateContactCache = async (hash: any, contact: any) => { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + if (contact.name) { + contact.escaped_name = escapeCharCache(contact.name) + } + + await redis.hmset(hash, contact); + + redis.quit() + +} + + +async function searchContactCache(search: string, offset: number, limit: number) { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return null + + search = escapeCharCache(search) + + const response: any = await redis.call('FT.SEARCH', 'idx_contact', `(@escaped_name:*${search}*)|(@number:*${search}*)`, 'LIMIT', offset, limit, 'SORTBY', 'escaped_name', 'ASC') + redis.quit() + + + if (response.length === 1) { + return [] + } + + const results: any = [] + + for (let n = 2; n < response.length; n += 2) { + const result: any = {} + const fieldNamesAndValues = response[n] + + for (let m = 0; m < fieldNamesAndValues.length; m += 2) { + const k = fieldNamesAndValues[m] + const v = fieldNamesAndValues[m + 1] + result[k] = v + } + + results.push(result) + } + + return results +} + + +const removeExtraSpace = (str: string) => { + + str = str.replace(/^\s+/g, '') + + return str.replace(/\s+/g, ' ') +} + +const escapeCharCache = (str: string) => { + + const pattern = /[\'|\"|\.|\,|\;|\<|\>|\{|\}|\[|\]|\"|\'|\=|\~|\*|\:|\#|\+|\^|\$|\@|\%|\!|\&|\)|\(|/|\-|\\)]/g; // no match, use replace function. + + let newStr = str.replace(pattern, (t1) => `\\${t1}`); + + newStr = removeExtraSpace(newStr) + + return newStr.trim() + +} + +const loadContactsCache = async () => { + + await createContactIndexCache('idx_contact') + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + let contacts = await ListContactsServiceCache() + + const pipeline = redis.pipeline() + + for (let i = 0; i < contacts.length; i++) { + + contacts[i].createdAt = new Date(contacts[i].createdAt).toISOString() + contacts[i].updatedAt = new Date(contacts[i].updatedAt).toISOString() + + contacts[i].escaped_name = escapeCharCache(contacts[i].name) + + pipeline.hmset(`contact:${contacts[i].id}`, contacts[i]); + } + + await pipeline.exec(() => { console.log(`${contacts.length} CONTACTS INSERTED IN CACHE!`) }); + + redis.quit() +} + +const createContactIndexCache = async (hashIndex: string) => { + + const redis: any = await redisConn(); + + if (redis.status !== 'connect') return + + try { + + const lst_index_redis: any = await redis.call('FT._LIST') + + if (lst_index_redis.includes(hashIndex)) { + console.log('entrou...') + await redis.call('FT.DROPINDEX', hashIndex) + } + + const response = await redis.call('FT.CREATE', hashIndex, 'ON', 'HASH', 'PREFIX', '1', 'contact:', 'SCHEMA', 'escaped_name', 'TEXT', 'SORTABLE', 'number', 'TEXT', 'SORTABLE') + + console.log('Contact index created: ', response) + + } catch (error) { + console.log('There was an error on createContactIndexCache: ', error) + } + + redis.quit() +} + +export { + loadContactsCache, + searchContactCache, + deleteContactsByIdCache, + updateContactCacheById, + createOrUpdateContactCache, + escapeCharCache +} \ No newline at end of file diff --git a/backend/src/helpers/LoadBalanceWhatsSameQueue.ts b/backend/src/helpers/LoadBalanceWhatsSameQueue.ts index c551c25..e70951a 100644 --- a/backend/src/helpers/LoadBalanceWhatsSameQueue.ts +++ b/backend/src/helpers/LoadBalanceWhatsSameQueue.ts @@ -10,9 +10,7 @@ export const WhatsIndex = (whatsapps: Object[]) => { if (WhatsQueueIndex.getIndex() >= whatsapps.length) { WhatsQueueIndex.setIndex(0) - } - - // console.log('WhatsQueueIndex.getIndex(): ', WhatsQueueIndex.getIndex()) + } index = +WhatsQueueIndex.getIndex() diff --git a/backend/src/helpers/SchedulingNotifySendMessage.ts b/backend/src/helpers/SchedulingNotifySendMessage.ts index 444c26a..44c8b54 100644 --- a/backend/src/helpers/SchedulingNotifySendMessage.ts +++ b/backend/src/helpers/SchedulingNotifySendMessage.ts @@ -90,21 +90,20 @@ const monitor = async () => { whatsapps.forEach(async whats => { - // console.log('whats id: ', whats.id) + const sourcePath = path.join(__dirname, `../../.wwebjs_auth/`, `session-bd_${whats.id}`) if (fs.existsSync(sourcePath)) { try { - // console.log('dir path exist!') + const fastFolderSizeAsync = promisify(fastFolderSize) let size = await fastFolderSizeAsync(sourcePath) size = convertBytes(size) - - // console.log(size) + // SESSION MONITORING const io = getIO(); diff --git a/backend/src/helpers/SetTicketMessagesAsRead.ts b/backend/src/helpers/SetTicketMessagesAsRead.ts index 379f18a..326ca86 100644 --- a/backend/src/helpers/SetTicketMessagesAsRead.ts +++ b/backend/src/helpers/SetTicketMessagesAsRead.ts @@ -50,17 +50,15 @@ const SetTicketMessagesAsRead = async (ticket: Ticket): Promise => { const whatsapp = await ShowWhatsAppService(ticket.whatsappId); - if (whatsapp && whatsapp.status == 'CONNECTED') { - - console.log('SetTicketMessagesAsRead.ts - ENTROU NO RESTORE...') + if (whatsapp && whatsapp.status == 'CONNECTED') { + let timestamp = Math.floor(Date.now() / 1000) fs.writeFile(`${sourcePath}/${timestamp}_SetTicketMessagesAsRead.txt`, `Whatsapp id: ${whatsapp.id} \nDate: ${dateToday.fullDate} ${dateToday.fullTime} \nFile: SetTicketMessagesAsRead.ts \nError: ${err}`, (error)=>{}); await restartWhatsSession(whatsapp) - - console.log('...PASSOU O RESTORE - SetTicketMessagesAsRead.ts ') + } } diff --git a/backend/src/helpers/SumOlineTimeNow.ts b/backend/src/helpers/SumOlineTimeNow.ts index 3b61f75..a02772d 100644 --- a/backend/src/helpers/SumOlineTimeNow.ts +++ b/backend/src/helpers/SumOlineTimeNow.ts @@ -8,8 +8,7 @@ import { addHours, addMinutes, addSeconds, intervalToDuration, add } from "date- onlineTime.setUTCHours(new Date(oldOnlineTimeSum.onlineTime).getHours()) onlineTime.setUTCMinutes(new Date(oldOnlineTimeSum.onlineTime).getMinutes()) onlineTime.setUTCSeconds(new Date(oldOnlineTimeSum.onlineTime).getSeconds()) - - // console.log('_________________oldOnlineTimeSum.updatedAt: ', oldOnlineTimeSum.updatedAt) + let newtTime = intervalToDuration({ start: new Date(oldOnlineTimeSum.updatedAt), end: new Date() }) @@ -25,8 +24,7 @@ import { addHours, addMinutes, addSeconds, intervalToDuration, add } from "date- } const isoDate = new Date(onlineTime); - const newOnlinetime = isoDate.toJSON().slice(0, 19).replace('T', ' '); - //console.log('sum new online time: ', newOnlinetime) + const newOnlinetime = isoDate.toJSON().slice(0, 19).replace('T', ' '); return newOnlinetime } diff --git a/backend/src/helpers/TicketCache.ts b/backend/src/helpers/TicketCache.ts new file mode 100644 index 0000000..c9f414f --- /dev/null +++ b/backend/src/helpers/TicketCache.ts @@ -0,0 +1,389 @@ + +import Redis from 'ioredis' +import { List } from 'whatsapp-web.js' +const unflatten = require('flat').unflatten +var flatten = require('flat') +import ListTicketServiceCache from "../services/TicketServices/ListTicketServiceCache" + +import { escapeCharCache } from './ContactsCache' + + +const redisConn = async () => { + + try { + + const redis = new Redis(); + + const conn = () => new Promise((resolve, reject) => { + + redis.on('error', (err) => { + + if (err.code === 'ECONNREFUSED') { + console.error(`Redis connection error: ${err}.`) + redis.quit() + } + else { + console.error(`Redis encountered an error: ${err.message}.`) + } + + reject(err) + + }) + + redis.on('connect', () => { + + resolve(redis); + + }) + }); + + return await conn(); + + } catch (e) { + console.error(e); + return Promise.resolve([]); + } + +} + + +const flushCache = async () => { + + const redis: any = await redisConn(); + + if (redis.status === 'connect') { + + console.log('TICKETS CACHE REMOVED') + await redis.call('FLUSHALL') + redis.quit() + } + +} + +const cacheSize = async () => { + + const redis: any = await redisConn(); + + if (redis.status !== 'connect') { + return -1 + } + + const size = await redis.call('dbsize') + redis.quit() + return size + +} + +const loadTicketsCache = async () => { + + const redis: any = await redisConn(); + + if (redis.status !== 'connect') return + + await createTicketIndexCache('idx_ticket') + + let tickets = await ListTicketServiceCache({}) + + const pipeline = redis.pipeline() + + for (let i = 0; i < tickets.length; i++) { + + tickets[i].createdAt = new Date(tickets[i].createdAt).toISOString() + tickets[i].updatedAt = new Date(tickets[i].updatedAt).toISOString() + + tickets[i].escaped_name = escapeCharCache(tickets[i]['contact.name']) + + // tickets[i]['contact_name'] = tickets[i]['contact.name'] + // delete tickets[i]['contact.name'] + + tickets[i]['contact_number'] = tickets[i]['contact.number'] + delete tickets[i]['contact.number'] + + pipeline.hmset(`ticket:${tickets[i].id}`, tickets[i]); + } + + await pipeline.exec(() => { console.log(`${tickets.length} TICKETS INSERTED IN CACHE!`) }); + + redis.quit() +} + + +const createTicketIndexCache = async (hashIndex: string) => { + + const redis: any = await redisConn(); + + if (redis.status !== 'connect') return + + try { + + const lst_index_redis: any = await redis.call('FT._LIST') + + if (lst_index_redis.includes(hashIndex)) { + console.log('entrou...') + await redis.call('FT.DROPINDEX', hashIndex) + } + + const response = await redis.call('FT.CREATE', hashIndex, 'ON', 'HASH', 'PREFIX', '1', 'ticket:', 'SCHEMA', 'escaped_name', 'TEXT', 'SORTABLE', 'contact_number', 'TEXT', 'SORTABLE', 'status', 'TAG', 'SORTABLE') + + console.log('Ticket index created: ', response) + + } catch (error) { + console.log('There was an error on createTicketIndexCache: ', error) + } + + redis.quit() +} + +const updateTicketCache = async (hash: any, json_object: any) => { + + const redis: any = await redisConn(); + + if (redis.status !== 'connect') return + + const pipeline = redis.pipeline() + let entries = Object.entries(json_object) + + entries.forEach((e: any) => { + pipeline.hset(hash, e[0], e[1]) + }) + + await pipeline.exec(() => { console.log("updateTicketCache Key/value inserted/updated") }); + + redis.quit() + +} + +const updateTicketCacheByTicketId = async (ticketId: string | number, update_fields: any) => { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + const ticket_cache = await redis.hgetall(`ticket:${ticketId}`) + + try { + if (ticket_cache && Object.keys(ticket_cache).length > 0) { + + if (update_fields.escaped_name) { + update_fields.escaped_name = escapeCharCache(update_fields['contact.name']) + } + + await updateTicketCache(`ticket:${ticketId}`, update_fields) + + console.log(`updateTicketCacheByTicketId TICKET ${ticket_cache['contact_number']} CACHE WAS UPDATED!`) + } + else { + console.log('TICKET CACHE NOT FOUND!') + } + } catch (error) { + console.log(`There was an error on updateTicketCacheByTicketId: ${error}`) + } + + redis.quit() + + +} + + +const createOrUpdateTicketCache = async (hash: any, ticket: any) => { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + if (redis.status !== 'connect') return + + ticket.escaped_name = escapeCharCache(ticket['contact.name']) + + ticket['contact_number'] = ticket['contact.number'] + delete ticket['contact.number'] + + await redis.hmset(hash, ticket); + + console.log('CREATED/UPDATED TICKET CACHE') + + redis.quit() + +} + +const deleteTicketsByIdCache = async (ticketId: string | number) => { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + const ticket_cache = await redis.hgetall(`ticket:${ticketId}`) + + try { + if (ticket_cache && Object.keys(ticket_cache).length > 0) { + + await redis.del(`ticket:${ticketId}`) + + console.log(`TICKET ${ticket_cache['id']} CACHE WAS DELETED!`) + } + else { + console.log('TICKET CACHE NOT FOUND!') + } + } catch (error) { + console.log(`There was an error on deleteTicketsByIdCache: ${error}`) + } + + redis.quit() + +} + +const deleteTicketsFieldsCache = async (tickets: any, del_fields: any) => { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + const pipeline = redis.pipeline() + + if (tickets && tickets.length > 0) { + try { + + for (let i = 0; i < tickets.length; i++) { + + pipeline.hdel(`ticket:${tickets[i]['id']}`, del_fields) + + } + + await pipeline.exec(() => { console.log(`Tickets cache contact updated!`) }) + + } catch (error) { + console.log('There was an error on deleteTicketsFieldsByContactsCache function: ', error) + } + + } + + redis.quit() + +} + + +const updateTicketsByContactsCache = async (oldNumber: string, newName: string, newNumber: string) => { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + const pipeline = redis.pipeline() + + const tickets = await searchTicketCache(oldNumber) + + if (tickets && tickets.length > 0) { + try { + for (let i = 0; i < tickets.length; i++) { + + tickets[i]['contact.name'] = newName + tickets[i].escaped_name = escapeCharCache(newName) + tickets[i]['contact_number'] = newNumber + + pipeline.hmset(`ticket:${tickets[i]['id']}`, tickets[i]) + + } + + await pipeline.exec(() => { console.log(`updateTicketsByContactsCache Tickets cache contact updated!`) }) + + } catch (error) { + console.log('There was an error on updateTicketsByContactsCache function: ', error) + } + + } + + redis.quit() + +} + + +const deleteTicketsByContactsCache = async (number: string) => { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + const pipeline = redis.pipeline() + + const tickets = await searchTicketCache(number) + + if (tickets && tickets.length > 0) { + try { + for (let i = 0; i < tickets.length; i++) { + + pipeline.del(`ticket:${tickets[i]['id']}`) + + } + + await pipeline.exec(() => { console.log(`Tickets cache number ${tickets[0]['contact_number']} deleted!`) }) + + } catch (error) { + console.log('There was an error on deleteTicketsByContactsCache function: ', error) + } + + } + + redis.quit() + +} + +const deleteTicketCache = async (hash: any) => { + + const redis: any = await redisConn(); + if (redis.status !== 'connect') return + + await redis.del(hash) + redis.quit() + +} + +async function searchTicketCache(search: string, offset?: number, limit?: number) { + + const redis:any = await redisConn(); + + if(redis.status!=='connect') return null + + search = escapeCharCache(search) + + let response: any = undefined + + if (offset != undefined && limit != undefined) { + response = await redis.call('FT.SEARCH', 'idx_ticket', `(@escaped_name:*${search}*)|(@contact_number:*${search}*)`, 'LIMIT', offset, limit, 'SORTBY', 'status', 'DESC') + } + else { + response = await redis.call('FT.SEARCH', 'idx_ticket', `(@escaped_name:*${search}*)|(@contact_number:*${search}*)`) + } + redis.quit() + + // console.log('response: ', response) + + if (response.length === 1) { + return [] + } + + const results: any = [] + + for (let n = 2; n < response.length; n += 2) { + const result: any = {} + const fieldNamesAndValues = response[n] + + for (let m = 0; m < fieldNamesAndValues.length; m += 2) { + const k = fieldNamesAndValues[m] + const v = fieldNamesAndValues[m + 1] + result[k] = v + } + + results.push(result) + } + + return results +} + +export { + loadTicketsCache, + updateTicketCache, + createOrUpdateTicketCache, + searchTicketCache, + updateTicketCacheByTicketId, + deleteTicketsByContactsCache, + updateTicketsByContactsCache, + deleteTicketsByIdCache, + flushCache, + deleteTicketsFieldsCache, + cacheSize, + redisConn +} \ No newline at end of file diff --git a/backend/src/helpers/UpdateDeletedUserOpenTicketsStatus.ts b/backend/src/helpers/UpdateDeletedUserOpenTicketsStatus.ts index 6e05ffb..45f2b59 100644 --- a/backend/src/helpers/UpdateDeletedUserOpenTicketsStatus.ts +++ b/backend/src/helpers/UpdateDeletedUserOpenTicketsStatus.ts @@ -1,16 +1,16 @@ import Ticket from "../models/Ticket"; -import UpdateTicketService from "../services/TicketServices/UpdateTicketService"; +import UpdateTicketService from "../services/TicketServices/UpdateTicketService"; const UpdateDeletedUserOpenTicketsStatus = async ( tickets: Ticket[] ): Promise => { tickets.forEach(async t => { - const ticketId = t.id.toString(); + + const ticketId = t.id.toString(); + + await UpdateTicketService({ ticketData: { status: "pending" }, ticketId }); + - await UpdateTicketService({ - ticketData: { status: "pending" }, - ticketId - }); }); }; diff --git a/backend/src/helpers/WhoIsOnlineMonitor.ts b/backend/src/helpers/WhoIsOnlineMonitor.ts index 150a07a..406c0e6 100644 --- a/backend/src/helpers/WhoIsOnlineMonitor.ts +++ b/backend/src/helpers/WhoIsOnlineMonitor.ts @@ -97,8 +97,7 @@ const monitor = async () => { const indexAux = lstOnline.findIndex((e: any) => e.id == el.id) - if (indexAux == -1) { - console.log(' entrou indexAux: ', indexAux) + if (indexAux == -1) { const userOnline = await createOrUpdateOnlineUserService({ userId: el.id, status: 'online' }) diff --git a/backend/src/libs/socket.ts b/backend/src/libs/socket.ts index 9e8f48f..1323a26 100644 --- a/backend/src/libs/socket.ts +++ b/backend/src/libs/socket.ts @@ -79,8 +79,7 @@ export const initIO = (httpServer: Server): SocketIO => { if (index == -1) { listOnlineAux.push({ 'id': userId }) } - else { - console.log(' -------------- PULO FORA') + else { return } diff --git a/backend/src/models/Message.ts b/backend/src/models/Message.ts index 4f49b88..65f05cf 100644 --- a/backend/src/models/Message.ts +++ b/backend/src/models/Message.ts @@ -37,9 +37,7 @@ class Message extends Model { @Column(DataType.STRING) get mediaUrl(): string | null { if (this.getDataValue("mediaUrl")) { - return `${process.env.BACKEND_URL}:${ - process.env.PROXY_PORT - }/public/${this.getDataValue("mediaUrl")}`; + return `${process.env.BACKEND_URL}:${process.env.PROXY_PORT}/public/${this.getDataValue("mediaUrl")}`; } return null; } diff --git a/backend/src/routes/ticketRoutes.ts b/backend/src/routes/ticketRoutes.ts index e2c0a76..0524925 100644 --- a/backend/src/routes/ticketRoutes.ts +++ b/backend/src/routes/ticketRoutes.ts @@ -6,6 +6,8 @@ import * as TicketController from "../controllers/TicketController"; const ticketRoutes = express.Router(); +// ticketRoutes.get("/tickets/cache", isAuth, TicketController.ticketsCache); + ticketRoutes.get("/tickets/count", isAuth, TicketController.count); ticketRoutes.get("/tickets", isAuth, TicketController.index); diff --git a/backend/src/server.ts b/backend/src/server.ts index a13b9e2..c157334 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -7,6 +7,9 @@ import { StartAllWhatsAppsSessions } from "./services/WbotServices/StartAllWhats import { startSchedulingMonitor } from "./helpers/SchedulingNotifySendMessage" import { startWhoIsOnlineMonitor } from "./helpers/WhoIsOnlineMonitor" +import { loadTicketsCache, flushCache, cacheSize } from './helpers/TicketCache' +import { loadContactsCache } from './helpers/ContactsCache' + const server = app.listen(process.env.PORT, () => { logger.info(`Server started on port: ${process.env.PORT}`); }); @@ -15,5 +18,20 @@ initIO(server); StartAllWhatsAppsSessions(); gracefulShutdown(server); +(async()=>{ + + const cacheLength = await cacheSize() + + if(cacheLength == 0){ + console.log('Loading from cache...') + await flushCache() + await loadContactsCache() + await loadTicketsCache() + } + +})() + + startSchedulingMonitor(5000) -startWhoIsOnlineMonitor(50000) +startWhoIsOnlineMonitor(3000) + diff --git a/backend/src/services/ContactServices/CreateContactService.ts b/backend/src/services/ContactServices/CreateContactService.ts index 331d175..172b1a6 100644 --- a/backend/src/services/ContactServices/CreateContactService.ts +++ b/backend/src/services/ContactServices/CreateContactService.ts @@ -1,6 +1,8 @@ import AppError from "../../errors/AppError"; import Contact from "../../models/Contact"; +import { createOrUpdateContactCache } from '../../helpers/ContactsCache' + interface ExtraInfo { name: string; value: string; @@ -40,6 +42,12 @@ const CreateContactService = async ({ } ); + + // TEST DEL + await createOrUpdateContactCache(`contact:${contact.id}`, {id: contact.id, name, number, profilePicUrl:'', isGroup:'false', extraInfo, email }) + // + + return contact; }; diff --git a/backend/src/services/ContactServices/CreateOrUpdateContactService.ts b/backend/src/services/ContactServices/CreateOrUpdateContactService.ts index 10a25af..380cf9c 100644 --- a/backend/src/services/ContactServices/CreateOrUpdateContactService.ts +++ b/backend/src/services/ContactServices/CreateOrUpdateContactService.ts @@ -1,6 +1,8 @@ import { getIO } from "../../libs/socket"; import Contact from "../../models/Contact"; +import { createOrUpdateContactCache } from '../../helpers/ContactsCache' + interface ExtraInfo { name: string; value: string; @@ -28,10 +30,15 @@ const CreateOrUpdateContactService = async ({ const io = getIO(); let contact: Contact | null; + contact = await Contact.findOne({ where: { number } }); if (contact) { - contact.update({ profilePicUrl }); + contact.update({ profilePicUrl }); + + // TEST DEL + await createOrUpdateContactCache(`contact:${contact.id}`, { profilePicUrl }) + // io.emit("contact", { action: "update", @@ -47,6 +54,11 @@ const CreateOrUpdateContactService = async ({ extraInfo }); + // TEST DEL + await createOrUpdateContactCache(`contact:${contact.id}`, {id: contact.id, name, number, profilePicUrl, isGroup, extraInfo, email }) + // + + io.emit("contact", { action: "create", contact diff --git a/backend/src/services/ContactServices/DeleteContactService.ts b/backend/src/services/ContactServices/DeleteContactService.ts index caaf86a..4002996 100644 --- a/backend/src/services/ContactServices/DeleteContactService.ts +++ b/backend/src/services/ContactServices/DeleteContactService.ts @@ -1,6 +1,9 @@ import Contact from "../../models/Contact"; import AppError from "../../errors/AppError"; +import { deleteTicketsByContactsCache } from '../../helpers/TicketCache' +import {deleteContactsByIdCache} from '../../helpers/ContactsCache' + const DeleteContactService = async (id: string): Promise => { const contact = await Contact.findOne({ where: { id } @@ -10,6 +13,11 @@ const DeleteContactService = async (id: string): Promise => { throw new AppError("ERR_NO_CONTACT_FOUND", 404); } + // TEST DEL + await deleteTicketsByContactsCache(contact.number) + await deleteContactsByIdCache(contact.id) + // + await contact.destroy(); }; diff --git a/backend/src/services/ContactServices/ListContactsService.ts b/backend/src/services/ContactServices/ListContactsService.ts index 0bd7a38..f624308 100644 --- a/backend/src/services/ContactServices/ListContactsService.ts +++ b/backend/src/services/ContactServices/ListContactsService.ts @@ -29,14 +29,14 @@ const ListContactsService = async ({ ] }; const limit = 20; - const offset = limit * (+pageNumber - 1); + const offset = limit * (+pageNumber - 1); const { count, rows: contacts } = await Contact.findAndCountAll({ where: whereCondition, limit, offset, order: [["name", "ASC"]] - }); + }); const hasMore = count > offset + contacts.length; diff --git a/backend/src/services/ContactServices/ListContactsServiceCache.ts b/backend/src/services/ContactServices/ListContactsServiceCache.ts new file mode 100644 index 0000000..3690f8f --- /dev/null +++ b/backend/src/services/ContactServices/ListContactsServiceCache.ts @@ -0,0 +1,11 @@ +import { Sequelize, Op } from "sequelize"; +import Contact from "../../models/Contact"; + +const ListContactsServiceCache = async (): Promise => { + + const contacts = await Contact.findAll({ where: {}, raw:true, order: [["name", "ASC"]] }); + + return contacts +}; + +export default ListContactsServiceCache; diff --git a/backend/src/services/ContactServices/UpdateContactService.ts b/backend/src/services/ContactServices/UpdateContactService.ts index 8211766..4548577 100644 --- a/backend/src/services/ContactServices/UpdateContactService.ts +++ b/backend/src/services/ContactServices/UpdateContactService.ts @@ -2,6 +2,9 @@ import AppError from "../../errors/AppError"; import Contact from "../../models/Contact"; import ContactCustomField from "../../models/ContactCustomField"; +import { updateTicketsByContactsCache } from '../../helpers/TicketCache' +import { updateContactCacheById } from '../../helpers/ContactsCache' + interface ExtraInfo { id?: number; name: string; @@ -18,6 +21,7 @@ interface Request { contactData: ContactData; contactId: string; } + const UpdateContactService = async ({ contactData, @@ -51,19 +55,31 @@ const UpdateContactService = async ({ } }) ); - } + } + + const oldNumber = contact.number await contact.update({ name, number, email - }); + }); + + //TEST DEL + await updateTicketsByContactsCache(oldNumber, contact.name, contact.number) + // + await contact.reload({ attributes: ["id", "name", "number", "email", "profilePicUrl"], include: ["extraInfo"] }); + + + // console.log('contactcontactcontactcontact: ',flatten(JSON.parse(JSON.stringify(contact)))) + await updateContactCacheById(contact.id, JSON.parse(JSON.stringify(contact))) + return contact; }; diff --git a/backend/src/services/MessageServices/CreateMessageService.ts b/backend/src/services/MessageServices/CreateMessageService.ts index e2958e7..4ccac9b 100644 --- a/backend/src/services/MessageServices/CreateMessageService.ts +++ b/backend/src/services/MessageServices/CreateMessageService.ts @@ -1,3 +1,4 @@ +import { updateTicketCacheByTicketId } from "../../helpers/TicketCache"; import { getIO } from "../../libs/socket"; import Message from "../../models/Message"; import Ticket from "../../models/Ticket"; @@ -16,7 +17,7 @@ interface Request { messageData: MessageData; } -const CreateMessageService = async ({messageData}: Request): Promise => { +const CreateMessageService = async ({ messageData }: Request): Promise => { await Message.upsert(messageData); const message = await Message.findByPk(messageData.id, { @@ -39,9 +40,20 @@ const CreateMessageService = async ({messageData}: Request): Promise => throw new Error("ERR_CREATING_MESSAGE"); } - - - if(message.ticket.status!='queueChoice'){ + + if (message.ticket.status != 'queueChoice') { + + + // TEST DEL + await updateTicketCacheByTicketId(message.ticket.id, + { + lastMessage: message.body, + updatedAt: new Date(message.ticket.updatedAt).toISOString(), + 'contact.profilePicUrl': message.ticket.contact.profilePicUrl, + unreadMessages: message.ticket.unreadMessages + }) + // + const io = getIO(); io.to(message.ticketId.toString()) @@ -54,8 +66,8 @@ const CreateMessageService = async ({messageData}: Request): Promise => contact: message.ticket.contact }); - } - + } + return message; }; diff --git a/backend/src/services/QueueService/DeleteQueueService.ts b/backend/src/services/QueueService/DeleteQueueService.ts index 7bd39fc..59201d7 100644 --- a/backend/src/services/QueueService/DeleteQueueService.ts +++ b/backend/src/services/QueueService/DeleteQueueService.ts @@ -2,14 +2,31 @@ import ShowQueueService from "./ShowQueueService"; import UserQueue from "../../models/UserQueue"; +import ListTicketsServiceCache from "../TicketServices/ListTicketServiceCache"; + +import { deleteTicketsFieldsCache } from '../../helpers/TicketCache' + const DeleteQueueService = async (queueId: number | string): Promise => { + const queue = await ShowQueueService(queueId); + if (queue.id) { + + const tickets = await ListTicketsServiceCache({ queueId }) + + await deleteTicketsFieldsCache(tickets, ['queue.id', 'queue.name', 'queue.color']) + + } + try { - await UserQueue.destroy({ where: {queueId: queueId } }); + + await UserQueue.destroy({ where: { queueId: queueId } }); + } catch (error) { - console.log('Error on delete UserQueue by queueId: ',queueId) - } + + console.log('Error on delete UserQueue by queueId: ', queueId) + + } await queue.destroy(); }; diff --git a/backend/src/services/SchedulingNotifyServices/CreateSchedulingNotifyService.ts b/backend/src/services/SchedulingNotifyServices/CreateSchedulingNotifyService.ts index 13931bb..1315d5b 100644 --- a/backend/src/services/SchedulingNotifyServices/CreateSchedulingNotifyService.ts +++ b/backend/src/services/SchedulingNotifyServices/CreateSchedulingNotifyService.ts @@ -23,9 +23,7 @@ const CreateSchedulingNotifyService = async ({ let schedulingNotify = null; - if(schedulingNotifyId){ - - console.log('000000000000000000000000000 ATUALIZOU!') + if(schedulingNotifyId){ schedulingNotify = await SchedulingNotify.findOne({ where: { id: schedulingNotifyId } }); @@ -48,9 +46,7 @@ const CreateSchedulingNotifyService = async ({ } if(!schedulingNotify){ - - console.log('111111111111111111111111111 criou!') - + schedulingNotify = await SchedulingNotify.create( { ticketId, diff --git a/backend/src/services/TicketServices/CreateTicketService.ts b/backend/src/services/TicketServices/CreateTicketService.ts index 50eb44d..936033f 100644 --- a/backend/src/services/TicketServices/CreateTicketService.ts +++ b/backend/src/services/TicketServices/CreateTicketService.ts @@ -13,6 +13,11 @@ import ptBR from 'date-fns/locale/pt-BR'; import { splitDateTime } from "../../helpers/SplitDateTime"; import TicketEmiterSumOpenClosedByUser from "../../helpers/OnlineReporEmiterInfoByUser"; +import { createOrUpdateTicketCache } from '../../helpers/TicketCache' +let flatten = require('flat') + + + interface Request { contactId: number; status: string; @@ -41,16 +46,29 @@ const CreateTicketService = async ({ if (!ticket) { throw new AppError("ERR_CREATING_TICKET"); - } + } + + // console.log('CONTACT ticket.id: ', ticket.id) - //test del - // 2022-05-11T05:20:33.000Z, - // const dateToday = ticket.createdAt.toISOString().split('T')[0] + // TEST DEL + try { + + let jsonString = JSON.stringify(ticket); //convert to string to remove the sequelize specific meta data + let ticket_obj = JSON.parse(jsonString); //to make plain json + delete ticket_obj['contact']['extraInfo'] + + ticket_obj = flatten(ticket_obj) + + await createOrUpdateTicketCache(`ticket:${ticket.id}`, ticket_obj) + + } catch (error) { + console.log('There was an error on UpdateTicketService.ts on createTicketCache from user: ', error) + } + // - const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }))) - - //openByUser : [ { id: 13, status: 'online' } ] + + const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }))) TicketEmiterSumOpenClosedByUser(userId.toString(), dateToday.fullDate, dateToday.fullDate) @@ -58,10 +76,7 @@ const CreateTicketService = async ({ io.emit("ticketStatus", { action: "update", ticketStatus: {ticketId: ticket.id, status: ticket.status} - }); - - - // + }); return ticket; diff --git a/backend/src/services/TicketServices/DeleteTicketService.ts b/backend/src/services/TicketServices/DeleteTicketService.ts index 279a913..cc2e3fa 100644 --- a/backend/src/services/TicketServices/DeleteTicketService.ts +++ b/backend/src/services/TicketServices/DeleteTicketService.ts @@ -1,6 +1,8 @@ import Ticket from "../../models/Ticket"; import AppError from "../../errors/AppError"; +import { deleteTicketsByIdCache } from '../../helpers/TicketCache' + const DeleteTicketService = async (id: string): Promise => { const ticket = await Ticket.findOne({ where: { id } @@ -10,7 +12,11 @@ const DeleteTicketService = async (id: string): Promise => { throw new AppError("ERR_NO_TICKET_FOUND", 404); } - await ticket.destroy(); + await ticket.destroy(); + + // TEST DEL + await deleteTicketsByIdCache(id) + // return ticket; }; diff --git a/backend/src/services/TicketServices/FindOrCreateTicketService.ts b/backend/src/services/TicketServices/FindOrCreateTicketService.ts index 2e691c9..94e7d9b 100644 --- a/backend/src/services/TicketServices/FindOrCreateTicketService.ts +++ b/backend/src/services/TicketServices/FindOrCreateTicketService.ts @@ -4,9 +4,7 @@ import BotIsOnQueue from "../../helpers/BotIsOnQueue"; import Contact from "../../models/Contact"; import Ticket from "../../models/Ticket"; import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService"; -import ShowTicketService from "./ShowTicketService"; - - +import ShowTicketService from "./ShowTicketService"; const FindOrCreateTicketService = async ( @@ -22,18 +20,18 @@ const FindOrCreateTicketService = async ( }, contactId: groupContact ? groupContact.id : contact.id } - }); + }); + + const { queues, greetingMessage } = await ShowWhatsAppService(whatsappId); + - const { queues, greetingMessage } = await ShowWhatsAppService(whatsappId); - - //Habilitar esse caso queira usar o bot // const botInfo = await BotIsOnQueue('botqueue') - const botInfo = {isOnQueue: false} - - + const botInfo = { isOnQueue: false } - if (ticket) { + + + if (ticket) { await ticket.update({ unreadMessages }); } @@ -47,7 +45,7 @@ const FindOrCreateTicketService = async ( - if (ticket) { + if (ticket) { await ticket.update({ status: "pending", @@ -57,8 +55,8 @@ const FindOrCreateTicketService = async ( } } - if (!ticket && !groupContact) { - + if (!ticket && !groupContact) { + ticket = await Ticket.findOne({ where: { updatedAt: { @@ -68,15 +66,15 @@ const FindOrCreateTicketService = async ( //[Op.between]: [+subMinutes(new Date(), 30), +new Date()] // Sub seconds - [Op.between]: [+subSeconds(new Date(), 0), +new Date()] + [Op.between]: [+subSeconds(new Date(), 0), +new Date()] }, contactId: contact.id }, order: [["updatedAt", "DESC"]] }); - if (ticket) { - + if (ticket) { + await ticket.update({ status: "pending", userId: null, @@ -85,14 +83,14 @@ const FindOrCreateTicketService = async ( } } - if (!ticket) { - + if (!ticket) { + let status = "pending" - if(queues.length > 1 && !botInfo.isOnQueue){ + if (queues.length > 1 && !botInfo.isOnQueue) { status = "queueChoice" - } - + } + ticket = await Ticket.create({ contactId: groupContact ? groupContact.id : contact.id, status: status, @@ -100,10 +98,18 @@ const FindOrCreateTicketService = async ( unreadMessages, whatsappId }); + + // TEST DEL + + // const { name } = await ShowContactService(contact.id); + // console.log('FIND OR CREATE TICKET SERVICE NAME: ', contact.name, ' STATUS: ', status) + + // } ticket = await ShowTicketService(ticket.id); + return ticket; }; diff --git a/backend/src/services/TicketServices/ListTicketServiceCache.ts b/backend/src/services/TicketServices/ListTicketServiceCache.ts index bc348ff..7e51ed2 100644 --- a/backend/src/services/TicketServices/ListTicketServiceCache.ts +++ b/backend/src/services/TicketServices/ListTicketServiceCache.ts @@ -11,10 +11,25 @@ import Contact from "../../models/Contact"; import Queue from "../../models/Queue"; const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }))) -const ListTicketsServiceCache = async (status?: string, date?: string): Promise => { + +interface Request { + status?: string; + date?: string; + userId?: string | number; + queueId?: string | number + } + +const ListTicketsServiceCache = async ({ + status, + date, + userId, + queueId +}:Request): Promise => { let where_clause = {} + console.log(' QUEUE ID: ', queueId) + if (date) { where_clause = { createdAt: { @@ -23,6 +38,19 @@ const ListTicketsServiceCache = async (status?: string, date?: string): Promise< } } } + else if(queueId){ + + + where_clause = { + queueId: queueId + } + } + else if(userId){ + + where_clause = { + userId: userId + } + } else { // where_clause = { // createdAt: { diff --git a/backend/src/services/TicketServices/ListTicketsService.ts b/backend/src/services/TicketServices/ListTicketsService.ts index a2b05b1..da326ab 100644 --- a/backend/src/services/TicketServices/ListTicketsService.ts +++ b/backend/src/services/TicketServices/ListTicketsService.ts @@ -8,11 +8,17 @@ import Message from "../../models/Message"; import Queue from "../../models/Queue"; import ShowUserService from "../UserServices/ShowUserService"; +const unflatten = require('flat').unflatten + import { splitDateTime } from "../../helpers/SplitDateTime"; const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }))) import ListTicketServiceCache from "./ListTicketServiceCache" +import { searchTicketCache, loadTicketsCache } from '../../helpers/TicketCache' + + + interface Request { searchParam?: string; @@ -32,6 +38,7 @@ interface Response { hasMore: boolean; } + const ListTicketsService = async ({ searchParam = "", pageNumber = "1", @@ -43,17 +50,48 @@ const ListTicketsService = async ({ withUnreadMessages, unlimited = 'false' }: Request): Promise => { - let whereCondition: Filterable["where"] = { - [Op.or]: [{ userId }, { status: "pending" }], - queueId: { [Op.or]: [queueIds, null] } - }; + + let whereCondition: Filterable["where"] = { [Op.or]: [{ userId }, { status: "pending" }], queueId: { [Op.or]: [queueIds, null] } }; + + if (searchParam && searchParam.trim().length > 0) { + + try { + + const offset = 40 * (+pageNumber - 1); + + console.log('QUERY TICKET SEARCH PARAM FROM CACHE: ', searchParam) + + let tickets: any = await searchTicketCache(searchParam, offset, 40); + + if (tickets) { + console.log('QUERY TICKET SEARCH PARAM FROM CACHE LENGTH...: ', tickets.length) + + tickets.map((t: any) => { + + t['contact.number'] = t['contact_number'] + delete t['contact_number'] + + return { ...['contact_number'] } + }) + + tickets = tickets.map((e: any) => unflatten(e)) + + return { tickets, count: tickets.length, hasMore: tickets.length > 0 ? true : false }; + } + + } catch (error) { + console.log('There was an error on search ListTicketservice.ts search cache: ', error) + } + + console.log('QUERY TICKETS FROM DATABASE...') + + } + + + + let includeCondition: Includeable[]; - - // test del - // const test = await ListTicketServiceCache() - // console.log('TEST:\n', test) - // includeCondition = [ @@ -77,9 +115,8 @@ const ListTicketsService = async ({ whereCondition = { ...whereCondition, status }; - // console.log('TEST unlimited: ', unlimited) - if (unlimited === 'true' && status !== 'pending') { + if (unlimited === 'true' && status !== 'pending') { whereCondition = { ...whereCondition, @@ -95,10 +132,6 @@ const ListTicketsService = async ({ if (searchParam) { const sanitizedSearchParam = searchParam.toLocaleLowerCase().trim(); - //othavio - - console.log('sanitizedSearchParam:'+ sanitizedSearchParam, ' | date: ',date) - // includeCondition = [ // ...includeCondition, // { @@ -119,7 +152,7 @@ const ListTicketsService = async ({ { "$contact.name$": where(fn("LOWER", col("contact.name")), "LIKE", `%${sanitizedSearchParam}%`) }, - + { "$contact.number$": { [Op.like]: `%${sanitizedSearchParam}%` } }, // { @@ -152,7 +185,8 @@ const ListTicketsService = async ({ const offset = limit * (+pageNumber - 1); - // console.log('whereCondition: ', JSON.stringify(whereCondition)) + + console.log('ENTROU NO LIST TICKET SERVICE') const { count, rows: tickets } = await Ticket.findAndCountAll({ where: whereCondition, @@ -165,7 +199,7 @@ const ListTicketsService = async ({ const hasMore = count > offset + tickets.length; - + return { tickets, diff --git a/backend/src/services/TicketServices/UpdateTicketService.ts b/backend/src/services/TicketServices/UpdateTicketService.ts index 1b790c8..db89646 100644 --- a/backend/src/services/TicketServices/UpdateTicketService.ts +++ b/backend/src/services/TicketServices/UpdateTicketService.ts @@ -6,6 +6,11 @@ import SendWhatsAppMessage from "../WbotServices/SendWhatsAppMessage"; import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService"; import ShowTicketService from "./ShowTicketService"; +import { createOrUpdateTicketCache } from '../../helpers/TicketCache' +var flatten = require('flat') + + + interface TicketData { status?: string; userId?: number; @@ -38,8 +43,8 @@ const UpdateTicketService = async ({ if (oldStatus === "closed") { await CheckContactOpenTickets(ticket.contact.id); - } - + } + await ticket.update({ status, queueId, @@ -47,10 +52,27 @@ const UpdateTicketService = async ({ statusChatEnd }); - - await ticket.reload(); + // TEST DEL + try { + + // const { name, number } = await ShowContactService(ticket.contactId) + + let jsonString = JSON.stringify(ticket); //convert to string to remove the sequelize specific meta data + let ticket_obj = JSON.parse(jsonString); //to make plain json + delete ticket_obj['contact']['extraInfo'] + delete ticket_obj['user'] + + ticket_obj = flatten(ticket_obj) + + await createOrUpdateTicketCache(`ticket:${ticket.id}`, ticket_obj) + + } catch (error) { + console.log('There was an error on UpdateTicketService.ts on createTicketCache: ', error) + } + // + let io = getIO(); if (ticket.status !== oldStatus || ticket.user?.id !== oldUserId) { @@ -69,7 +91,7 @@ const UpdateTicketService = async ({ ticket }); - + io.emit("ticketStatus", { action: "update", ticketStatus: { ticketId: ticket.id, status: ticket.status } diff --git a/backend/src/services/UserServices/CreateOrUpdateOnlineUserService.ts b/backend/src/services/UserServices/CreateOrUpdateOnlineUserService.ts index 3075da3..29f03aa 100644 --- a/backend/src/services/UserServices/CreateOrUpdateOnlineUserService.ts +++ b/backend/src/services/UserServices/CreateOrUpdateOnlineUserService.ts @@ -33,16 +33,16 @@ const CreateOrUpdateUserOnlineTime = async ({ userId, status, }: Request): Promise => { - + const io = getIO(); - let userOnlineTime:any = null; + let userOnlineTime: any = null; const user = await User.findOne({ where: { id: userId } }); if (!user) { - console.log(' yyyyyyyyyyyyyyyyyyyyyyyyyy não tem mais esse usuario id: ', userId) + return userOnlineTime } @@ -68,27 +68,21 @@ const CreateOrUpdateUserOnlineTime = async ({ let oldStatus = userOnlineTime.status - console.log('>>>>>>>>> oldStatus: ', oldStatus, ' | new status', status) + if (oldStatus == 'online' && status === 'offline') { //updatedAt let newtTime = intervalToDuration({ start: userOnlineTime.updatedAt, end: new Date() }) - console.log('TESTANDO INTERVAL DURATION: ', newtTime) - console.log('hours: ', newtTime.hours, ' | minutes: ', newtTime.minutes, ' | seconds: ', newtTime.seconds) + + let onlineTime = new Date() onlineTime.setUTCHours(userOnlineTime.onlineTime.getHours()) onlineTime.setUTCMinutes(userOnlineTime.onlineTime.getMinutes()) - onlineTime.setUTCSeconds(userOnlineTime.onlineTime.getSeconds()) + onlineTime.setUTCSeconds(userOnlineTime.onlineTime.getSeconds()) - console.log('userOnlineTime.onlineTime: ', userOnlineTime.onlineTime) - console.log('userOnlineTime.onlineTime.getHours(): ', userOnlineTime.onlineTime.getHours()) - console.log('userOnlineTime.onlineTime.getMinutes(): ', userOnlineTime.onlineTime.getMinutes()) - console.log('userOnlineTime.onlineTime.getSeconds(): ', userOnlineTime.onlineTime.getSeconds()) - - console.log('online time 3: ', onlineTime) if (newtTime.hours && +newtTime.hours > 0) { @@ -101,11 +95,11 @@ const CreateOrUpdateUserOnlineTime = async ({ onlineTime = addSeconds(onlineTime, newtTime.seconds) } - console.log('online time 4: ', onlineTime) + const isoDate = new Date(onlineTime); const mySQLDateString = isoDate.toJSON().slice(0, 19).replace('T', ' '); - console.log('mySQLDateString: ', mySQLDateString) + await userOnlineTime.update({ status, onlineTime: mySQLDateString }) @@ -114,10 +108,10 @@ const CreateOrUpdateUserOnlineTime = async ({ const updatedAtString = formatDateTimeString(userOnlineTime.updatedAt) const createdAtString = formatDateTimeString(userOnlineTime.createdAt) - console.log('CreatedAt string: ', createdAtString) - console.log('UpdatedAt string: ', updatedAtString) + + // - + io.emit("onlineStatus", { action: "update", @@ -133,7 +127,7 @@ const CreateOrUpdateUserOnlineTime = async ({ } else if (oldStatus == 'offline' && status === 'online') { await userOnlineTime.update({ status }) - + io.emit("onlineStatus", { action: "update", userOnlineTime: { diff --git a/backend/src/services/UserServices/ShowUserServiceReport.ts b/backend/src/services/UserServices/ShowUserServiceReport.ts index f9de30d..33c94e4 100644 --- a/backend/src/services/UserServices/ShowUserServiceReport.ts +++ b/backend/src/services/UserServices/ShowUserServiceReport.ts @@ -104,11 +104,7 @@ const ShowUserServiceReport = async ({ }); } - - - // console.log('>>>>>>>>>>>>>> objQuery: ', objQuery) - - + if (!objQuery) { throw new AppError("ERR_NO_OBJ_QUERY_FOUND", 404); diff --git a/backend/src/services/WbotServices/ImportContactsService.ts b/backend/src/services/WbotServices/ImportContactsService.ts index ee6fd1f..7b0e60d 100644 --- a/backend/src/services/WbotServices/ImportContactsService.ts +++ b/backend/src/services/WbotServices/ImportContactsService.ts @@ -3,6 +3,8 @@ import { getWbot } from "../../libs/wbot"; import Contact from "../../models/Contact"; import { logger } from "../../utils/logger"; +import { createOrUpdateContactCache } from '../../helpers/ContactsCache' + const ImportContactsService = async (): Promise => { const defaultWhatsapp = await GetDefaultWhatsApp(); @@ -32,7 +34,16 @@ const ImportContactsService = async (): Promise => { if (numberExists) return null; - return Contact.create({ number, name }); + let contact = await Contact.create({ number, name }); + + // await contact.reload() + + // TEST DEL + await createOrUpdateContactCache(`contact:${contact.id}`, {id:contact.id, name, number, profilePicUrl: contact.profilePicUrl, isGroup: contact.isGroup, extraInfo: '', email:'' }) + // + + // return Contact.create({ number, name }); + return contact }) ); } diff --git a/backend/src/services/WbotServices/SendWhatsAppMedia.ts b/backend/src/services/WbotServices/SendWhatsAppMedia.ts index bb64bd3..b090c1c 100644 --- a/backend/src/services/WbotServices/SendWhatsAppMedia.ts +++ b/backend/src/services/WbotServices/SendWhatsAppMedia.ts @@ -4,6 +4,9 @@ import AppError from "../../errors/AppError"; import GetTicketWbot from "../../helpers/GetTicketWbot"; import Ticket from "../../models/Ticket"; +import { updateTicketCacheByTicketId } from '../../helpers/TicketCache' +import { date } from "faker"; + interface Request { media: Express.Multer.File; ticket: Ticket; @@ -22,6 +25,10 @@ const SendWhatsAppMedia = async ({ await ticket.update({ lastMessage: media.filename }); + // TEST DEL + await updateTicketCacheByTicketId(ticket.id, { lastMessage: media.filename, updatedAt: new Date(ticket.updatedAt).toISOString() }) + // + fs.unlinkSync(media.path); return sentMessage; diff --git a/backend/src/services/WbotServices/SendWhatsAppMessage.ts b/backend/src/services/WbotServices/SendWhatsAppMessage.ts index 2a88f2c..7ad1f50 100644 --- a/backend/src/services/WbotServices/SendWhatsAppMessage.ts +++ b/backend/src/services/WbotServices/SendWhatsAppMessage.ts @@ -11,6 +11,7 @@ import wbotByUserQueue from '../../helpers/GetWbotByUserQueue' import { WhatsIndex } from "../../helpers/LoadBalanceWhatsSameQueue"; +import { updateTicketCacheByTicketId } from '../../helpers/TicketCache' interface Request { body: string; @@ -61,6 +62,12 @@ const SendWhatsAppMessage = async ({ try { const sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, body, { quotedMessageId: quotedMsgSerializedId, linkPreview: false }); await ticket.update({ lastMessage: body }); + + + // TEST DEL + await updateTicketCacheByTicketId(ticket.id, { lastMessage: body, updatedAt: new Date(ticket.updatedAt).toISOString() }) + // + return sentMessage; } catch (err) { throw new AppError("ERR_SENDING_WAPP_MSG"); diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index e48766f..18fe020 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -10,6 +10,8 @@ import path from 'path'; import { format } from "date-fns"; import ptBR from 'date-fns/locale/pt-BR'; + + import { Contact as WbotContact, Message as WbotMessage, @@ -49,7 +51,9 @@ import final_message from "./ura_final_message"; import SendWhatsAppMessage from "./SendWhatsAppMessage"; import Whatsapp from "../../models/Whatsapp"; import { splitDateTime } from "../../helpers/SplitDateTime"; -// +// + +import { updateTicketCacheByTicketId } from '../../helpers/TicketCache' @@ -159,6 +163,10 @@ const verifyMessage = async ( await ticket.update({ lastMessage: msg.body }); + // TEST DEL + // await updateTicketCacheByTicketId(ticket.id, { lastMessage: msg.body, updatedAt: new Date(ticket.updatedAt).toISOString() }) + // + await CreateMessageService({ messageData }); }; @@ -227,7 +235,7 @@ const verifyQueue = async ( ticketData: { queueId: choosenQueue.id }, ticketId: ticket.id }); - + let botOptions = '' @@ -255,7 +263,8 @@ const verifyQueue = async ( const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); await verifyMessage(sentMessage, ticket, contact); - } else { + } + else { //test del transfere o atendimento se entrar na ura infinita @@ -288,8 +297,7 @@ const verifyQueue = async ( } - //console.log('TICKET MESSAGE ON QUEUE CHOICE: ', ticket_message) - // + } }; @@ -378,7 +386,7 @@ const handleMessage = async ( msgContact = await msg.getContact(); - // console.log('-----msgContact TESTE MSG2: ', msgContact, ' | msg: ', msg) + // console.log(`\n <<<<<<<<<< RECEIVING MESSAGE: Parcial msg and msgContact info: @@ -412,7 +420,8 @@ const handleMessage = async ( const unreadMessages = msg.fromMe ? 0 : chat.unreadCount; - const contact = await verifyContact(msgContact); + const contact = await verifyContact(msgContact); + if (unreadMessages === 0 && whatsapp.farewellMessage && whatsapp.farewellMessage === msg.body) return; @@ -422,12 +431,15 @@ const handleMessage = async ( wbot.id!, unreadMessages, groupContact - ); + ); + + // + // await updateTicketCacheByTicketId(ticket.id, {'contact.profilePicUrl': ticket.contact.profilePicUrl}) // Para responder para o cliente pelo mesmo whatsapp que ele enviou a mensagen if (wbot.id != ticket.whatsappId) { - console.log('>>> entrou wbot.id: ', wbot.id, ' | ', ticket.whatsappId) + await ticket.update({ whatsappId: wbot.id }); } @@ -495,7 +507,7 @@ const handleMessage = async ( opt_user_attendant = data_ura[indexAttendant].id } - // console.log('¨¨¨¨¨¨¨¨¨¨¨¨¨¨ indexAttendant: ',indexAttendant, ' | opt_user_attendant: ', opt_user_attendant) + // let ticket_message = await ShowTicketMessage(ticket.id, true, ura_length, `^[0-${ura_length}}]$`); @@ -529,9 +541,9 @@ const handleMessage = async ( - // console.log('----------------- ticket_message: ', ticket_message) + // - //console.log('¨¨¨¨¨¨¨¨¨¨¨¨¨¨ MSG.BODY: ', msg.body , ' | opt_user_attendant: ',opt_user_attendant, ' | lastOption: ', lastOption) + // // È numero if (!Number.isNaN(Number(msg.body.trim())) && (+msg.body >= 0 && +msg.body <= data_ura.length)) { @@ -546,7 +558,7 @@ const handleMessage = async ( - console.log('TICKET MESSAGE: ', ticket_message) + // test del let next = true @@ -780,7 +792,7 @@ const handleMessage = async ( if (whatsapp.status == 'CONNECTED') { - console.log('wbotMessageListener.ts - ENTROU NO RESTORE...') + let timestamp = Math.floor(Date.now() / 1000) @@ -789,7 +801,7 @@ const handleMessage = async ( await restartWhatsSession(whatsapp) - console.log('...PASSOU O RESTORE - wbotMessageListener.ts ') + } } diff --git a/frontend/src/App.js b/frontend/src/App.js index e37774e..854091e 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -5,6 +5,8 @@ import "react-toastify/dist/ReactToastify.css"; import { createTheme, ThemeProvider } from "@material-ui/core/styles"; import { ptBR } from "@material-ui/core/locale"; +import { TabTicketProvider } from "../src/context/TabTicketHeaderOption/TabTicketHeaderOption"; + const App = () => { const [locale, setLocale] = useState(); @@ -18,7 +20,7 @@ const App = () => { "&::-webkit-scrollbar-thumb": { boxShadow: "inset 0 0 6px rgba(0, 0, 0, 0.3)", - backgroundColor: "#e8e8e8", + backgroundColor: "#e8e8e8", }, }, palette: { @@ -41,7 +43,13 @@ const App = () => { return ( - + + {/*TabTicketProvider Context to manipulate the entire state of selected option from user click on tickets options header */} + + + + + ); }; diff --git a/frontend/src/components/ChatEnd/ModalChatEnd/index.js b/frontend/src/components/ChatEnd/ModalChatEnd/index.js index 7f95d6a..e64916d 100644 --- a/frontend/src/components/ChatEnd/ModalChatEnd/index.js +++ b/frontend/src/components/ChatEnd/ModalChatEnd/index.js @@ -165,7 +165,7 @@ const Modal = (props) => { // Get from child 2 const datePickerValue = (data) => { - console.log('datePickerValue: ', (data)); + setDatePicker(data) @@ -173,7 +173,7 @@ const Modal = (props) => { // Get from child 3 const timerPickerValue = (data) => { - console.log('timerPickerValue: ', (data)); + setTimerPicker(data) @@ -207,7 +207,7 @@ const Modal = (props) => { if (statusChatEndId === '2' || statusChatEndId === '3') { - console.log('Entrou! textArea1: ', textArea1) + if (startDate.trim().length === 0) { @@ -255,18 +255,18 @@ const Modal = (props) => { let sendMessageDayBefore = currenciesTimeBefore.filter(i => i.label.indexOf('24 HORAS ANTES DO HORÁRIO DO AGENDAMENTO') >= 0); if (sendMessageDayBefore.length > 0 && timeBefore === formatedTimeHour(timerPicker)) { - console.log('ENVIAR MENSAGEM UM DIA ANTES!') - console.log('MENSAGEM SERÁ ENVIA NO DIA: ', dateCurrentFormated(new Date(subDays(new Date(startDate + ' ' + formatedTimeHour(new Date(`${startDate} ${timerPicker.getHours()}:${timerPicker.getMinutes()}:00`))), 1)))) + + dateSendMessage = dateCurrentFormated(new Date(subDays(new Date(startDate + ' ' + formatedTimeHour(new Date(`${startDate} ${timerPicker.getHours()}:${timerPicker.getMinutes()}:00`))), 1))) } - console.log('AGENDAMENTO ENVIO MENSAGEM1: ', `${dateSendMessage} ${timeBefore}:00`) + } else if (statusChatEndId === '2') { - console.log('AGENDAMENTO ENVIO MENSAGEM2: ', startDate + ' ' + formatedTimeHour(new Date(`${startDate} ${timerPicker.getHours()}:${timerPicker.getMinutes()}:00`))) + } @@ -297,21 +297,21 @@ const Modal = (props) => { let hours = [] let hour = 1 - console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>> startDate: ', startDate) - console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>> dateCurrentFormated: ', dateCurrentFormated()) - console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>> startDate: ', typeof (startDate)) - console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>> startDate: ', (startDate)) + + + + if (typeof (startDate) === 'string' && startDate.trim().length > 0 && startDate === dateCurrentFormated()) { - console.log('HOJE++++') + while (subHours(timer, hour).getHours() >= 6 && subHours(timer, hour).getHours() >= new Date().getHours() && subHours(timer, hour).getHours() <= 20) { - console.log('******** TIMER: ', formatedTimeHour(subHours(timer, hour))) + hours.push({ value: formatedTimeHour(subHours(timer, hour)), label: `${hour} HORA ANTES DO HORÁRIO DO AGENDAMENTO` }) @@ -319,7 +319,7 @@ const Modal = (props) => { } if (hours.length > 1) { - console.log('entrou----------------------: ', hours.length) + hours.pop() setCurrency(hours[0].value) } @@ -332,7 +332,7 @@ const Modal = (props) => { while (subHours(timer, hour).getHours() >= 6 && subHours(timer, hour).getHours() <= 20) { - console.log('******** another day TIMER: ', formatedTimeHour(subHours(timer, hour))) + hours.push( { @@ -344,7 +344,7 @@ const Modal = (props) => { } if (hours.length > 0) { - console.log('entrou----------------------: ', hours.length) + setCurrency(hours[0].value) } else { @@ -358,18 +358,18 @@ const Modal = (props) => { hours.push({ value: formatedTimeHour(timerPicker), label: `24 HORAS ANTES DO HORÁRIO DO AGENDAMENTO` }) - console.log('#subDays: ', dateCurrentFormated(new Date(subDays(new Date(startDate + ' ' + formatedTimeHour(new Date(`${startDate} ${timerPicker.getHours()}:${timerPicker.getMinutes()}:00`))), 1)))) + } - console.log('hourshourshourshourshourshourshourshourshourshourshourshours ', hours) + return { time: hours, hour: hour } } - console.log('===================================== addDays: ', addDays(new Date(), 1)) + @@ -394,7 +394,7 @@ const Modal = (props) => { // Get from child 1 const textFieldSelect = (data) => { - console.log('textFieldSelect: ', data); + setStatusChatEnd(data) } @@ -408,7 +408,7 @@ const Modal = (props) => { const handleCheckBoxChange = (event) => { - //console.log('event.target.checked: ', event.target.checked) + setChecked(event.target.checked); }; @@ -416,11 +416,11 @@ const Modal = (props) => { const handleChangeHourBefore = (event) => { - console.log('textFihandleChangeHourBefore: ', event.target.value); + // var matchedTime = currenciesTimeBefore.filter(i => i.label.indexOf('24 HORAS ANTES DO HORÁRIO DO AGENDAMENTO') >= 0); - // console.log('textFihandleChangeHourBefore matchedTime: ',matchedTime); + setCurrency(event.target.value); diff --git a/frontend/src/components/DashboardUser/TableUser.jsx b/frontend/src/components/DashboardUser/TableUser.jsx index 8c663da..f91788e 100644 --- a/frontend/src/components/DashboardUser/TableUser.jsx +++ b/frontend/src/components/DashboardUser/TableUser.jsx @@ -17,8 +17,8 @@ import InputLabel from "@mui/material/InputLabel"; import MenuItem from "@mui/material/MenuItem"; import FormControl from "@mui/material/FormControl"; -import Tooltip from "@mui/material/Tooltip"; -import Zoom from "@mui/material/Zoom"; +// import Tooltip from "@mui/material/Tooltip"; +// import Zoom from "@mui/material/Zoom"; import CancelIcon from "@material-ui/icons/Cancel"; import CheckCircleIcon from "@material-ui/icons/CheckCircle"; diff --git a/frontend/src/components/MessageInput/index.js b/frontend/src/components/MessageInput/index.js index cd0b6f5..96e63c3 100644 --- a/frontend/src/components/MessageInput/index.js +++ b/frontend/src/components/MessageInput/index.js @@ -37,6 +37,10 @@ import { AuthContext } from "../../context/Auth/AuthContext"; import { useLocalStorage } from "../../hooks/useLocalStorage"; import toastError from "../../errors/toastError"; +// import TicketsManager from "../../components/TicketsManager/"; + +import { TabTicketContext } from "../../context/TabTicketHeaderOption/TabTicketHeaderOption"; + const Mp3Recorder = new MicRecorder({ bitRate: 128 }); const useStyles = makeStyles((theme) => ({ @@ -202,6 +206,9 @@ const useStyles = makeStyles((theme) => ({ })); const MessageInput = ({ ticketStatus }) => { + + const { tabOption, setTabOption } = useContext(TabTicketContext); + const classes = useStyles(); const { ticketId } = useParams(); @@ -214,8 +221,7 @@ const MessageInput = ({ ticketStatus }) => { const [typeBar, setTypeBar] = useState(false); const inputRef = useRef(); const [anchorEl, setAnchorEl] = useState(null); - const { setReplyingMessage, replyingMessage } = - useContext(ReplyMessageContext); + const { setReplyingMessage, replyingMessage } = useContext(ReplyMessageContext); const { user } = useContext(AuthContext); const [signMessage, setSignMessage] = useLocalStorage("signOption", true); @@ -268,6 +274,12 @@ const MessageInput = ({ ticketStatus }) => { setLoading(true); e.preventDefault(); + + + if (tabOption === 'search') { + setTabOption('open') + } + const formData = new FormData(); formData.append("fromMe", true); medias.forEach((media) => { @@ -288,6 +300,12 @@ const MessageInput = ({ ticketStatus }) => { const handleSendMessage = async () => { if (inputMessage.trim() === "") return; setLoading(true); + + + + if (tabOption === 'search') { + setTabOption('open') + } const message = { read: 1, @@ -310,7 +328,7 @@ const MessageInput = ({ ticketStatus }) => { setReplyingMessage(null); }; - const handleStartRecording = async () => { + const handleStartRecording = async () => { setLoading(true); try { @@ -346,6 +364,13 @@ const MessageInput = ({ ticketStatus }) => { const handleUploadAudio = async () => { setLoading(true); + + + + if (tabOption === 'search') { + setTabOption('open') + } + try { const [, blob] = await Mp3Recorder.stop().getMp3(); if (blob.size < 10000) { diff --git a/frontend/src/components/MessagesList/index.js b/frontend/src/components/MessagesList/index.js index 3f7fe46..94b6fab 100644 --- a/frontend/src/components/MessagesList/index.js +++ b/frontend/src/components/MessagesList/index.js @@ -283,7 +283,7 @@ const reducer = (state, action) => { state[messageIndex] = newMessage; } else { state.push(newMessage); - // console.log(' TESTANDO NOVA MENSAGEM: ', newMessage) + } return [...state]; @@ -333,7 +333,7 @@ const MessagesList = ({ ticketId, isGroup }) => { try { const { data } = await api.get("/messages/" + ticketId, { params: { pageNumber }, - }); + }); if (currentTicketId.current === ticketId) { dispatch({ type: "LOAD_MESSAGES", payload: data.messages }); @@ -362,17 +362,15 @@ const MessagesList = ({ ticketId, isGroup }) => { socket.on("connect", () => socket.emit("joinChatBox", ticketId)); socket.on("appMessage", (data) => { - + if (data.action === "create") { - dispatch({ type: "ADD_MESSAGE", payload: data.message }); + dispatch({ type: "ADD_MESSAGE", payload: data.message }); scrollToBottom(); } if (data.action === "update") { - console.log('2 THIS IS THE DATA: ', data) - dispatch({ type: "UPDATE_MESSAGE", payload: data.message }); } }); @@ -423,7 +421,7 @@ const MessagesList = ({ ticketId, isGroup }) => { return ; } if (message.mediaType === "audio") { - + return (