Implementação de solução para consultas dos tickets e dos contatos usando Redis como banco de dados em memória. Ajustes no frontend para corrigir bugs de datas exibidas nas mensagens
parent
603e5fa2dd
commit
bde6058455
Binary file not shown.
|
@ -26,8 +26,10 @@
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-async-errors": "^3.1.1",
|
"express-async-errors": "^3.1.1",
|
||||||
"fast-folder-size": "^1.7.0",
|
"fast-folder-size": "^1.7.0",
|
||||||
|
"flat": "^5.0.2",
|
||||||
"fs-extra": "^10.1.0",
|
"fs-extra": "^10.1.0",
|
||||||
"http-graceful-shutdown": "^2.3.2",
|
"http-graceful-shutdown": "^2.3.2",
|
||||||
|
"ioredis": "^5.2.3",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"multer": "^1.4.2",
|
"multer": "^1.4.2",
|
||||||
"mysql2": "^2.2.5",
|
"mysql2": "^2.2.5",
|
||||||
|
|
|
@ -13,6 +13,12 @@ import CheckIsValidContact from "../services/WbotServices/CheckIsValidContact";
|
||||||
import GetProfilePicUrl from "../services/WbotServices/GetProfilePicUrl";
|
import GetProfilePicUrl from "../services/WbotServices/GetProfilePicUrl";
|
||||||
import AppError from "../errors/AppError";
|
import AppError from "../errors/AppError";
|
||||||
|
|
||||||
|
|
||||||
|
import { searchContactCache } from '../helpers/ContactsCache'
|
||||||
|
import { off } from "process";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type IndexQuery = {
|
type IndexQuery = {
|
||||||
searchParam: string;
|
searchParam: string;
|
||||||
pageNumber: string;
|
pageNumber: string;
|
||||||
|
@ -30,12 +36,34 @@ interface ContactData {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const index = async (req: Request, res: Response): Promise<Response> => {
|
export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||||
const { searchParam, pageNumber } = req.query as IndexQuery;
|
let { searchParam, pageNumber } = req.query as IndexQuery;
|
||||||
|
|
||||||
const { contacts, count, hasMore } = await ListContactsService({
|
// TEST DEL
|
||||||
searchParam,
|
if (searchParam && searchParam.trim().length > 0) {
|
||||||
pageNumber
|
|
||||||
});
|
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 });
|
return res.json({ contacts, count, hasMore });
|
||||||
};
|
};
|
||||||
|
@ -58,8 +86,8 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
}
|
}
|
||||||
|
|
||||||
await CheckIsValidContact(newContact.number);
|
await CheckIsValidContact(newContact.number);
|
||||||
const validNumber : any = await CheckContactNumber(newContact.number)
|
const validNumber: any = await CheckContactNumber(newContact.number)
|
||||||
|
|
||||||
const profilePicUrl = await GetProfilePicUrl(validNumber);
|
const profilePicUrl = await GetProfilePicUrl(validNumber);
|
||||||
|
|
||||||
let name = newContact.name
|
let name = newContact.name
|
||||||
|
|
|
@ -8,7 +8,7 @@ import CreateSchedulingNotifyService from "../services/SchedulingNotifyServices
|
||||||
// const test = await ListSchedulingNotifyContactService('5517988310949','2022-03-18','2022-03-19');
|
// 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('','2022-03-18','2022-03-19');
|
||||||
// const test = await ListSchedulingNotifyContactService('5517988310949');
|
// 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;
|
const scheduleData = req.body;
|
||||||
|
|
||||||
console.log(' +++++++++++ scheduleData: ', scheduleData)
|
|
||||||
|
|
||||||
const schedulingNotifyCreate = await CreateSchedulingNotifyService(
|
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<Response> => {
|
export const remove = async ( req: Request, res: Response ): Promise<Response> => {
|
||||||
|
|
||||||
console.log('EEEEEEEEEEEEEEEEEEEEEEEEEEE')
|
|
||||||
|
|
||||||
const { scheduleId } = req.params;
|
const { scheduleId } = req.params;
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,9 @@ import ptBR from 'date-fns/locale/pt-BR';
|
||||||
import { splitDateTime } from "../helpers/SplitDateTime";
|
import { splitDateTime } from "../helpers/SplitDateTime";
|
||||||
import format from 'date-fns/format';
|
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<Response> => {
|
||||||
|
|
||||||
export const store = async (req: Request, res: Response): Promise<Response> => {
|
export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
const { contactId, status, userId }: TicketData = req.body;
|
const { contactId, status, userId }: TicketData = req.body;
|
||||||
|
|
||||||
// naty
|
|
||||||
// console.log(
|
|
||||||
// `contactId: ${contactId} \n| status: ${status} \n| userId: ${userId}`
|
|
||||||
// )
|
|
||||||
|
|
||||||
|
|
||||||
// test del
|
// test del
|
||||||
let ticket = await Ticket.findOne({ where: { contactId, status: 'queueChoice' } });
|
let ticket = await Ticket.findOne({ where: { contactId, status: 'queueChoice' } });
|
||||||
|
|
||||||
if (ticket) {
|
if (ticket) {
|
||||||
await UpdateTicketService({ ticketData: { status: 'open', userId: userId, }, ticketId: ticket.id });
|
await UpdateTicketService({ ticketData: { status: 'open', userId: userId, }, ticketId: ticket.id });
|
||||||
console.log('TICKET QUEUE CHOICE !!!!!!!')
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ticket = await CreateTicketService({ contactId, status, userId });
|
ticket = await CreateTicketService({ contactId, status, userId });
|
||||||
|
@ -145,7 +142,7 @@ export const show = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
|
||||||
export const count = async (req: Request, res: Response): Promise<Response> => {
|
export const count = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
|
||||||
type indexQ = { status: string; date?: string; };
|
// type indexQ = { status: string; date?: string; };
|
||||||
const { status, date } = req.query as IndexQuery
|
const { status, date } = req.query as IndexQuery
|
||||||
|
|
||||||
const ticketCount = await CountTicketService(status, date);
|
const ticketCount = await CountTicketService(status, date);
|
||||||
|
@ -153,10 +150,7 @@ export const count = async (req: Request, res: Response): Promise<Response> => {
|
||||||
return res.status(200).json(ticketCount);
|
return res.status(200).json(ticketCount);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const update = async (req: Request, res: Response): Promise<Response> => {
|
export const update = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
@ -184,7 +178,7 @@ export const update = async (req: Request, res: Response): Promise<Response> =>
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
//console.log('------- scheduleData.farewellMessage: ', scheduleData.farewellMessage)
|
//
|
||||||
|
|
||||||
if (scheduleData.farewellMessage) {
|
if (scheduleData.farewellMessage) {
|
||||||
const whatsapp = await ShowWhatsAppService(ticket.whatsappId);
|
const whatsapp = await ShowWhatsAppService(ticket.whatsappId);
|
||||||
|
@ -195,15 +189,11 @@ export const update = async (req: Request, res: Response): Promise<Response> =>
|
||||||
await SendWhatsAppMessage({ body: farewellMessage, ticket });
|
await SendWhatsAppMessage({ body: farewellMessage, ticket });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
// lembrete // agendamento
|
// lembrete // agendamento
|
||||||
if (scheduleData.statusChatEndId === '2' || scheduleData.statusChatEndId === '3') {
|
if (scheduleData.statusChatEndId === '2' || scheduleData.statusChatEndId === '3') {
|
||||||
|
|
||||||
console.log('*** schedulingDate: ', scheduleData.schedulingDate)
|
|
||||||
console.log('*** schedulingTime: ', scheduleData.schedulingTime)
|
|
||||||
|
|
||||||
if (isScheduling(scheduleData.schedulingDate, scheduleData.schedulingTime)) {
|
if (isScheduling(scheduleData.schedulingDate, scheduleData.schedulingTime)) {
|
||||||
console.log('*** É AGENDAMENTO!')
|
console.log('*** É AGENDAMENTO!')
|
||||||
|
@ -255,9 +245,7 @@ export const update = async (req: Request, res: Response): Promise<Response> =>
|
||||||
|
|
||||||
const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR })))
|
const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR })))
|
||||||
|
|
||||||
if (userOldInfo.userId) {
|
if (userOldInfo.userId) {
|
||||||
|
|
||||||
// console.log('FECHOU...')
|
|
||||||
|
|
||||||
TicketEmiterSumOpenClosedByUser(userOldInfo.userId.toString(), dateToday.fullDate, dateToday.fullDate)
|
TicketEmiterSumOpenClosedByUser(userOldInfo.userId.toString(), dateToday.fullDate, dateToday.fullDate)
|
||||||
|
|
||||||
|
|
|
@ -112,11 +112,7 @@ export const show = async (req: Request, res: Response): Promise<Response> => {
|
||||||
export const logoutUser = async (req: Request, res: Response): Promise<Response> => {
|
export const logoutUser = async (req: Request, res: Response): Promise<Response> => {
|
||||||
const { userId } = req.params;
|
const { userId } = req.params;
|
||||||
|
|
||||||
//const user = await ShowUserService(userId);
|
|
||||||
|
|
||||||
console.log('userId: ', userId)
|
|
||||||
|
|
||||||
//test del
|
|
||||||
await stopWhoIsOnlineMonitor()
|
await stopWhoIsOnlineMonitor()
|
||||||
|
|
||||||
let onlineTime = {
|
let onlineTime = {
|
||||||
|
|
|
@ -123,9 +123,7 @@ export const remove = async (
|
||||||
|
|
||||||
removeDir(path.join(process.cwd(), '.wwebjs_auth', `session-bd_${whatsappId}`))
|
removeDir(path.join(process.cwd(), '.wwebjs_auth', `session-bd_${whatsappId}`))
|
||||||
|
|
||||||
removeWbot(+whatsappId);
|
removeWbot(+whatsappId);
|
||||||
|
|
||||||
console.log('Deleteou o whatsapp service com id = ', whatsappId)
|
|
||||||
|
|
||||||
const io = getIO();
|
const io = getIO();
|
||||||
io.emit("whatsapp", {
|
io.emit("whatsapp", {
|
||||||
|
|
|
@ -56,14 +56,7 @@ const remove = async (req: Request, res: Response): Promise<Response> => {
|
||||||
const { whatsappId } = req.params;
|
const { whatsappId } = req.params;
|
||||||
const whatsapp = await ShowWhatsAppService(whatsappId);
|
const whatsapp = await ShowWhatsAppService(whatsappId);
|
||||||
|
|
||||||
const wbot = getWbot(whatsapp.id);
|
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}`))
|
|
||||||
|
|
||||||
await wbot.logout();
|
await wbot.logout();
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -10,9 +10,7 @@ export const WhatsIndex = (whatsapps: Object[]) => {
|
||||||
|
|
||||||
if (WhatsQueueIndex.getIndex() >= whatsapps.length) {
|
if (WhatsQueueIndex.getIndex() >= whatsapps.length) {
|
||||||
WhatsQueueIndex.setIndex(0)
|
WhatsQueueIndex.setIndex(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log('WhatsQueueIndex.getIndex(): ', WhatsQueueIndex.getIndex())
|
|
||||||
|
|
||||||
index = +WhatsQueueIndex.getIndex()
|
index = +WhatsQueueIndex.getIndex()
|
||||||
|
|
||||||
|
|
|
@ -90,21 +90,20 @@ const monitor = async () => {
|
||||||
|
|
||||||
whatsapps.forEach(async whats => {
|
whatsapps.forEach(async whats => {
|
||||||
|
|
||||||
// console.log('whats id: ', whats.id)
|
|
||||||
|
|
||||||
const sourcePath = path.join(__dirname, `../../.wwebjs_auth/`, `session-bd_${whats.id}`)
|
const sourcePath = path.join(__dirname, `../../.wwebjs_auth/`, `session-bd_${whats.id}`)
|
||||||
|
|
||||||
if (fs.existsSync(sourcePath)) {
|
if (fs.existsSync(sourcePath)) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// console.log('dir path exist!')
|
|
||||||
const fastFolderSizeAsync = promisify(fastFolderSize)
|
const fastFolderSizeAsync = promisify(fastFolderSize)
|
||||||
|
|
||||||
let size = await fastFolderSizeAsync(sourcePath)
|
let size = await fastFolderSizeAsync(sourcePath)
|
||||||
|
|
||||||
size = convertBytes(size)
|
size = convertBytes(size)
|
||||||
|
|
||||||
// console.log(size)
|
|
||||||
|
|
||||||
// SESSION MONITORING
|
// SESSION MONITORING
|
||||||
const io = getIO();
|
const io = getIO();
|
||||||
|
|
|
@ -50,17 +50,15 @@ const SetTicketMessagesAsRead = async (ticket: Ticket): Promise<void> => {
|
||||||
|
|
||||||
const whatsapp = await ShowWhatsAppService(ticket.whatsappId);
|
const whatsapp = await ShowWhatsAppService(ticket.whatsappId);
|
||||||
|
|
||||||
if (whatsapp && whatsapp.status == 'CONNECTED') {
|
if (whatsapp && whatsapp.status == 'CONNECTED') {
|
||||||
|
|
||||||
console.log('SetTicketMessagesAsRead.ts - ENTROU NO RESTORE...')
|
|
||||||
|
|
||||||
let timestamp = Math.floor(Date.now() / 1000)
|
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)=>{});
|
fs.writeFile(`${sourcePath}/${timestamp}_SetTicketMessagesAsRead.txt`, `Whatsapp id: ${whatsapp.id} \nDate: ${dateToday.fullDate} ${dateToday.fullTime} \nFile: SetTicketMessagesAsRead.ts \nError: ${err}`, (error)=>{});
|
||||||
|
|
||||||
await restartWhatsSession(whatsapp)
|
await restartWhatsSession(whatsapp)
|
||||||
|
|
||||||
console.log('...PASSOU O RESTORE - SetTicketMessagesAsRead.ts ')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,7 @@ import { addHours, addMinutes, addSeconds, intervalToDuration, add } from "date-
|
||||||
onlineTime.setUTCHours(new Date(oldOnlineTimeSum.onlineTime).getHours())
|
onlineTime.setUTCHours(new Date(oldOnlineTimeSum.onlineTime).getHours())
|
||||||
onlineTime.setUTCMinutes(new Date(oldOnlineTimeSum.onlineTime).getMinutes())
|
onlineTime.setUTCMinutes(new Date(oldOnlineTimeSum.onlineTime).getMinutes())
|
||||||
onlineTime.setUTCSeconds(new Date(oldOnlineTimeSum.onlineTime).getSeconds())
|
onlineTime.setUTCSeconds(new Date(oldOnlineTimeSum.onlineTime).getSeconds())
|
||||||
|
|
||||||
// console.log('_________________oldOnlineTimeSum.updatedAt: ', oldOnlineTimeSum.updatedAt)
|
|
||||||
|
|
||||||
let newtTime = intervalToDuration({ start: new Date(oldOnlineTimeSum.updatedAt), end: new Date() })
|
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 isoDate = new Date(onlineTime);
|
||||||
const newOnlinetime = isoDate.toJSON().slice(0, 19).replace('T', ' ');
|
const newOnlinetime = isoDate.toJSON().slice(0, 19).replace('T', ' ');
|
||||||
//console.log('sum new online time: ', newOnlinetime)
|
|
||||||
|
|
||||||
return newOnlinetime
|
return newOnlinetime
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -1,16 +1,16 @@
|
||||||
import Ticket from "../models/Ticket";
|
import Ticket from "../models/Ticket";
|
||||||
import UpdateTicketService from "../services/TicketServices/UpdateTicketService";
|
import UpdateTicketService from "../services/TicketServices/UpdateTicketService";
|
||||||
|
|
||||||
const UpdateDeletedUserOpenTicketsStatus = async (
|
const UpdateDeletedUserOpenTicketsStatus = async (
|
||||||
tickets: Ticket[]
|
tickets: Ticket[]
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
tickets.forEach(async t => {
|
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
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -97,8 +97,7 @@ const monitor = async () => {
|
||||||
const indexAux = lstOnline.findIndex((e: any) => e.id == el.id)
|
const indexAux = lstOnline.findIndex((e: any) => e.id == el.id)
|
||||||
|
|
||||||
|
|
||||||
if (indexAux == -1) {
|
if (indexAux == -1) {
|
||||||
console.log(' entrou indexAux: ', indexAux)
|
|
||||||
|
|
||||||
const userOnline = await createOrUpdateOnlineUserService({ userId: el.id, status: 'online' })
|
const userOnline = await createOrUpdateOnlineUserService({ userId: el.id, status: 'online' })
|
||||||
|
|
||||||
|
|
|
@ -79,8 +79,7 @@ export const initIO = (httpServer: Server): SocketIO => {
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
listOnlineAux.push({ 'id': userId })
|
listOnlineAux.push({ 'id': userId })
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log(' -------------- PULO FORA')
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,7 @@ class Message extends Model<Message> {
|
||||||
@Column(DataType.STRING)
|
@Column(DataType.STRING)
|
||||||
get mediaUrl(): string | null {
|
get mediaUrl(): string | null {
|
||||||
if (this.getDataValue("mediaUrl")) {
|
if (this.getDataValue("mediaUrl")) {
|
||||||
return `${process.env.BACKEND_URL}:${
|
return `${process.env.BACKEND_URL}:${process.env.PROXY_PORT}/public/${this.getDataValue("mediaUrl")}`;
|
||||||
process.env.PROXY_PORT
|
|
||||||
}/public/${this.getDataValue("mediaUrl")}`;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import * as TicketController from "../controllers/TicketController";
|
||||||
const ticketRoutes = express.Router();
|
const ticketRoutes = express.Router();
|
||||||
|
|
||||||
|
|
||||||
|
// ticketRoutes.get("/tickets/cache", isAuth, TicketController.ticketsCache);
|
||||||
|
|
||||||
ticketRoutes.get("/tickets/count", isAuth, TicketController.count);
|
ticketRoutes.get("/tickets/count", isAuth, TicketController.count);
|
||||||
|
|
||||||
ticketRoutes.get("/tickets", isAuth, TicketController.index);
|
ticketRoutes.get("/tickets", isAuth, TicketController.index);
|
||||||
|
|
|
@ -7,6 +7,9 @@ import { StartAllWhatsAppsSessions } from "./services/WbotServices/StartAllWhats
|
||||||
import { startSchedulingMonitor } from "./helpers/SchedulingNotifySendMessage"
|
import { startSchedulingMonitor } from "./helpers/SchedulingNotifySendMessage"
|
||||||
import { startWhoIsOnlineMonitor } from "./helpers/WhoIsOnlineMonitor"
|
import { startWhoIsOnlineMonitor } from "./helpers/WhoIsOnlineMonitor"
|
||||||
|
|
||||||
|
import { loadTicketsCache, flushCache, cacheSize } from './helpers/TicketCache'
|
||||||
|
import { loadContactsCache } from './helpers/ContactsCache'
|
||||||
|
|
||||||
const server = app.listen(process.env.PORT, () => {
|
const server = app.listen(process.env.PORT, () => {
|
||||||
logger.info(`Server started on port: ${process.env.PORT}`);
|
logger.info(`Server started on port: ${process.env.PORT}`);
|
||||||
});
|
});
|
||||||
|
@ -15,5 +18,20 @@ initIO(server);
|
||||||
StartAllWhatsAppsSessions();
|
StartAllWhatsAppsSessions();
|
||||||
gracefulShutdown(server);
|
gracefulShutdown(server);
|
||||||
|
|
||||||
|
(async()=>{
|
||||||
|
|
||||||
|
const cacheLength = await cacheSize()
|
||||||
|
|
||||||
|
if(cacheLength == 0){
|
||||||
|
console.log('Loading from cache...')
|
||||||
|
await flushCache()
|
||||||
|
await loadContactsCache()
|
||||||
|
await loadTicketsCache()
|
||||||
|
}
|
||||||
|
|
||||||
|
})()
|
||||||
|
|
||||||
|
|
||||||
startSchedulingMonitor(5000)
|
startSchedulingMonitor(5000)
|
||||||
startWhoIsOnlineMonitor(50000)
|
startWhoIsOnlineMonitor(3000)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import AppError from "../../errors/AppError";
|
import AppError from "../../errors/AppError";
|
||||||
import Contact from "../../models/Contact";
|
import Contact from "../../models/Contact";
|
||||||
|
|
||||||
|
import { createOrUpdateContactCache } from '../../helpers/ContactsCache'
|
||||||
|
|
||||||
interface ExtraInfo {
|
interface ExtraInfo {
|
||||||
name: string;
|
name: string;
|
||||||
value: 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;
|
return contact;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { getIO } from "../../libs/socket";
|
import { getIO } from "../../libs/socket";
|
||||||
import Contact from "../../models/Contact";
|
import Contact from "../../models/Contact";
|
||||||
|
|
||||||
|
import { createOrUpdateContactCache } from '../../helpers/ContactsCache'
|
||||||
|
|
||||||
interface ExtraInfo {
|
interface ExtraInfo {
|
||||||
name: string;
|
name: string;
|
||||||
value: string;
|
value: string;
|
||||||
|
@ -28,10 +30,15 @@ const CreateOrUpdateContactService = async ({
|
||||||
const io = getIO();
|
const io = getIO();
|
||||||
let contact: Contact | null;
|
let contact: Contact | null;
|
||||||
|
|
||||||
|
|
||||||
contact = await Contact.findOne({ where: { number } });
|
contact = await Contact.findOne({ where: { number } });
|
||||||
|
|
||||||
if (contact) {
|
if (contact) {
|
||||||
contact.update({ profilePicUrl });
|
contact.update({ profilePicUrl });
|
||||||
|
|
||||||
|
// TEST DEL
|
||||||
|
await createOrUpdateContactCache(`contact:${contact.id}`, { profilePicUrl })
|
||||||
|
//
|
||||||
|
|
||||||
io.emit("contact", {
|
io.emit("contact", {
|
||||||
action: "update",
|
action: "update",
|
||||||
|
@ -47,6 +54,11 @@ const CreateOrUpdateContactService = async ({
|
||||||
extraInfo
|
extraInfo
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TEST DEL
|
||||||
|
await createOrUpdateContactCache(`contact:${contact.id}`, {id: contact.id, name, number, profilePicUrl, isGroup, extraInfo, email })
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
io.emit("contact", {
|
io.emit("contact", {
|
||||||
action: "create",
|
action: "create",
|
||||||
contact
|
contact
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import Contact from "../../models/Contact";
|
import Contact from "../../models/Contact";
|
||||||
import AppError from "../../errors/AppError";
|
import AppError from "../../errors/AppError";
|
||||||
|
|
||||||
|
import { deleteTicketsByContactsCache } from '../../helpers/TicketCache'
|
||||||
|
import {deleteContactsByIdCache} from '../../helpers/ContactsCache'
|
||||||
|
|
||||||
const DeleteContactService = async (id: string): Promise<void> => {
|
const DeleteContactService = async (id: string): Promise<void> => {
|
||||||
const contact = await Contact.findOne({
|
const contact = await Contact.findOne({
|
||||||
where: { id }
|
where: { id }
|
||||||
|
@ -10,6 +13,11 @@ const DeleteContactService = async (id: string): Promise<void> => {
|
||||||
throw new AppError("ERR_NO_CONTACT_FOUND", 404);
|
throw new AppError("ERR_NO_CONTACT_FOUND", 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TEST DEL
|
||||||
|
await deleteTicketsByContactsCache(contact.number)
|
||||||
|
await deleteContactsByIdCache(contact.id)
|
||||||
|
//
|
||||||
|
|
||||||
await contact.destroy();
|
await contact.destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,14 +29,14 @@ const ListContactsService = async ({
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
const limit = 20;
|
const limit = 20;
|
||||||
const offset = limit * (+pageNumber - 1);
|
const offset = limit * (+pageNumber - 1);
|
||||||
|
|
||||||
const { count, rows: contacts } = await Contact.findAndCountAll({
|
const { count, rows: contacts } = await Contact.findAndCountAll({
|
||||||
where: whereCondition,
|
where: whereCondition,
|
||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
order: [["name", "ASC"]]
|
order: [["name", "ASC"]]
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasMore = count > offset + contacts.length;
|
const hasMore = count > offset + contacts.length;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Sequelize, Op } from "sequelize";
|
||||||
|
import Contact from "../../models/Contact";
|
||||||
|
|
||||||
|
const ListContactsServiceCache = async (): Promise<any> => {
|
||||||
|
|
||||||
|
const contacts = await Contact.findAll({ where: {}, raw:true, order: [["name", "ASC"]] });
|
||||||
|
|
||||||
|
return contacts
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ListContactsServiceCache;
|
|
@ -2,6 +2,9 @@ import AppError from "../../errors/AppError";
|
||||||
import Contact from "../../models/Contact";
|
import Contact from "../../models/Contact";
|
||||||
import ContactCustomField from "../../models/ContactCustomField";
|
import ContactCustomField from "../../models/ContactCustomField";
|
||||||
|
|
||||||
|
import { updateTicketsByContactsCache } from '../../helpers/TicketCache'
|
||||||
|
import { updateContactCacheById } from '../../helpers/ContactsCache'
|
||||||
|
|
||||||
interface ExtraInfo {
|
interface ExtraInfo {
|
||||||
id?: number;
|
id?: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -18,6 +21,7 @@ interface Request {
|
||||||
contactData: ContactData;
|
contactData: ContactData;
|
||||||
contactId: string;
|
contactId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const UpdateContactService = async ({
|
const UpdateContactService = async ({
|
||||||
contactData,
|
contactData,
|
||||||
|
@ -51,19 +55,31 @@ const UpdateContactService = async ({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const oldNumber = contact.number
|
||||||
|
|
||||||
await contact.update({
|
await contact.update({
|
||||||
name,
|
name,
|
||||||
number,
|
number,
|
||||||
email
|
email
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//TEST DEL
|
||||||
|
await updateTicketsByContactsCache(oldNumber, contact.name, contact.number)
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
await contact.reload({
|
await contact.reload({
|
||||||
attributes: ["id", "name", "number", "email", "profilePicUrl"],
|
attributes: ["id", "name", "number", "email", "profilePicUrl"],
|
||||||
include: ["extraInfo"]
|
include: ["extraInfo"]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// console.log('contactcontactcontactcontact: ',flatten(JSON.parse(JSON.stringify(contact))))
|
||||||
|
await updateContactCacheById(contact.id, JSON.parse(JSON.stringify(contact)))
|
||||||
|
|
||||||
return contact;
|
return contact;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { updateTicketCacheByTicketId } from "../../helpers/TicketCache";
|
||||||
import { getIO } from "../../libs/socket";
|
import { getIO } from "../../libs/socket";
|
||||||
import Message from "../../models/Message";
|
import Message from "../../models/Message";
|
||||||
import Ticket from "../../models/Ticket";
|
import Ticket from "../../models/Ticket";
|
||||||
|
@ -16,7 +17,7 @@ interface Request {
|
||||||
messageData: MessageData;
|
messageData: MessageData;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CreateMessageService = async ({messageData}: Request): Promise<Message> => {
|
const CreateMessageService = async ({ messageData }: Request): Promise<Message> => {
|
||||||
await Message.upsert(messageData);
|
await Message.upsert(messageData);
|
||||||
|
|
||||||
const message = await Message.findByPk(messageData.id, {
|
const message = await Message.findByPk(messageData.id, {
|
||||||
|
@ -39,9 +40,20 @@ const CreateMessageService = async ({messageData}: Request): Promise<Message> =>
|
||||||
throw new Error("ERR_CREATING_MESSAGE");
|
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();
|
const io = getIO();
|
||||||
io.to(message.ticketId.toString())
|
io.to(message.ticketId.toString())
|
||||||
|
@ -54,8 +66,8 @@ const CreateMessageService = async ({messageData}: Request): Promise<Message> =>
|
||||||
contact: message.ticket.contact
|
contact: message.ticket.contact
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,14 +2,31 @@ import ShowQueueService from "./ShowQueueService";
|
||||||
|
|
||||||
import UserQueue from "../../models/UserQueue";
|
import UserQueue from "../../models/UserQueue";
|
||||||
|
|
||||||
|
import ListTicketsServiceCache from "../TicketServices/ListTicketServiceCache";
|
||||||
|
|
||||||
|
import { deleteTicketsFieldsCache } from '../../helpers/TicketCache'
|
||||||
|
|
||||||
const DeleteQueueService = async (queueId: number | string): Promise<void> => {
|
const DeleteQueueService = async (queueId: number | string): Promise<void> => {
|
||||||
|
|
||||||
const queue = await ShowQueueService(queueId);
|
const queue = await ShowQueueService(queueId);
|
||||||
|
|
||||||
|
if (queue.id) {
|
||||||
|
|
||||||
|
const tickets = await ListTicketsServiceCache({ queueId })
|
||||||
|
|
||||||
|
await deleteTicketsFieldsCache(tickets, ['queue.id', 'queue.name', 'queue.color'])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await UserQueue.destroy({ where: {queueId: queueId } });
|
|
||||||
|
await UserQueue.destroy({ where: { queueId: queueId } });
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Error on delete UserQueue by queueId: ',queueId)
|
|
||||||
}
|
console.log('Error on delete UserQueue by queueId: ', queueId)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
await queue.destroy();
|
await queue.destroy();
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,9 +23,7 @@ const CreateSchedulingNotifyService = async ({
|
||||||
|
|
||||||
let schedulingNotify = null;
|
let schedulingNotify = null;
|
||||||
|
|
||||||
if(schedulingNotifyId){
|
if(schedulingNotifyId){
|
||||||
|
|
||||||
console.log('000000000000000000000000000 ATUALIZOU!')
|
|
||||||
|
|
||||||
schedulingNotify = await SchedulingNotify.findOne({ where: { id: schedulingNotifyId } });
|
schedulingNotify = await SchedulingNotify.findOne({ where: { id: schedulingNotifyId } });
|
||||||
|
|
||||||
|
@ -48,9 +46,7 @@ const CreateSchedulingNotifyService = async ({
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!schedulingNotify){
|
if(!schedulingNotify){
|
||||||
|
|
||||||
console.log('111111111111111111111111111 criou!')
|
|
||||||
|
|
||||||
schedulingNotify = await SchedulingNotify.create(
|
schedulingNotify = await SchedulingNotify.create(
|
||||||
{
|
{
|
||||||
ticketId,
|
ticketId,
|
||||||
|
|
|
@ -13,6 +13,11 @@ import ptBR from 'date-fns/locale/pt-BR';
|
||||||
import { splitDateTime } from "../../helpers/SplitDateTime";
|
import { splitDateTime } from "../../helpers/SplitDateTime";
|
||||||
import TicketEmiterSumOpenClosedByUser from "../../helpers/OnlineReporEmiterInfoByUser";
|
import TicketEmiterSumOpenClosedByUser from "../../helpers/OnlineReporEmiterInfoByUser";
|
||||||
|
|
||||||
|
import { createOrUpdateTicketCache } from '../../helpers/TicketCache'
|
||||||
|
let flatten = require('flat')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface Request {
|
interface Request {
|
||||||
contactId: number;
|
contactId: number;
|
||||||
status: string;
|
status: string;
|
||||||
|
@ -41,16 +46,29 @@ const CreateTicketService = async ({
|
||||||
|
|
||||||
if (!ticket) {
|
if (!ticket) {
|
||||||
throw new AppError("ERR_CREATING_TICKET");
|
throw new AppError("ERR_CREATING_TICKET");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// console.log('CONTACT ticket.id: ', ticket.id)
|
||||||
|
|
||||||
|
|
||||||
//test del
|
// TEST DEL
|
||||||
// 2022-05-11T05:20:33.000Z,
|
try {
|
||||||
// const dateToday = ticket.createdAt.toISOString().split('T')[0]
|
|
||||||
|
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 })))
|
|
||||||
|
const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR })))
|
||||||
//openByUser : [ { id: 13, status: 'online' } ]
|
|
||||||
|
|
||||||
TicketEmiterSumOpenClosedByUser(userId.toString(), dateToday.fullDate, dateToday.fullDate)
|
TicketEmiterSumOpenClosedByUser(userId.toString(), dateToday.fullDate, dateToday.fullDate)
|
||||||
|
|
||||||
|
@ -58,10 +76,7 @@ const CreateTicketService = async ({
|
||||||
io.emit("ticketStatus", {
|
io.emit("ticketStatus", {
|
||||||
action: "update",
|
action: "update",
|
||||||
ticketStatus: {ticketId: ticket.id, status: ticket.status}
|
ticketStatus: {ticketId: ticket.id, status: ticket.status}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
return ticket;
|
return ticket;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import Ticket from "../../models/Ticket";
|
import Ticket from "../../models/Ticket";
|
||||||
import AppError from "../../errors/AppError";
|
import AppError from "../../errors/AppError";
|
||||||
|
|
||||||
|
import { deleteTicketsByIdCache } from '../../helpers/TicketCache'
|
||||||
|
|
||||||
const DeleteTicketService = async (id: string): Promise<Ticket> => {
|
const DeleteTicketService = async (id: string): Promise<Ticket> => {
|
||||||
const ticket = await Ticket.findOne({
|
const ticket = await Ticket.findOne({
|
||||||
where: { id }
|
where: { id }
|
||||||
|
@ -10,7 +12,11 @@ const DeleteTicketService = async (id: string): Promise<Ticket> => {
|
||||||
throw new AppError("ERR_NO_TICKET_FOUND", 404);
|
throw new AppError("ERR_NO_TICKET_FOUND", 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
await ticket.destroy();
|
await ticket.destroy();
|
||||||
|
|
||||||
|
// TEST DEL
|
||||||
|
await deleteTicketsByIdCache(id)
|
||||||
|
//
|
||||||
|
|
||||||
return ticket;
|
return ticket;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,9 +4,7 @@ import BotIsOnQueue from "../../helpers/BotIsOnQueue";
|
||||||
import Contact from "../../models/Contact";
|
import Contact from "../../models/Contact";
|
||||||
import Ticket from "../../models/Ticket";
|
import Ticket from "../../models/Ticket";
|
||||||
import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService";
|
import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService";
|
||||||
import ShowTicketService from "./ShowTicketService";
|
import ShowTicketService from "./ShowTicketService";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const FindOrCreateTicketService = async (
|
const FindOrCreateTicketService = async (
|
||||||
|
@ -22,18 +20,18 @@ const FindOrCreateTicketService = async (
|
||||||
},
|
},
|
||||||
contactId: groupContact ? groupContact.id : contact.id
|
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
|
//Habilitar esse caso queira usar o bot
|
||||||
// const botInfo = await BotIsOnQueue('botqueue')
|
// const botInfo = await BotIsOnQueue('botqueue')
|
||||||
const botInfo = {isOnQueue: false}
|
const botInfo = { isOnQueue: false }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (ticket) {
|
|
||||||
|
|
||||||
|
if (ticket) {
|
||||||
await ticket.update({ unreadMessages });
|
await ticket.update({ unreadMessages });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +45,7 @@ const FindOrCreateTicketService = async (
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (ticket) {
|
if (ticket) {
|
||||||
|
|
||||||
await ticket.update({
|
await ticket.update({
|
||||||
status: "pending",
|
status: "pending",
|
||||||
|
@ -57,8 +55,8 @@ const FindOrCreateTicketService = async (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ticket && !groupContact) {
|
if (!ticket && !groupContact) {
|
||||||
|
|
||||||
ticket = await Ticket.findOne({
|
ticket = await Ticket.findOne({
|
||||||
where: {
|
where: {
|
||||||
updatedAt: {
|
updatedAt: {
|
||||||
|
@ -68,15 +66,15 @@ const FindOrCreateTicketService = async (
|
||||||
//[Op.between]: [+subMinutes(new Date(), 30), +new Date()]
|
//[Op.between]: [+subMinutes(new Date(), 30), +new Date()]
|
||||||
|
|
||||||
// Sub seconds
|
// Sub seconds
|
||||||
[Op.between]: [+subSeconds(new Date(), 0), +new Date()]
|
[Op.between]: [+subSeconds(new Date(), 0), +new Date()]
|
||||||
},
|
},
|
||||||
contactId: contact.id
|
contactId: contact.id
|
||||||
},
|
},
|
||||||
order: [["updatedAt", "DESC"]]
|
order: [["updatedAt", "DESC"]]
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ticket) {
|
if (ticket) {
|
||||||
|
|
||||||
await ticket.update({
|
await ticket.update({
|
||||||
status: "pending",
|
status: "pending",
|
||||||
userId: null,
|
userId: null,
|
||||||
|
@ -85,14 +83,14 @@ const FindOrCreateTicketService = async (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ticket) {
|
if (!ticket) {
|
||||||
|
|
||||||
let status = "pending"
|
let status = "pending"
|
||||||
|
|
||||||
if(queues.length > 1 && !botInfo.isOnQueue){
|
if (queues.length > 1 && !botInfo.isOnQueue) {
|
||||||
status = "queueChoice"
|
status = "queueChoice"
|
||||||
}
|
}
|
||||||
|
|
||||||
ticket = await Ticket.create({
|
ticket = await Ticket.create({
|
||||||
contactId: groupContact ? groupContact.id : contact.id,
|
contactId: groupContact ? groupContact.id : contact.id,
|
||||||
status: status,
|
status: status,
|
||||||
|
@ -100,10 +98,18 @@ const FindOrCreateTicketService = async (
|
||||||
unreadMessages,
|
unreadMessages,
|
||||||
whatsappId
|
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);
|
ticket = await ShowTicketService(ticket.id);
|
||||||
|
|
||||||
|
|
||||||
return ticket;
|
return ticket;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,25 @@ import Contact from "../../models/Contact";
|
||||||
import Queue from "../../models/Queue";
|
import Queue from "../../models/Queue";
|
||||||
const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR })))
|
const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR })))
|
||||||
|
|
||||||
const ListTicketsServiceCache = async (status?: string, date?: string): Promise<any> => {
|
|
||||||
|
interface Request {
|
||||||
|
status?: string;
|
||||||
|
date?: string;
|
||||||
|
userId?: string | number;
|
||||||
|
queueId?: string | number
|
||||||
|
}
|
||||||
|
|
||||||
|
const ListTicketsServiceCache = async ({
|
||||||
|
status,
|
||||||
|
date,
|
||||||
|
userId,
|
||||||
|
queueId
|
||||||
|
}:Request): Promise<any> => {
|
||||||
|
|
||||||
let where_clause = {}
|
let where_clause = {}
|
||||||
|
|
||||||
|
console.log(' QUEUE ID: ', queueId)
|
||||||
|
|
||||||
if (date) {
|
if (date) {
|
||||||
where_clause = {
|
where_clause = {
|
||||||
createdAt: {
|
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 {
|
else {
|
||||||
// where_clause = {
|
// where_clause = {
|
||||||
// createdAt: {
|
// createdAt: {
|
||||||
|
|
|
@ -8,11 +8,17 @@ import Message from "../../models/Message";
|
||||||
import Queue from "../../models/Queue";
|
import Queue from "../../models/Queue";
|
||||||
import ShowUserService from "../UserServices/ShowUserService";
|
import ShowUserService from "../UserServices/ShowUserService";
|
||||||
|
|
||||||
|
const unflatten = require('flat').unflatten
|
||||||
|
|
||||||
import { splitDateTime } from "../../helpers/SplitDateTime";
|
import { splitDateTime } from "../../helpers/SplitDateTime";
|
||||||
const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR })))
|
const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR })))
|
||||||
|
|
||||||
import ListTicketServiceCache from "./ListTicketServiceCache"
|
import ListTicketServiceCache from "./ListTicketServiceCache"
|
||||||
|
|
||||||
|
import { searchTicketCache, loadTicketsCache } from '../../helpers/TicketCache'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface Request {
|
interface Request {
|
||||||
searchParam?: string;
|
searchParam?: string;
|
||||||
|
@ -32,6 +38,7 @@ interface Response {
|
||||||
hasMore: boolean;
|
hasMore: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const ListTicketsService = async ({
|
const ListTicketsService = async ({
|
||||||
searchParam = "",
|
searchParam = "",
|
||||||
pageNumber = "1",
|
pageNumber = "1",
|
||||||
|
@ -43,17 +50,48 @@ const ListTicketsService = async ({
|
||||||
withUnreadMessages,
|
withUnreadMessages,
|
||||||
unlimited = 'false'
|
unlimited = 'false'
|
||||||
}: Request): Promise<Response> => {
|
}: Request): Promise<Response> => {
|
||||||
let whereCondition: Filterable["where"] = {
|
|
||||||
[Op.or]: [{ userId }, { status: "pending" }],
|
let whereCondition: Filterable["where"] = { [Op.or]: [{ userId }, { status: "pending" }], queueId: { [Op.or]: [queueIds, null] } };
|
||||||
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[];
|
let includeCondition: Includeable[];
|
||||||
|
|
||||||
|
|
||||||
// test del
|
|
||||||
// const test = await ListTicketServiceCache()
|
|
||||||
// console.log('TEST:\n', test)
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
includeCondition = [
|
includeCondition = [
|
||||||
|
@ -77,9 +115,8 @@ const ListTicketsService = async ({
|
||||||
|
|
||||||
whereCondition = { ...whereCondition, status };
|
whereCondition = { ...whereCondition, status };
|
||||||
|
|
||||||
// console.log('TEST unlimited: ', unlimited)
|
|
||||||
|
|
||||||
if (unlimited === 'true' && status !== 'pending') {
|
if (unlimited === 'true' && status !== 'pending') {
|
||||||
|
|
||||||
whereCondition = {
|
whereCondition = {
|
||||||
...whereCondition,
|
...whereCondition,
|
||||||
|
@ -95,10 +132,6 @@ const ListTicketsService = async ({
|
||||||
if (searchParam) {
|
if (searchParam) {
|
||||||
const sanitizedSearchParam = searchParam.toLocaleLowerCase().trim();
|
const sanitizedSearchParam = searchParam.toLocaleLowerCase().trim();
|
||||||
|
|
||||||
//othavio
|
|
||||||
|
|
||||||
console.log('sanitizedSearchParam:'+ sanitizedSearchParam, ' | date: ',date)
|
|
||||||
|
|
||||||
// includeCondition = [
|
// includeCondition = [
|
||||||
// ...includeCondition,
|
// ...includeCondition,
|
||||||
// {
|
// {
|
||||||
|
@ -119,7 +152,7 @@ const ListTicketsService = async ({
|
||||||
{
|
{
|
||||||
"$contact.name$": where(fn("LOWER", col("contact.name")), "LIKE", `%${sanitizedSearchParam}%`)
|
"$contact.name$": where(fn("LOWER", col("contact.name")), "LIKE", `%${sanitizedSearchParam}%`)
|
||||||
},
|
},
|
||||||
|
|
||||||
{ "$contact.number$": { [Op.like]: `%${sanitizedSearchParam}%` } },
|
{ "$contact.number$": { [Op.like]: `%${sanitizedSearchParam}%` } },
|
||||||
|
|
||||||
// {
|
// {
|
||||||
|
@ -152,7 +185,8 @@ const ListTicketsService = async ({
|
||||||
const offset = limit * (+pageNumber - 1);
|
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({
|
const { count, rows: tickets } = await Ticket.findAndCountAll({
|
||||||
where: whereCondition,
|
where: whereCondition,
|
||||||
|
@ -165,7 +199,7 @@ const ListTicketsService = async ({
|
||||||
|
|
||||||
const hasMore = count > offset + tickets.length;
|
const hasMore = count > offset + tickets.length;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tickets,
|
tickets,
|
||||||
|
|
|
@ -6,6 +6,11 @@ import SendWhatsAppMessage from "../WbotServices/SendWhatsAppMessage";
|
||||||
import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService";
|
import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService";
|
||||||
import ShowTicketService from "./ShowTicketService";
|
import ShowTicketService from "./ShowTicketService";
|
||||||
|
|
||||||
|
import { createOrUpdateTicketCache } from '../../helpers/TicketCache'
|
||||||
|
var flatten = require('flat')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface TicketData {
|
interface TicketData {
|
||||||
status?: string;
|
status?: string;
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
@ -38,8 +43,8 @@ const UpdateTicketService = async ({
|
||||||
|
|
||||||
if (oldStatus === "closed") {
|
if (oldStatus === "closed") {
|
||||||
await CheckContactOpenTickets(ticket.contact.id);
|
await CheckContactOpenTickets(ticket.contact.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
await ticket.update({
|
await ticket.update({
|
||||||
status,
|
status,
|
||||||
queueId,
|
queueId,
|
||||||
|
@ -47,10 +52,27 @@ const UpdateTicketService = async ({
|
||||||
statusChatEnd
|
statusChatEnd
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await ticket.reload();
|
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();
|
let io = getIO();
|
||||||
|
|
||||||
if (ticket.status !== oldStatus || ticket.user?.id !== oldUserId) {
|
if (ticket.status !== oldStatus || ticket.user?.id !== oldUserId) {
|
||||||
|
@ -69,7 +91,7 @@ const UpdateTicketService = async ({
|
||||||
ticket
|
ticket
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
io.emit("ticketStatus", {
|
io.emit("ticketStatus", {
|
||||||
action: "update",
|
action: "update",
|
||||||
ticketStatus: { ticketId: ticket.id, status: ticket.status }
|
ticketStatus: { ticketId: ticket.id, status: ticket.status }
|
||||||
|
|
|
@ -33,16 +33,16 @@ const CreateOrUpdateUserOnlineTime = async ({
|
||||||
userId,
|
userId,
|
||||||
status,
|
status,
|
||||||
}: Request): Promise<UserOnlineTime> => {
|
}: Request): Promise<UserOnlineTime> => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const io = getIO();
|
const io = getIO();
|
||||||
let userOnlineTime:any = null;
|
let userOnlineTime: any = null;
|
||||||
|
|
||||||
const user = await User.findOne({ where: { id: userId } });
|
const user = await User.findOne({ where: { id: userId } });
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
console.log(' yyyyyyyyyyyyyyyyyyyyyyyyyy não tem mais esse usuario id: ', userId)
|
|
||||||
return userOnlineTime
|
return userOnlineTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,27 +68,21 @@ const CreateOrUpdateUserOnlineTime = async ({
|
||||||
let oldStatus = userOnlineTime.status
|
let oldStatus = userOnlineTime.status
|
||||||
|
|
||||||
|
|
||||||
console.log('>>>>>>>>> oldStatus: ', oldStatus, ' | new status', status)
|
|
||||||
|
|
||||||
if (oldStatus == 'online' && status === 'offline') {
|
if (oldStatus == 'online' && status === 'offline') {
|
||||||
//updatedAt
|
//updatedAt
|
||||||
let newtTime = intervalToDuration({ start: userOnlineTime.updatedAt, end: new Date() })
|
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()
|
let onlineTime = new Date()
|
||||||
|
|
||||||
onlineTime.setUTCHours(userOnlineTime.onlineTime.getHours())
|
onlineTime.setUTCHours(userOnlineTime.onlineTime.getHours())
|
||||||
onlineTime.setUTCMinutes(userOnlineTime.onlineTime.getMinutes())
|
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) {
|
if (newtTime.hours && +newtTime.hours > 0) {
|
||||||
|
@ -101,11 +95,11 @@ const CreateOrUpdateUserOnlineTime = async ({
|
||||||
onlineTime = addSeconds(onlineTime, newtTime.seconds)
|
onlineTime = addSeconds(onlineTime, newtTime.seconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('online time 4: ', onlineTime)
|
|
||||||
|
|
||||||
const isoDate = new Date(onlineTime);
|
const isoDate = new Date(onlineTime);
|
||||||
const mySQLDateString = isoDate.toJSON().slice(0, 19).replace('T', ' ');
|
const mySQLDateString = isoDate.toJSON().slice(0, 19).replace('T', ' ');
|
||||||
console.log('mySQLDateString: ', mySQLDateString)
|
|
||||||
|
|
||||||
await userOnlineTime.update({ status, onlineTime: mySQLDateString })
|
await userOnlineTime.update({ status, onlineTime: mySQLDateString })
|
||||||
|
|
||||||
|
@ -114,10 +108,10 @@ const CreateOrUpdateUserOnlineTime = async ({
|
||||||
const updatedAtString = formatDateTimeString(userOnlineTime.updatedAt)
|
const updatedAtString = formatDateTimeString(userOnlineTime.updatedAt)
|
||||||
const createdAtString = formatDateTimeString(userOnlineTime.createdAt)
|
const createdAtString = formatDateTimeString(userOnlineTime.createdAt)
|
||||||
|
|
||||||
console.log('CreatedAt string: ', createdAtString)
|
|
||||||
console.log('UpdatedAt string: ', updatedAtString)
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
io.emit("onlineStatus", {
|
io.emit("onlineStatus", {
|
||||||
action: "update",
|
action: "update",
|
||||||
|
@ -133,7 +127,7 @@ const CreateOrUpdateUserOnlineTime = async ({
|
||||||
}
|
}
|
||||||
else if (oldStatus == 'offline' && status === 'online') {
|
else if (oldStatus == 'offline' && status === 'online') {
|
||||||
await userOnlineTime.update({ status })
|
await userOnlineTime.update({ status })
|
||||||
|
|
||||||
io.emit("onlineStatus", {
|
io.emit("onlineStatus", {
|
||||||
action: "update",
|
action: "update",
|
||||||
userOnlineTime: {
|
userOnlineTime: {
|
||||||
|
|
|
@ -104,11 +104,7 @@ const ShowUserServiceReport = async ({
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// console.log('>>>>>>>>>>>>>> objQuery: ', objQuery)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!objQuery) {
|
if (!objQuery) {
|
||||||
throw new AppError("ERR_NO_OBJ_QUERY_FOUND", 404);
|
throw new AppError("ERR_NO_OBJ_QUERY_FOUND", 404);
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { getWbot } from "../../libs/wbot";
|
||||||
import Contact from "../../models/Contact";
|
import Contact from "../../models/Contact";
|
||||||
import { logger } from "../../utils/logger";
|
import { logger } from "../../utils/logger";
|
||||||
|
|
||||||
|
import { createOrUpdateContactCache } from '../../helpers/ContactsCache'
|
||||||
|
|
||||||
const ImportContactsService = async (): Promise<void> => {
|
const ImportContactsService = async (): Promise<void> => {
|
||||||
const defaultWhatsapp = await GetDefaultWhatsApp();
|
const defaultWhatsapp = await GetDefaultWhatsApp();
|
||||||
|
|
||||||
|
@ -32,7 +34,16 @@ const ImportContactsService = async (): Promise<void> => {
|
||||||
|
|
||||||
if (numberExists) return null;
|
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
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@ import AppError from "../../errors/AppError";
|
||||||
import GetTicketWbot from "../../helpers/GetTicketWbot";
|
import GetTicketWbot from "../../helpers/GetTicketWbot";
|
||||||
import Ticket from "../../models/Ticket";
|
import Ticket from "../../models/Ticket";
|
||||||
|
|
||||||
|
import { updateTicketCacheByTicketId } from '../../helpers/TicketCache'
|
||||||
|
import { date } from "faker";
|
||||||
|
|
||||||
interface Request {
|
interface Request {
|
||||||
media: Express.Multer.File;
|
media: Express.Multer.File;
|
||||||
ticket: Ticket;
|
ticket: Ticket;
|
||||||
|
@ -22,6 +25,10 @@ const SendWhatsAppMedia = async ({
|
||||||
|
|
||||||
await ticket.update({ lastMessage: media.filename });
|
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);
|
fs.unlinkSync(media.path);
|
||||||
|
|
||||||
return sentMessage;
|
return sentMessage;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import wbotByUserQueue from '../../helpers/GetWbotByUserQueue'
|
||||||
|
|
||||||
import { WhatsIndex } from "../../helpers/LoadBalanceWhatsSameQueue";
|
import { WhatsIndex } from "../../helpers/LoadBalanceWhatsSameQueue";
|
||||||
|
|
||||||
|
import { updateTicketCacheByTicketId } from '../../helpers/TicketCache'
|
||||||
|
|
||||||
interface Request {
|
interface Request {
|
||||||
body: string;
|
body: string;
|
||||||
|
@ -61,6 +62,12 @@ const SendWhatsAppMessage = async ({
|
||||||
try {
|
try {
|
||||||
const sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, body, { quotedMessageId: quotedMsgSerializedId, linkPreview: false });
|
const sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, body, { quotedMessageId: quotedMsgSerializedId, linkPreview: false });
|
||||||
await ticket.update({ lastMessage: body });
|
await ticket.update({ lastMessage: body });
|
||||||
|
|
||||||
|
|
||||||
|
// TEST DEL
|
||||||
|
await updateTicketCacheByTicketId(ticket.id, { lastMessage: body, updatedAt: new Date(ticket.updatedAt).toISOString() })
|
||||||
|
//
|
||||||
|
|
||||||
return sentMessage;
|
return sentMessage;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new AppError("ERR_SENDING_WAPP_MSG");
|
throw new AppError("ERR_SENDING_WAPP_MSG");
|
||||||
|
|
|
@ -10,6 +10,8 @@ import path from 'path';
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import ptBR from 'date-fns/locale/pt-BR';
|
import ptBR from 'date-fns/locale/pt-BR';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Contact as WbotContact,
|
Contact as WbotContact,
|
||||||
Message as WbotMessage,
|
Message as WbotMessage,
|
||||||
|
@ -49,7 +51,9 @@ import final_message from "./ura_final_message";
|
||||||
import SendWhatsAppMessage from "./SendWhatsAppMessage";
|
import SendWhatsAppMessage from "./SendWhatsAppMessage";
|
||||||
import Whatsapp from "../../models/Whatsapp";
|
import Whatsapp from "../../models/Whatsapp";
|
||||||
import { splitDateTime } from "../../helpers/SplitDateTime";
|
import { splitDateTime } from "../../helpers/SplitDateTime";
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import { updateTicketCacheByTicketId } from '../../helpers/TicketCache'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,6 +163,10 @@ const verifyMessage = async (
|
||||||
|
|
||||||
await ticket.update({ lastMessage: msg.body });
|
await ticket.update({ lastMessage: msg.body });
|
||||||
|
|
||||||
|
// TEST DEL
|
||||||
|
// await updateTicketCacheByTicketId(ticket.id, { lastMessage: msg.body, updatedAt: new Date(ticket.updatedAt).toISOString() })
|
||||||
|
//
|
||||||
|
|
||||||
await CreateMessageService({ messageData });
|
await CreateMessageService({ messageData });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -227,7 +235,7 @@ const verifyQueue = async (
|
||||||
ticketData: { queueId: choosenQueue.id },
|
ticketData: { queueId: choosenQueue.id },
|
||||||
ticketId: ticket.id
|
ticketId: ticket.id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let botOptions = ''
|
let botOptions = ''
|
||||||
|
|
||||||
|
@ -255,7 +263,8 @@ const verifyQueue = async (
|
||||||
const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body);
|
const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body);
|
||||||
|
|
||||||
await verifyMessage(sentMessage, ticket, contact);
|
await verifyMessage(sentMessage, ticket, contact);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
|
||||||
//test del transfere o atendimento se entrar na ura infinita
|
//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();
|
msgContact = await msg.getContact();
|
||||||
|
|
||||||
// console.log('-----msgContact TESTE MSG2: ', msgContact, ' | msg: ', msg)
|
//
|
||||||
|
|
||||||
console.log(`\n <<<<<<<<<< RECEIVING MESSAGE:
|
console.log(`\n <<<<<<<<<< RECEIVING MESSAGE:
|
||||||
Parcial msg and msgContact info:
|
Parcial msg and msgContact info:
|
||||||
|
@ -412,7 +420,8 @@ const handleMessage = async (
|
||||||
|
|
||||||
const unreadMessages = msg.fromMe ? 0 : chat.unreadCount;
|
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;
|
if (unreadMessages === 0 && whatsapp.farewellMessage && whatsapp.farewellMessage === msg.body) return;
|
||||||
|
@ -422,12 +431,15 @@ const handleMessage = async (
|
||||||
wbot.id!,
|
wbot.id!,
|
||||||
unreadMessages,
|
unreadMessages,
|
||||||
groupContact
|
groupContact
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// await updateTicketCacheByTicketId(ticket.id, {'contact.profilePicUrl': ticket.contact.profilePicUrl})
|
||||||
|
|
||||||
// Para responder para o cliente pelo mesmo whatsapp que ele enviou a mensagen
|
// Para responder para o cliente pelo mesmo whatsapp que ele enviou a mensagen
|
||||||
if (wbot.id != ticket.whatsappId) {
|
if (wbot.id != ticket.whatsappId) {
|
||||||
|
|
||||||
console.log('>>> entrou wbot.id: ', wbot.id, ' | ', ticket.whatsappId)
|
|
||||||
|
|
||||||
await ticket.update({ whatsappId: wbot.id });
|
await ticket.update({ whatsappId: wbot.id });
|
||||||
}
|
}
|
||||||
|
@ -495,7 +507,7 @@ const handleMessage = async (
|
||||||
opt_user_attendant = data_ura[indexAttendant].id
|
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}}]$`);
|
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
|
// È numero
|
||||||
if (!Number.isNaN(Number(msg.body.trim())) && (+msg.body >= 0 && +msg.body <= data_ura.length)) {
|
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
|
// test del
|
||||||
let next = true
|
let next = true
|
||||||
|
@ -780,7 +792,7 @@ const handleMessage = async (
|
||||||
|
|
||||||
if (whatsapp.status == 'CONNECTED') {
|
if (whatsapp.status == 'CONNECTED') {
|
||||||
|
|
||||||
console.log('wbotMessageListener.ts - ENTROU NO RESTORE...')
|
|
||||||
|
|
||||||
let timestamp = Math.floor(Date.now() / 1000)
|
let timestamp = Math.floor(Date.now() / 1000)
|
||||||
|
|
||||||
|
@ -789,7 +801,7 @@ const handleMessage = async (
|
||||||
|
|
||||||
await restartWhatsSession(whatsapp)
|
await restartWhatsSession(whatsapp)
|
||||||
|
|
||||||
console.log('...PASSOU O RESTORE - wbotMessageListener.ts ')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import "react-toastify/dist/ReactToastify.css";
|
||||||
import { createTheme, ThemeProvider } from "@material-ui/core/styles";
|
import { createTheme, ThemeProvider } from "@material-ui/core/styles";
|
||||||
import { ptBR } from "@material-ui/core/locale";
|
import { ptBR } from "@material-ui/core/locale";
|
||||||
|
|
||||||
|
import { TabTicketProvider } from "../src/context/TabTicketHeaderOption/TabTicketHeaderOption";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [locale, setLocale] = useState();
|
const [locale, setLocale] = useState();
|
||||||
|
|
||||||
|
@ -18,7 +20,7 @@ const App = () => {
|
||||||
"&::-webkit-scrollbar-thumb": {
|
"&::-webkit-scrollbar-thumb": {
|
||||||
boxShadow: "inset 0 0 6px rgba(0, 0, 0, 0.3)",
|
boxShadow: "inset 0 0 6px rgba(0, 0, 0, 0.3)",
|
||||||
|
|
||||||
backgroundColor: "#e8e8e8",
|
backgroundColor: "#e8e8e8",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
palette: {
|
palette: {
|
||||||
|
@ -41,7 +43,13 @@ const App = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<Routes />
|
|
||||||
|
{/*TabTicketProvider Context to manipulate the entire state of selected option from user click on tickets options header */}
|
||||||
|
<TabTicketProvider>
|
||||||
|
<Routes />
|
||||||
|
</TabTicketProvider>
|
||||||
|
|
||||||
|
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -165,7 +165,7 @@ const Modal = (props) => {
|
||||||
|
|
||||||
// Get from child 2
|
// Get from child 2
|
||||||
const datePickerValue = (data) => {
|
const datePickerValue = (data) => {
|
||||||
console.log('datePickerValue: ', (data));
|
|
||||||
setDatePicker(data)
|
setDatePicker(data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ const Modal = (props) => {
|
||||||
|
|
||||||
// Get from child 3
|
// Get from child 3
|
||||||
const timerPickerValue = (data) => {
|
const timerPickerValue = (data) => {
|
||||||
console.log('timerPickerValue: ', (data));
|
|
||||||
setTimerPicker(data)
|
setTimerPicker(data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ const Modal = (props) => {
|
||||||
|
|
||||||
if (statusChatEndId === '2' || statusChatEndId === '3') {
|
if (statusChatEndId === '2' || statusChatEndId === '3') {
|
||||||
|
|
||||||
console.log('Entrou! textArea1: ', textArea1)
|
|
||||||
|
|
||||||
if (startDate.trim().length === 0) {
|
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);
|
let sendMessageDayBefore = currenciesTimeBefore.filter(i => i.label.indexOf('24 HORAS ANTES DO HORÁRIO DO AGENDAMENTO') >= 0);
|
||||||
|
|
||||||
if (sendMessageDayBefore.length > 0 && timeBefore === formatedTimeHour(timerPicker)) {
|
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)))
|
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') {
|
} 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 hours = []
|
||||||
let hour = 1
|
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()) {
|
if (typeof (startDate) === 'string' && startDate.trim().length > 0 && startDate === dateCurrentFormated()) {
|
||||||
|
|
||||||
console.log('HOJE++++')
|
|
||||||
|
|
||||||
while (subHours(timer, hour).getHours() >= 6 &&
|
while (subHours(timer, hour).getHours() >= 6 &&
|
||||||
|
|
||||||
subHours(timer, hour).getHours() >= new Date().getHours() &&
|
subHours(timer, hour).getHours() >= new Date().getHours() &&
|
||||||
subHours(timer, hour).getHours() <= 20) {
|
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` })
|
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) {
|
if (hours.length > 1) {
|
||||||
console.log('entrou----------------------: ', hours.length)
|
|
||||||
hours.pop()
|
hours.pop()
|
||||||
setCurrency(hours[0].value)
|
setCurrency(hours[0].value)
|
||||||
}
|
}
|
||||||
|
@ -332,7 +332,7 @@ const Modal = (props) => {
|
||||||
|
|
||||||
while (subHours(timer, hour).getHours() >= 6 && subHours(timer, hour).getHours() <= 20) {
|
while (subHours(timer, hour).getHours() >= 6 && subHours(timer, hour).getHours() <= 20) {
|
||||||
|
|
||||||
console.log('******** another day TIMER: ', formatedTimeHour(subHours(timer, hour)))
|
|
||||||
|
|
||||||
hours.push(
|
hours.push(
|
||||||
{
|
{
|
||||||
|
@ -344,7 +344,7 @@ const Modal = (props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hours.length > 0) {
|
if (hours.length > 0) {
|
||||||
console.log('entrou----------------------: ', hours.length)
|
|
||||||
setCurrency(hours[0].value)
|
setCurrency(hours[0].value)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -358,18 +358,18 @@ const Modal = (props) => {
|
||||||
|
|
||||||
hours.push({ value: formatedTimeHour(timerPicker), label: `24 HORAS ANTES DO HORÁRIO DO AGENDAMENTO` })
|
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 }
|
return { time: hours, hour: hour }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('===================================== addDays: ', addDays(new Date(), 1))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -394,7 +394,7 @@ const Modal = (props) => {
|
||||||
|
|
||||||
// Get from child 1
|
// Get from child 1
|
||||||
const textFieldSelect = (data) => {
|
const textFieldSelect = (data) => {
|
||||||
console.log('textFieldSelect: ', data);
|
|
||||||
setStatusChatEnd(data)
|
setStatusChatEnd(data)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ const Modal = (props) => {
|
||||||
|
|
||||||
const handleCheckBoxChange = (event) => {
|
const handleCheckBoxChange = (event) => {
|
||||||
|
|
||||||
//console.log('event.target.checked: ', event.target.checked)
|
|
||||||
setChecked(event.target.checked);
|
setChecked(event.target.checked);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -416,11 +416,11 @@ const Modal = (props) => {
|
||||||
|
|
||||||
const handleChangeHourBefore = (event) => {
|
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);
|
// 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);
|
setCurrency(event.target.value);
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ import InputLabel from "@mui/material/InputLabel";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import FormControl from "@mui/material/FormControl";
|
import FormControl from "@mui/material/FormControl";
|
||||||
|
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
// import Tooltip from "@mui/material/Tooltip";
|
||||||
import Zoom from "@mui/material/Zoom";
|
// import Zoom from "@mui/material/Zoom";
|
||||||
|
|
||||||
import CancelIcon from "@material-ui/icons/Cancel";
|
import CancelIcon from "@material-ui/icons/Cancel";
|
||||||
import CheckCircleIcon from "@material-ui/icons/CheckCircle";
|
import CheckCircleIcon from "@material-ui/icons/CheckCircle";
|
||||||
|
|
|
@ -37,6 +37,10 @@ import { AuthContext } from "../../context/Auth/AuthContext";
|
||||||
import { useLocalStorage } from "../../hooks/useLocalStorage";
|
import { useLocalStorage } from "../../hooks/useLocalStorage";
|
||||||
import toastError from "../../errors/toastError";
|
import toastError from "../../errors/toastError";
|
||||||
|
|
||||||
|
// import TicketsManager from "../../components/TicketsManager/";
|
||||||
|
|
||||||
|
import { TabTicketContext } from "../../context/TabTicketHeaderOption/TabTicketHeaderOption";
|
||||||
|
|
||||||
const Mp3Recorder = new MicRecorder({ bitRate: 128 });
|
const Mp3Recorder = new MicRecorder({ bitRate: 128 });
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
|
@ -202,6 +206,9 @@ const useStyles = makeStyles((theme) => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const MessageInput = ({ ticketStatus }) => {
|
const MessageInput = ({ ticketStatus }) => {
|
||||||
|
|
||||||
|
const { tabOption, setTabOption } = useContext(TabTicketContext);
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const { ticketId } = useParams();
|
const { ticketId } = useParams();
|
||||||
|
|
||||||
|
@ -214,8 +221,7 @@ const MessageInput = ({ ticketStatus }) => {
|
||||||
const [typeBar, setTypeBar] = useState(false);
|
const [typeBar, setTypeBar] = useState(false);
|
||||||
const inputRef = useRef();
|
const inputRef = useRef();
|
||||||
const [anchorEl, setAnchorEl] = useState(null);
|
const [anchorEl, setAnchorEl] = useState(null);
|
||||||
const { setReplyingMessage, replyingMessage } =
|
const { setReplyingMessage, replyingMessage } = useContext(ReplyMessageContext);
|
||||||
useContext(ReplyMessageContext);
|
|
||||||
const { user } = useContext(AuthContext);
|
const { user } = useContext(AuthContext);
|
||||||
|
|
||||||
const [signMessage, setSignMessage] = useLocalStorage("signOption", true);
|
const [signMessage, setSignMessage] = useLocalStorage("signOption", true);
|
||||||
|
@ -268,6 +274,12 @@ const MessageInput = ({ ticketStatus }) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (tabOption === 'search') {
|
||||||
|
setTabOption('open')
|
||||||
|
}
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("fromMe", true);
|
formData.append("fromMe", true);
|
||||||
medias.forEach((media) => {
|
medias.forEach((media) => {
|
||||||
|
@ -288,6 +300,12 @@ const MessageInput = ({ ticketStatus }) => {
|
||||||
const handleSendMessage = async () => {
|
const handleSendMessage = async () => {
|
||||||
if (inputMessage.trim() === "") return;
|
if (inputMessage.trim() === "") return;
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (tabOption === 'search') {
|
||||||
|
setTabOption('open')
|
||||||
|
}
|
||||||
|
|
||||||
const message = {
|
const message = {
|
||||||
read: 1,
|
read: 1,
|
||||||
|
@ -310,7 +328,7 @@ const MessageInput = ({ ticketStatus }) => {
|
||||||
setReplyingMessage(null);
|
setReplyingMessage(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleStartRecording = async () => {
|
const handleStartRecording = async () => {
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
|
@ -346,6 +364,13 @@ const MessageInput = ({ ticketStatus }) => {
|
||||||
|
|
||||||
const handleUploadAudio = async () => {
|
const handleUploadAudio = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (tabOption === 'search') {
|
||||||
|
setTabOption('open')
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [, blob] = await Mp3Recorder.stop().getMp3();
|
const [, blob] = await Mp3Recorder.stop().getMp3();
|
||||||
if (blob.size < 10000) {
|
if (blob.size < 10000) {
|
||||||
|
|
|
@ -283,7 +283,7 @@ const reducer = (state, action) => {
|
||||||
state[messageIndex] = newMessage;
|
state[messageIndex] = newMessage;
|
||||||
} else {
|
} else {
|
||||||
state.push(newMessage);
|
state.push(newMessage);
|
||||||
// console.log(' TESTANDO NOVA MENSAGEM: ', newMessage)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...state];
|
return [...state];
|
||||||
|
@ -333,7 +333,7 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
try {
|
try {
|
||||||
const { data } = await api.get("/messages/" + ticketId, {
|
const { data } = await api.get("/messages/" + ticketId, {
|
||||||
params: { pageNumber },
|
params: { pageNumber },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (currentTicketId.current === ticketId) {
|
if (currentTicketId.current === ticketId) {
|
||||||
dispatch({ type: "LOAD_MESSAGES", payload: data.messages });
|
dispatch({ type: "LOAD_MESSAGES", payload: data.messages });
|
||||||
|
@ -362,17 +362,15 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
socket.on("connect", () => socket.emit("joinChatBox", ticketId));
|
socket.on("connect", () => socket.emit("joinChatBox", ticketId));
|
||||||
|
|
||||||
socket.on("appMessage", (data) => {
|
socket.on("appMessage", (data) => {
|
||||||
|
|
||||||
if (data.action === "create") {
|
if (data.action === "create") {
|
||||||
dispatch({ type: "ADD_MESSAGE", payload: data.message });
|
dispatch({ type: "ADD_MESSAGE", payload: data.message });
|
||||||
|
|
||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.action === "update") {
|
if (data.action === "update") {
|
||||||
|
|
||||||
console.log('2 THIS IS THE DATA: ', data)
|
|
||||||
|
|
||||||
dispatch({ type: "UPDATE_MESSAGE", payload: data.message });
|
dispatch({ type: "UPDATE_MESSAGE", payload: data.message });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -423,7 +421,7 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
return <ModalImageCors imageUrl={message.mediaUrl} />;
|
return <ModalImageCors imageUrl={message.mediaUrl} />;
|
||||||
}
|
}
|
||||||
if (message.mediaType === "audio") {
|
if (message.mediaType === "audio") {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<audio controls>
|
<audio controls>
|
||||||
<source src={message.mediaUrl} type="audio/ogg"></source>
|
<source src={message.mediaUrl} type="audio/ogg"></source>
|
||||||
|
@ -487,11 +485,13 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < messagesList.length - 1) {
|
if (index < messagesList.length - 1) {
|
||||||
let messageDay = parseISO(messagesList[index].createdAt);
|
let messageDay = parseISO(messagesList[index].createdAt);
|
||||||
let previousMessageDay = parseISO(messagesList[index - 1].createdAt);
|
let previousMessageDay = parseISO(messagesList[index - 1].createdAt);
|
||||||
|
|
||||||
if (!isSameDay(messageDay, previousMessageDay)) {
|
if (!isSameDay(messageDay, previousMessageDay)) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={classes.dailyTimestamp}
|
className={classes.dailyTimestamp}
|
||||||
|
@ -504,13 +504,30 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index === messagesList.length - 1) {
|
if (index === messagesList.length - 1) {
|
||||||
|
|
||||||
|
let messageDay = parseISO(messagesList[index].createdAt);
|
||||||
|
let previousMessageDay = parseISO(messagesList[index - 1].createdAt);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<>
|
||||||
key={`ref-${message.createdAt}`}
|
{!isSameDay(messageDay, previousMessageDay) &&
|
||||||
ref={lastMessageRef}
|
<span
|
||||||
style={{ float: "left", clear: "both" }}
|
className={classes.dailyTimestamp}
|
||||||
/>
|
key={`timestamp-${message.id}`}
|
||||||
|
>
|
||||||
|
<div className={classes.dailyTimestampText}>
|
||||||
|
{format(parseISO(messagesList[index].createdAt), "dd/MM/yyyy")}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
<div
|
||||||
|
key={`ref-${message.createdAt}`}
|
||||||
|
ref={lastMessageRef}
|
||||||
|
style={{ float: "left", clear: "both" }}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -63,14 +63,14 @@ const NotificationsPopOver = () => {
|
||||||
|
|
||||||
// const [lastRef] = useState(+history.location.pathname.split("/")[2])
|
// const [lastRef] = useState(+history.location.pathname.split("/")[2])
|
||||||
|
|
||||||
// console.log('ticketIdRef: ',ticketIdRef, ' | lastRef: ',lastRef)
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
soundAlertRef.current = play;
|
soundAlertRef.current = play;
|
||||||
|
|
||||||
if (!("Notification" in window)) {
|
if (!("Notification" in window)) {
|
||||||
console.log("This browser doesn't support notifications");
|
|
||||||
} else {
|
} else {
|
||||||
Notification.requestPermission();
|
Notification.requestPermission();
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ const NotificationsPopOver = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
// console.log('888888888888888888888888888888888888888888888888888888888888888888')
|
|
||||||
|
|
||||||
ticketIdRef.current = ticketIdUrl;
|
ticketIdRef.current = ticketIdUrl;
|
||||||
}, [ticketIdUrl]);
|
}, [ticketIdUrl]);
|
||||||
|
@ -97,7 +97,7 @@ const NotificationsPopOver = () => {
|
||||||
|
|
||||||
if(data.action === "logout"){
|
if(data.action === "logout"){
|
||||||
|
|
||||||
console.log('___________data.userId: ', data.userOnlineTime['status'])
|
|
||||||
|
|
||||||
if(`${user.id}` === data.userOnlineTime['userId']){
|
if(`${user.id}` === data.userOnlineTime['userId']){
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ const NotificationsPopOver = () => {
|
||||||
|
|
||||||
socket.on("isOnline", (data) => {
|
socket.on("isOnline", (data) => {
|
||||||
|
|
||||||
// console.log('___________data.userId: ', data.userId)
|
|
||||||
|
|
||||||
if(data.action === "online"){
|
if(data.action === "online"){
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ const NotificationsPopOver = () => {
|
||||||
|
|
||||||
socket.on("appMessage", data => {
|
socket.on("appMessage", data => {
|
||||||
|
|
||||||
// console.log('******************* DATA: ', data)
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
data.action === "create" &&
|
data.action === "create" &&
|
||||||
|
@ -177,24 +177,24 @@ const NotificationsPopOver = () => {
|
||||||
(data.ticket.userId === user?.id || !data.ticket.userId)
|
(data.ticket.userId === user?.id || !data.ticket.userId)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// console.log('entrou.............')
|
|
||||||
|
|
||||||
|
|
||||||
setNotifications(prevState => {
|
setNotifications(prevState => {
|
||||||
|
|
||||||
// console.log('prevState: ', prevState)
|
|
||||||
|
|
||||||
// prevState.forEach((e)=>{
|
// prevState.forEach((e)=>{
|
||||||
// console.log(`>>> e.id: ${e.id} | data.ticket.Id: ${data.ticket.id}`)
|
//
|
||||||
// })
|
// })
|
||||||
|
|
||||||
const ticketIndex = prevState.findIndex(t => t.id === data.ticket.id);
|
const ticketIndex = prevState.findIndex(t => t.id === data.ticket.id);
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
// console.log(` data.ticket 1 `)
|
|
||||||
prevState[ticketIndex] = data.ticket;
|
prevState[ticketIndex] = data.ticket;
|
||||||
return [...prevState];
|
return [...prevState];
|
||||||
}
|
}
|
||||||
// console.log(` data.ticket 2 `)
|
|
||||||
return [data.ticket, ...prevState];
|
return [data.ticket, ...prevState];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ const NotificationsPopOver = () => {
|
||||||
|
|
||||||
if (shouldNotNotificate) return;
|
if (shouldNotNotificate) return;
|
||||||
|
|
||||||
//console.log('PASSOU!!!!!!!')
|
|
||||||
|
|
||||||
handleNotifications(data);
|
handleNotifications(data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ const MTable = (props) => {
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
|
|
||||||
// console.log(`You have clicked the button ${selectedRow} times`)
|
//
|
||||||
|
|
||||||
// }, [selectedRow]);
|
// }, [selectedRow]);
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ useEffect(()=>{
|
||||||
|
|
||||||
setCurrency( event.target.value)
|
setCurrency( event.target.value)
|
||||||
|
|
||||||
console.log('event.target.value: ', event.target.value)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
const TabPanel = ({ children, value, name, ...rest }) => {
|
const TabPanel = ({ children, value, name, ...rest }) => {
|
||||||
|
|
||||||
|
|
||||||
if (value === name) {
|
if (value === name) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -15,6 +15,8 @@ import { AuthContext } from "../../context/Auth/AuthContext";
|
||||||
import Modal from "../ChatEnd/ModalChatEnd";
|
import Modal from "../ChatEnd/ModalChatEnd";
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { TabTicketContext } from "../../context/TabTicketHeaderOption/TabTicketHeaderOption";
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
actionButtons: {
|
actionButtons: {
|
||||||
marginRight: 6,
|
marginRight: 6,
|
||||||
|
@ -34,6 +36,8 @@ const TicketActionButtons = ({ ticket, statusChatEnd }) => {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const ticketOptionsMenuOpen = Boolean(anchorEl);
|
const ticketOptionsMenuOpen = Boolean(anchorEl);
|
||||||
const { user } = useContext(AuthContext);
|
const { user } = useContext(AuthContext);
|
||||||
|
|
||||||
|
const { tabOption, setTabOption } = useContext(TabTicketContext);
|
||||||
|
|
||||||
const handleOpenTicketOptionsMenu = e => {
|
const handleOpenTicketOptionsMenu = e => {
|
||||||
setAnchorEl(e.currentTarget);
|
setAnchorEl(e.currentTarget);
|
||||||
|
@ -50,7 +54,7 @@ const TicketActionButtons = ({ ticket, statusChatEnd }) => {
|
||||||
|
|
||||||
data = {...data, 'ticketId': ticket.id}
|
data = {...data, 'ticketId': ticket.id}
|
||||||
|
|
||||||
console.log('ChatEnd: ',(data));
|
|
||||||
|
|
||||||
handleUpdateTicketStatus(null, "closed", user?.id, data)
|
handleUpdateTicketStatus(null, "closed", user?.id, data)
|
||||||
|
|
||||||
|
@ -78,6 +82,10 @@ const TicketActionButtons = ({ ticket, statusChatEnd }) => {
|
||||||
|
|
||||||
if(status==='closed'){
|
if(status==='closed'){
|
||||||
|
|
||||||
|
if (tabOption === 'search') {
|
||||||
|
setTabOption('open')
|
||||||
|
}
|
||||||
|
|
||||||
await api.put(`/tickets/${ticket.id}`, {
|
await api.put(`/tickets/${ticket.id}`, {
|
||||||
status: status,
|
status: status,
|
||||||
userId: userId || null,
|
userId: userId || null,
|
||||||
|
@ -86,6 +94,10 @@ const TicketActionButtons = ({ ticket, statusChatEnd }) => {
|
||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
||||||
|
if (tabOption === 'search') {
|
||||||
|
setTabOption('open')
|
||||||
|
}
|
||||||
|
|
||||||
await api.put(`/tickets/${ticket.id}`, {
|
await api.put(`/tickets/${ticket.id}`, {
|
||||||
status: status,
|
status: status,
|
||||||
|
@ -96,6 +108,8 @@ const TicketActionButtons = ({ ticket, statusChatEnd }) => {
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
if (status === "open") {
|
if (status === "open") {
|
||||||
|
|
||||||
|
|
||||||
history.push(`/tickets/${ticket.id}`);
|
history.push(`/tickets/${ticket.id}`);
|
||||||
} else {
|
} else {
|
||||||
history.push("/tickets");
|
history.push("/tickets");
|
||||||
|
@ -124,7 +138,7 @@ const TicketActionButtons = ({ ticket, statusChatEnd }) => {
|
||||||
)}
|
)}
|
||||||
{ticket.status === "open" && (
|
{ticket.status === "open" && (
|
||||||
<>
|
<>
|
||||||
<ButtonWithSpinner
|
<ButtonWithSpinner style={{ marginRight: "70px" }}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
startIcon={<Replay />}
|
startIcon={<Replay />}
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -132,14 +146,14 @@ const TicketActionButtons = ({ ticket, statusChatEnd }) => {
|
||||||
>
|
>
|
||||||
{i18n.t("messagesList.header.buttons.return")}
|
{i18n.t("messagesList.header.buttons.return")}
|
||||||
</ButtonWithSpinner>
|
</ButtonWithSpinner>
|
||||||
|
|
||||||
<ButtonWithSpinner
|
<ButtonWithSpinner
|
||||||
loading={loading}
|
loading={loading}
|
||||||
size="small"
|
size="small"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
|
|
||||||
|
|
||||||
handleModal()
|
handleModal()
|
||||||
// handleUpdateTicketStatus(e, "closed", user?.id)
|
// handleUpdateTicketStatus(e, "closed", user?.id)
|
||||||
|
|
|
@ -118,6 +118,7 @@ const TicketListItem = ({ ticket }) => {
|
||||||
const handleAcepptTicket = async id => {
|
const handleAcepptTicket = async id => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
await api.put(`/tickets/${id}`, {
|
await api.put(`/tickets/${id}`, {
|
||||||
status: "open",
|
status: "open",
|
||||||
userId: user?.id,
|
userId: user?.id,
|
||||||
|
@ -129,6 +130,9 @@ const TicketListItem = ({ ticket }) => {
|
||||||
if (isMounted.current) {
|
if (isMounted.current) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
history.push(`/tickets/${id}`);
|
history.push(`/tickets/${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -216,7 +220,7 @@ const TicketListItem = ({ ticket }) => {
|
||||||
|
|
||||||
<Badge
|
<Badge
|
||||||
className={classes.newMessagesCount}
|
className={classes.newMessagesCount}
|
||||||
badgeContent={ticket.unreadMessages}
|
badgeContent={+ticket.unreadMessages}
|
||||||
classes={{
|
classes={{
|
||||||
badge: classes.badgeStyle,
|
badge: classes.badgeStyle,
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -10,8 +10,9 @@ import TicketsListSkeleton from "../TicketsListSkeleton";
|
||||||
|
|
||||||
import useTickets from "../../hooks/useTickets";
|
import useTickets from "../../hooks/useTickets";
|
||||||
import { i18n } from "../../translate/i18n";
|
import { i18n } from "../../translate/i18n";
|
||||||
import { AuthContext } from "../../context/Auth/AuthContext";
|
import { AuthContext } from "../../context/Auth/AuthContext";
|
||||||
|
|
||||||
|
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket";
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
ticketsListWrapper: {
|
ticketsListWrapper: {
|
||||||
|
@ -79,12 +80,10 @@ const reducer = (state, action) => {
|
||||||
|
|
||||||
newTickets.forEach(ticket => {
|
newTickets.forEach(ticket => {
|
||||||
|
|
||||||
// console.log('* ticket.unreadMessages: ',ticket.unreadMessages)
|
const ticketIndex = state.findIndex(t => +t.id === +ticket.id);
|
||||||
|
|
||||||
const ticketIndex = state.findIndex(t => t.id === ticket.id);
|
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
state[ticketIndex] = ticket;
|
state[ticketIndex] = ticket;
|
||||||
if (ticket.unreadMessages > 0) {
|
if (+ticket.unreadMessages > 0) {
|
||||||
state.unshift(state.splice(ticketIndex, 1)[0]);
|
state.unshift(state.splice(ticketIndex, 1)[0]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -98,7 +97,10 @@ const reducer = (state, action) => {
|
||||||
if (action.type === "RESET_UNREAD") {
|
if (action.type === "RESET_UNREAD") {
|
||||||
const ticketId = action.payload;
|
const ticketId = action.payload;
|
||||||
|
|
||||||
const ticketIndex = state.findIndex(t => t.id === ticketId);
|
const ticketIndex = state.findIndex(t => +t.id === +ticketId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
state[ticketIndex].unreadMessages = 0;
|
state[ticketIndex].unreadMessages = 0;
|
||||||
}
|
}
|
||||||
|
@ -109,9 +111,8 @@ const reducer = (state, action) => {
|
||||||
if (action.type === "UPDATE_TICKET") {
|
if (action.type === "UPDATE_TICKET") {
|
||||||
const ticket = action.payload;
|
const ticket = action.payload;
|
||||||
|
|
||||||
// console.log('++++++++++++ UPDATE_TICKET: ',ticket)
|
const ticketIndex = state.findIndex(t => +t.id === +ticket.id);
|
||||||
|
|
||||||
const ticketIndex = state.findIndex(t => t.id === ticket.id);
|
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
state[ticketIndex] = ticket;
|
state[ticketIndex] = ticket;
|
||||||
} else {
|
} else {
|
||||||
|
@ -127,13 +128,13 @@ const reducer = (state, action) => {
|
||||||
|
|
||||||
const ticket = action.payload.ticket;
|
const ticket = action.payload.ticket;
|
||||||
|
|
||||||
const ticketIndex = state.findIndex(t => t.id === ticket.id);
|
const ticketIndex = state.findIndex(t => +t.id === +ticket.id);
|
||||||
|
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
|
|
||||||
// console.log('>>>>>> ticketIndex: ', ticketIndex)
|
|
||||||
|
|
||||||
// console.log('&&&&&&& UPDATE_TICKET_UNREAD_MESSAGES ticket: ',ticket, ' |\n MESSAGE: ', message)
|
|
||||||
|
|
||||||
|
|
||||||
if (!message.fromMe) {
|
if (!message.fromMe) {
|
||||||
ticket.unreadMessages += 1
|
ticket.unreadMessages += 1
|
||||||
|
@ -151,7 +152,7 @@ const reducer = (state, action) => {
|
||||||
|
|
||||||
if (action.type === "UPDATE_TICKET_CONTACT") {
|
if (action.type === "UPDATE_TICKET_CONTACT") {
|
||||||
const contact = action.payload;
|
const contact = action.payload;
|
||||||
const ticketIndex = state.findIndex(t => t.contactId === contact.id);
|
const ticketIndex = state.findIndex(t => +t.contactId === +contact.id);
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
state[ticketIndex].contact = contact;
|
state[ticketIndex].contact = contact;
|
||||||
}
|
}
|
||||||
|
@ -160,7 +161,7 @@ const reducer = (state, action) => {
|
||||||
|
|
||||||
if (action.type === "DELETE_TICKET") {
|
if (action.type === "DELETE_TICKET") {
|
||||||
const ticketId = action.payload;
|
const ticketId = action.payload;
|
||||||
const ticketIndex = state.findIndex(t => t.id === ticketId);
|
const ticketIndex = state.findIndex(t => +t.id === +ticketId);
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
state.splice(ticketIndex, 1);
|
state.splice(ticketIndex, 1);
|
||||||
}
|
}
|
||||||
|
@ -174,16 +175,21 @@ const reducer = (state, action) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const TicketsList = (props) => {
|
const TicketsList = (props) => {
|
||||||
const { status, searchParam, showAll, selectedQueueIds, updateCount, style } = props;
|
const { status, searchParam, showAll, selectedQueueIds, updateCount, style, tab } = props;
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [pageNumber, setPageNumber] = useState(1);
|
const [pageNumber, setPageNumber] = useState(1);
|
||||||
const [ticketsList, dispatch] = useReducer(reducer, []);
|
const [ticketsList, dispatch] = useReducer(reducer, []);
|
||||||
const { user } = useContext(AuthContext);
|
const { user } = useContext(AuthContext);
|
||||||
|
|
||||||
|
const { searchTicket } = useContext(SearchTicketContext)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch({ type: "RESET" });
|
dispatch({ type: "RESET" });
|
||||||
setPageNumber(1);
|
setPageNumber(1);
|
||||||
}, [status, searchParam, dispatch, showAll, selectedQueueIds]);
|
|
||||||
|
}, [status, searchParam, showAll, selectedQueueIds, searchTicket]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const { tickets, hasMore, loading } = useTickets({
|
const { tickets, hasMore, loading } = useTickets({
|
||||||
pageNumber,
|
pageNumber,
|
||||||
|
@ -191,20 +197,31 @@ const TicketsList = (props) => {
|
||||||
status,
|
status,
|
||||||
showAll,
|
showAll,
|
||||||
queueIds: JSON.stringify(selectedQueueIds),
|
queueIds: JSON.stringify(selectedQueueIds),
|
||||||
|
tab
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!status && !searchParam) return;
|
if (!status && !searchParam) return;
|
||||||
|
|
||||||
// console.log('lllllllllllllllllllllllllllllllll')
|
// if (searchParam) {
|
||||||
|
//
|
||||||
|
// dispatch({ type: "RESET" });
|
||||||
|
// }
|
||||||
|
|
||||||
dispatch({
|
if ((searchParam && searchParam.trim().length > 0) &&
|
||||||
type: "LOAD_TICKETS",
|
(tickets && tickets.length === 0) &&
|
||||||
payload: tickets,
|
pageNumber === 1) {
|
||||||
});
|
dispatch({ type: "RESET" })
|
||||||
}, [tickets, status, searchParam]);
|
}
|
||||||
|
|
||||||
|
dispatch({ type: "LOAD_TICKETS", payload: tickets, });
|
||||||
|
|
||||||
|
}, [tickets, status, searchParam, pageNumber]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
// 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 =>
|
const shouldUpdateTicket = ticket =>
|
||||||
|
@ -223,9 +240,14 @@ const TicketsList = (props) => {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("ticket", data => {
|
|
||||||
|
|
||||||
|
socket.on("ticket", data => {
|
||||||
|
|
||||||
if (data.action === "updateUnread") {
|
if (data.action === "updateUnread") {
|
||||||
|
|
||||||
|
if (tab === 'search' && data.ticket && data.ticket.status === 'pending') return
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "RESET_UNREAD",
|
type: "RESET_UNREAD",
|
||||||
payload: data.ticketId,
|
payload: data.ticketId,
|
||||||
|
@ -233,6 +255,9 @@ const TicketsList = (props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.action === "update" && shouldUpdateTicket(data.ticket)) {
|
if (data.action === "update" && shouldUpdateTicket(data.ticket)) {
|
||||||
|
|
||||||
|
if (tab === 'search' && data.ticket && (data.ticket.status === 'pending' || data.ticket.status === 'closed')) return
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "UPDATE_TICKET",
|
type: "UPDATE_TICKET",
|
||||||
payload: data.ticket,
|
payload: data.ticket,
|
||||||
|
@ -245,13 +270,15 @@ const TicketsList = (props) => {
|
||||||
|
|
||||||
if (data.action === "delete") {
|
if (data.action === "delete") {
|
||||||
dispatch({ type: "DELETE_TICKET", payload: data.ticketId });
|
dispatch({ type: "DELETE_TICKET", payload: data.ticketId });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
socket.on("appMessage", data => {
|
socket.on("appMessage", data => {
|
||||||
if (data.action === "create" && shouldUpdateTicket(data.ticket)) {
|
if (data.action === "create" && shouldUpdateTicket(data.ticket)) {
|
||||||
|
|
||||||
// console.log('((((((((((((((((((( DATA.MESSAGE: ', data.message)
|
|
||||||
|
if (tab === 'search') return
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "UPDATE_TICKET_UNREAD_MESSAGES",
|
type: "UPDATE_TICKET_UNREAD_MESSAGES",
|
||||||
|
@ -273,7 +300,7 @@ const TicketsList = (props) => {
|
||||||
return () => {
|
return () => {
|
||||||
socket.disconnect();
|
socket.disconnect();
|
||||||
};
|
};
|
||||||
}, [status, showAll, user, selectedQueueIds]);
|
}, [status, showAll, user, selectedQueueIds, tab]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
@ -296,6 +323,9 @@ const TicketsList = (props) => {
|
||||||
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
|
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
|
||||||
|
|
||||||
if (scrollHeight - (scrollTop + 100) < clientHeight) {
|
if (scrollHeight - (scrollTop + 100) < clientHeight) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
loadMore();
|
loadMore();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,6 +23,10 @@ import { Can } from "../Can";
|
||||||
import TicketsQueueSelect from "../TicketsQueueSelect";
|
import TicketsQueueSelect from "../TicketsQueueSelect";
|
||||||
import { Button } from "@material-ui/core";
|
import { Button } from "@material-ui/core";
|
||||||
|
|
||||||
|
import { TabTicketContext } from "../../context/TabTicketHeaderOption/TabTicketHeaderOption";
|
||||||
|
|
||||||
|
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
ticketsWrapper: {
|
ticketsWrapper: {
|
||||||
position: "relative",
|
position: "relative",
|
||||||
|
@ -92,6 +96,11 @@ const useStyles = makeStyles((theme) => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const TicketsManager = () => {
|
const TicketsManager = () => {
|
||||||
|
|
||||||
|
const { tabOption, setTabOption } = useContext(TabTicketContext);
|
||||||
|
|
||||||
|
const {setSearchTicket} = useContext(SearchTicketContext)
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
const [searchParam, setSearchParam] = useState("");
|
const [searchParam, setSearchParam] = useState("");
|
||||||
|
@ -108,6 +117,8 @@ const TicketsManager = () => {
|
||||||
const userQueueIds = user.queues.map((q) => q.id);
|
const userQueueIds = user.queues.map((q) => q.id);
|
||||||
const [selectedQueueIds, setSelectedQueueIds] = useState(userQueueIds || []);
|
const [selectedQueueIds, setSelectedQueueIds] = useState(userQueueIds || []);
|
||||||
|
|
||||||
|
const [inputSearch, setInputSearch] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user.profile.toUpperCase() === "ADMIN") {
|
if (user.profile.toUpperCase() === "ADMIN") {
|
||||||
setShowAllTickets(true);
|
setShowAllTickets(true);
|
||||||
|
@ -119,25 +130,55 @@ const TicketsManager = () => {
|
||||||
if (tab === "search") {
|
if (tab === "search") {
|
||||||
searchInputRef.current.focus();
|
searchInputRef.current.focus();
|
||||||
}
|
}
|
||||||
}, [tab]);
|
|
||||||
|
setTabOption(tab)
|
||||||
|
|
||||||
|
}, [tab, setTabOption]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
|
||||||
|
if (tabOption === 'open') {
|
||||||
|
|
||||||
|
setTabOption('')
|
||||||
|
setSearchParam('');
|
||||||
|
setInputSearch('');
|
||||||
|
setTab("open");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [tabOption, setTabOption])
|
||||||
|
|
||||||
let searchTimeout;
|
let searchTimeout;
|
||||||
|
|
||||||
|
const removeExtraSpace = (str) => {
|
||||||
|
|
||||||
|
str = str.replace(/^\s+/g, '')
|
||||||
|
|
||||||
|
return str.replace(/\s+/g, ' ')
|
||||||
|
}
|
||||||
|
|
||||||
const handleSearch = (e) => {
|
const handleSearch = (e) => {
|
||||||
let searchedTerm = e.target.value.toLowerCase()
|
let searchedTerm = e.target.value.toLowerCase()
|
||||||
|
|
||||||
|
setInputSearch(removeExtraSpace(searchedTerm))
|
||||||
|
|
||||||
|
setSearchTicket(searchParam)
|
||||||
|
|
||||||
clearTimeout(searchTimeout);
|
clearTimeout(searchTimeout);
|
||||||
|
|
||||||
if (searchedTerm === "") {
|
if (searchedTerm === "") {
|
||||||
setSearchParam(searchedTerm);
|
setSearchParam(searchedTerm);
|
||||||
|
setInputSearch(searchedTerm)
|
||||||
setTab("open");
|
setTab("open");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
searchTimeout = setTimeout(() => {
|
searchTimeout = setTimeout(() => {
|
||||||
|
|
||||||
setSearchParam(searchedTerm);
|
setSearchParam(searchedTerm);
|
||||||
}, 1000);
|
|
||||||
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleChangeTab = (e, newValue) => {
|
const handleChangeTab = (e, newValue) => {
|
||||||
|
@ -197,7 +238,8 @@ const TicketsManager = () => {
|
||||||
className={classes.searchInput}
|
className={classes.searchInput}
|
||||||
inputRef={searchInputRef}
|
inputRef={searchInputRef}
|
||||||
placeholder={i18n.t("tickets.search.placeholder")}
|
placeholder={i18n.t("tickets.search.placeholder")}
|
||||||
type="search"
|
type="search"
|
||||||
|
value={inputSearch}
|
||||||
onChange={handleSearch}
|
onChange={handleSearch}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -286,7 +328,7 @@ const TicketsManager = () => {
|
||||||
selectedQueueIds={selectedQueueIds}
|
selectedQueueIds={selectedQueueIds}
|
||||||
updateCount={(val) => setPendingCount(val)}
|
updateCount={(val) => setPendingCount(val)}
|
||||||
style={applyPanelStyle("pending")}
|
style={applyPanelStyle("pending")}
|
||||||
/>
|
/>
|
||||||
</Paper>
|
</Paper>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel value={tab} name="closed" className={classes.ticketsWrapper}>
|
<TabPanel value={tab} name="closed" className={classes.ticketsWrapper}>
|
||||||
|
@ -297,11 +339,15 @@ const TicketsManager = () => {
|
||||||
/>
|
/>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel value={tab} name="search" className={classes.ticketsWrapper}>
|
<TabPanel value={tab} name="search" className={classes.ticketsWrapper}>
|
||||||
<TicketsList
|
|
||||||
searchParam={searchParam}
|
|
||||||
showAll={true}
|
<TicketsList
|
||||||
selectedQueueIds={selectedQueueIds}
|
searchParam={searchParam}
|
||||||
/>
|
tab={tab}
|
||||||
|
showAll={true}
|
||||||
|
selectedQueueIds={selectedQueueIds}
|
||||||
|
/>
|
||||||
|
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</Paper>
|
</Paper>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,7 +7,7 @@ const AuthContext = createContext();
|
||||||
const AuthProvider = ({ children }) => {
|
const AuthProvider = ({ children }) => {
|
||||||
const { loading, user, isAuth, handleLogin, handleLogout } = useAuth();
|
const { loading, user, isAuth, handleLogin, handleLogout } = useAuth();
|
||||||
|
|
||||||
//{console.log('authContext teste: ', user)}
|
//{
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthContext.Provider
|
<AuthContext.Provider
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import React, { useState, createContext } from "react";
|
||||||
|
|
||||||
|
const SearchTicketContext = createContext();
|
||||||
|
|
||||||
|
|
||||||
|
const SearchTicketProvider = ({ children }) => {
|
||||||
|
|
||||||
|
const [searchTicket, setSearchTicket] = useState(0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SearchTicketContext.Provider value={{ searchTicket, setSearchTicket }}>
|
||||||
|
{children}
|
||||||
|
</SearchTicketContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { SearchTicketContext, SearchTicketProvider };
|
|
@ -0,0 +1,33 @@
|
||||||
|
import React, { useState, createContext } from "react";
|
||||||
|
|
||||||
|
// export const TabTicketContext = createContext();
|
||||||
|
|
||||||
|
const TabTicketContext = createContext();
|
||||||
|
|
||||||
|
|
||||||
|
// export const TabTicketProvider= ({ children }) => {
|
||||||
|
|
||||||
|
// const [tabOption, setTabOption] = useState(0);
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <TabTicketContext.Provider value={{ tabOption, setTabOption }}>
|
||||||
|
// {children}
|
||||||
|
// </TabTicketContext.Provider>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const TabTicketProvider = ({ children }) => {
|
||||||
|
|
||||||
|
const [tabOption, setTabOption] = useState(0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TabTicketContext.Provider value={{ tabOption, setTabOption }}>
|
||||||
|
{children}
|
||||||
|
</TabTicketContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { TabTicketContext, TabTicketProvider };
|
|
@ -11,23 +11,26 @@ const useTickets = ({
|
||||||
showAll,
|
showAll,
|
||||||
queueIds,
|
queueIds,
|
||||||
withUnreadMessages,
|
withUnreadMessages,
|
||||||
unlimited
|
unlimited,
|
||||||
|
tab
|
||||||
}) => {
|
}) => {
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [hasMore, setHasMore] = useState(false);
|
const [hasMore, setHasMore] = useState(false);
|
||||||
const [tickets, setTickets] = useState([]);
|
const [tickets, setTickets] = useState([]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const delayDebounceFn = setTimeout(() => {
|
const delayDebounceFn = setTimeout(() => {
|
||||||
const fetchTickets = async () => {
|
const fetchTickets = async () => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if(searchParam){
|
if ((tab === 'search') && ( !searchParam || searchParam.trim().length === 0 || searchParam.trim().length >40 || searchParam.endsWith(' '))) {
|
||||||
console.log('searchParam: ', searchParam)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const { data } = await api.get("/tickets", {
|
const { data } = await api.get("/tickets", {
|
||||||
params: {
|
params: {
|
||||||
|
@ -40,15 +43,16 @@ const useTickets = ({
|
||||||
withUnreadMessages,
|
withUnreadMessages,
|
||||||
unlimited
|
unlimited
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
console.log('data.tickets: ', data.tickets)
|
|
||||||
// console.log('data.hasMore: ', data.hasMore)
|
|
||||||
|
|
||||||
setTickets(data.tickets);
|
setTickets(data.tickets);
|
||||||
setHasMore(data.hasMore);
|
setHasMore(data.hasMore);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
toastError(err);
|
toastError(err);
|
||||||
|
@ -65,7 +69,7 @@ const useTickets = ({
|
||||||
showAll,
|
showAll,
|
||||||
queueIds,
|
queueIds,
|
||||||
withUnreadMessages,
|
withUnreadMessages,
|
||||||
|
tab,
|
||||||
unlimited
|
unlimited
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ const useWhatsApps = () => {
|
||||||
socket.on("whatsappSessionMonit", data => {
|
socket.on("whatsappSessionMonit", data => {
|
||||||
if (data.action === "update") {
|
if (data.action === "update") {
|
||||||
|
|
||||||
// console.log('data.whatsappSessionSize: ', data.whatsappSessionSize)
|
|
||||||
|
|
||||||
dispatch({ type: "UPDATE_WHATSAPPS_SESSION_MONIT", payload: data.whatsappSessionSize });
|
dispatch({ type: "UPDATE_WHATSAPPS_SESSION_MONIT", payload: data.whatsappSessionSize });
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ function ListItemLink(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const MainListItems = (props) => {
|
const MainListItems = (props) => {
|
||||||
const { drawerClose, setDrawerOpen, drawerOpen } = props;
|
const { setDrawerOpen } = props;
|
||||||
const { whatsApps } = useContext(WhatsAppsContext);
|
const { whatsApps } = useContext(WhatsAppsContext);
|
||||||
const { user } = useContext(AuthContext);
|
const { user } = useContext(AuthContext);
|
||||||
const [connectionWarning, setConnectionWarning] = useState(false);
|
const [connectionWarning, setConnectionWarning] = useState(false);
|
||||||
|
|
|
@ -44,9 +44,9 @@ const reducer = (state, action) => {
|
||||||
const newContacts = [];
|
const newContacts = [];
|
||||||
|
|
||||||
contacts.forEach((contact) => {
|
contacts.forEach((contact) => {
|
||||||
|
|
||||||
const contactIndex = state.findIndex((c) => c.id === contact.id);
|
const contactIndex = state.findIndex((c) => +c.id === +contact.id);
|
||||||
|
|
||||||
if (contactIndex !== -1) {
|
if (contactIndex !== -1) {
|
||||||
state[contactIndex] = contact;
|
state[contactIndex] = contact;
|
||||||
} else {
|
} else {
|
||||||
|
@ -60,7 +60,7 @@ const reducer = (state, action) => {
|
||||||
|
|
||||||
if (action.type === "UPDATE_CONTACTS") {
|
if (action.type === "UPDATE_CONTACTS") {
|
||||||
const contact = action.payload;
|
const contact = action.payload;
|
||||||
const contactIndex = state.findIndex((c) => c.id === contact.id);
|
const contactIndex = state.findIndex((c) => +c.id === +contact.id);
|
||||||
|
|
||||||
if (contactIndex !== -1) {
|
if (contactIndex !== -1) {
|
||||||
state[contactIndex] = contact;
|
state[contactIndex] = contact;
|
||||||
|
@ -73,7 +73,7 @@ const reducer = (state, action) => {
|
||||||
if (action.type === "DELETE_CONTACT") {
|
if (action.type === "DELETE_CONTACT") {
|
||||||
const contactId = action.payload;
|
const contactId = action.payload;
|
||||||
|
|
||||||
const contactIndex = state.findIndex((c) => c.id === contactId);
|
const contactIndex = state.findIndex((c) => +c.id === +contactId);
|
||||||
if (contactIndex !== -1) {
|
if (contactIndex !== -1) {
|
||||||
state.splice(contactIndex, 1);
|
state.splice(contactIndex, 1);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ const Contacts = () => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const { user } = useContext(AuthContext);
|
const { user } = useContext(AuthContext);
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [pageNumber, setPageNumber] = useState(1);
|
const [pageNumber, setPageNumber] = useState(1);
|
||||||
|
@ -110,25 +110,46 @@ const Contacts = () => {
|
||||||
const [confirmOpen, setConfirmOpen] = useState(false);
|
const [confirmOpen, setConfirmOpen] = useState(false);
|
||||||
const [hasMore, setHasMore] = useState(false);
|
const [hasMore, setHasMore] = useState(false);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch({ type: "RESET" });
|
dispatch({ type: "RESET" });
|
||||||
setPageNumber(1);
|
setPageNumber(1);
|
||||||
}, [searchParam]);
|
}, [searchParam]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
|
||||||
|
if (searchParam.trim().length > 0 && searchParam.endsWith(' ')) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const delayDebounceFn = setTimeout(() => {
|
const delayDebounceFn = setTimeout(() => {
|
||||||
const fetchContacts = async () => {
|
const fetchContacts = async () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { data } = await api.get("/contacts/", {
|
|
||||||
params: { searchParam, pageNumber },
|
if (searchParam.trim().length > 40) {
|
||||||
});
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await api.get("/contacts/", { params: { searchParam, pageNumber }, });
|
||||||
|
|
||||||
|
|
||||||
dispatch({ type: "LOAD_CONTACTS", payload: data.contacts });
|
dispatch({ type: "LOAD_CONTACTS", payload: data.contacts });
|
||||||
setHasMore(data.hasMore);
|
setHasMore(data.hasMore);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toastError(err);
|
toastError(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
fetchContacts();
|
fetchContacts();
|
||||||
}, 500);
|
}, 500);
|
||||||
|
@ -153,8 +174,15 @@ const Contacts = () => {
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const removeExtraSpace = (str) => {
|
||||||
|
|
||||||
|
str = str.replace(/^\s+/g, '')
|
||||||
|
|
||||||
|
return str.replace(/\s+/g, ' ')
|
||||||
|
}
|
||||||
|
|
||||||
const handleSearch = (event) => {
|
const handleSearch = (event) => {
|
||||||
setSearchParam(event.target.value.toLowerCase());
|
setSearchParam(removeExtraSpace(event.target.value.toLowerCase()));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOpenContactModal = () => {
|
const handleOpenContactModal = () => {
|
||||||
|
@ -217,7 +245,7 @@ const Contacts = () => {
|
||||||
if (!hasMore || loading) return;
|
if (!hasMore || loading) return;
|
||||||
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
|
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
|
||||||
|
|
||||||
// console.log('scrollTop: ', scrollTop, ' | scrollHeight: ', scrollHeight, ' | clientHeight: ', clientHeight)
|
|
||||||
|
|
||||||
if (scrollHeight - (scrollTop + 100) < clientHeight) {
|
if (scrollHeight - (scrollTop + 100) < clientHeight) {
|
||||||
loadMore();
|
loadMore();
|
||||||
|
@ -235,9 +263,8 @@ const Contacts = () => {
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
title={
|
title={
|
||||||
deletingContact
|
deletingContact
|
||||||
? `${i18n.t("contacts.confirmationModal.deleteTitle")} ${
|
? `${i18n.t("contacts.confirmationModal.deleteTitle")} ${deletingContact.name
|
||||||
deletingContact.name
|
}?`
|
||||||
}?`
|
|
||||||
: `${i18n.t("contacts.confirmationModal.importTitlte")}`
|
: `${i18n.t("contacts.confirmationModal.importTitlte")}`
|
||||||
}
|
}
|
||||||
open={confirmOpen}
|
open={confirmOpen}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import IconButton from "@mui/material/IconButton";
|
||||||
import Info from "@material-ui/icons/Info";
|
import Info from "@material-ui/icons/Info";
|
||||||
|
|
||||||
import { AuthContext } from "../../context/Auth/AuthContext";
|
import { AuthContext } from "../../context/Auth/AuthContext";
|
||||||
import { i18n } from "../../translate/i18n";
|
// import { i18n } from "../../translate/i18n";
|
||||||
import Chart from "./Chart";
|
import Chart from "./Chart";
|
||||||
import openSocket from "socket.io-client";
|
import openSocket from "socket.io-client";
|
||||||
import api from "../../services/api";
|
import api from "../../services/api";
|
||||||
|
@ -241,7 +241,7 @@ const Dashboard = () => {
|
||||||
dispatch({ type: "RESET" });
|
dispatch({ type: "RESET" });
|
||||||
dispatch({ type: "LOAD_QUERY", payload: dataQuery.data });
|
dispatch({ type: "LOAD_QUERY", payload: dataQuery.data });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ const Dashboard = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ticketStatusChange === "") return console.log("foi");
|
if (ticketStatusChange === "") return
|
||||||
const delayDebounceFn = setTimeout(() => {
|
const delayDebounceFn = setTimeout(() => {
|
||||||
const fetchQueries = async () => {
|
const fetchQueries = async () => {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -21,8 +21,7 @@ import apiBroker from "../../services/apiBroker";
|
||||||
import fileDownload from 'js-file-download'
|
import fileDownload from 'js-file-download'
|
||||||
|
|
||||||
|
|
||||||
import openSocket from "socket.io-client";
|
import openSocket from "socket.io-client";
|
||||||
import { TramOutlined } from "@material-ui/icons";
|
|
||||||
|
|
||||||
const report = [{ 'value': '1', 'label': 'Atendimento por atendentes' }, { 'value': '2', 'label': 'Usuários online/offline' }]
|
const report = [{ 'value': '1', 'label': 'Atendimento por atendentes' }, { 'value': '2', 'label': 'Usuários online/offline' }]
|
||||||
|
|
||||||
|
@ -216,7 +215,7 @@ let columnsData = [
|
||||||
{ title: 'Status', field: 'status' },
|
{ title: 'Status', field: 'status' },
|
||||||
|
|
||||||
{ title: 'Criado', field: 'createdAt' },
|
{ title: 'Criado', field: 'createdAt' },
|
||||||
//{title: 'Atualizado', field: 'updatedAt'},
|
{title: 'Atualizado', field: 'updatedAt'},
|
||||||
{ title: 'Status de encerramento', field: 'statusChatEnd' }];
|
{ title: 'Status de encerramento', field: 'statusChatEnd' }];
|
||||||
|
|
||||||
|
|
||||||
|
@ -305,7 +304,7 @@ const Report = () => {
|
||||||
|
|
||||||
const { data } = await api.get("/reports/", { params: { userId, startDate, endDate, pageNumber: pageNumberTickets }, });
|
const { data } = await api.get("/reports/", { params: { userId, startDate, endDate, pageNumber: pageNumberTickets }, });
|
||||||
|
|
||||||
dispatchQ({ type: "LOAD_QUERY", payload: data.tickets });
|
dispatchQ({ type: "LOAD_QUERY", payload: data.tickets });
|
||||||
|
|
||||||
setHasMore(data.hasMore);
|
setHasMore(data.hasMore);
|
||||||
setTotalCountTickets(data.count)
|
setTotalCountTickets(data.count)
|
||||||
|
@ -317,13 +316,8 @@ const Report = () => {
|
||||||
|
|
||||||
const dataQuery = await api.get("/reports/user/services", { params: { userId, startDate, endDate }, });
|
const dataQuery = await api.get("/reports/user/services", { params: { userId, startDate, endDate }, });
|
||||||
dispatchQ({ type: "RESET" })
|
dispatchQ({ type: "RESET" })
|
||||||
dispatchQ({ type: "LOAD_QUERY", payload: dataQuery.data });
|
dispatchQ({ type: "LOAD_QUERY", payload: dataQuery.data });
|
||||||
|
//setLoading(false);
|
||||||
//setLoading(false);
|
|
||||||
|
|
||||||
console.log('REPORT 2 dataQuery : ', dataQuery.data)
|
|
||||||
|
|
||||||
//console.log()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ const Settings = () => {
|
||||||
|
|
||||||
// const handleEdit = () => {
|
// const handleEdit = () => {
|
||||||
|
|
||||||
// console.log('Editar....')
|
//
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ import Ticket from "../../components/Ticket/";
|
||||||
import { i18n } from "../../translate/i18n";
|
import { i18n } from "../../translate/i18n";
|
||||||
import Hidden from "@material-ui/core/Hidden";
|
import Hidden from "@material-ui/core/Hidden";
|
||||||
|
|
||||||
|
import { SearchTicketProvider } from "../../context/SearchTicket/SearchTicket";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
chatContainer: {
|
chatContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
@ -78,8 +80,12 @@ const Chat = () => {
|
||||||
className={
|
className={
|
||||||
ticketId ? classes.contactsWrapperSmall : classes.contactsWrapper
|
ticketId ? classes.contactsWrapperSmall : classes.contactsWrapper
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<TicketsManager />
|
<SearchTicketProvider>
|
||||||
|
<TicketsManager />
|
||||||
|
</SearchTicketProvider>
|
||||||
|
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} md={8} className={classes.messagessWrapper}>
|
<Grid item xs={12} md={8} className={classes.messagessWrapper}>
|
||||||
{/* <Grid item xs={8} className={classes.messagessWrapper}> */}
|
{/* <Grid item xs={8} className={classes.messagessWrapper}> */}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { AuthProvider } from "../context/Auth/AuthContext";
|
||||||
import { WhatsAppsProvider } from "../context/WhatsApp/WhatsAppsContext";
|
import { WhatsAppsProvider } from "../context/WhatsApp/WhatsAppsContext";
|
||||||
import Route from "./Route";
|
import Route from "./Route";
|
||||||
|
|
||||||
//console.log('---AuthProvider: ',AuthProvider)
|
|
||||||
|
|
||||||
const Routes = () => {
|
const Routes = () => {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -241,7 +241,7 @@ const messages = {
|
||||||
search: { title: "Busca" },
|
search: { title: "Busca" },
|
||||||
},
|
},
|
||||||
search: {
|
search: {
|
||||||
placeholder: "Buscar tickets e mensagens",
|
placeholder: "Busca telefone/nome",
|
||||||
},
|
},
|
||||||
buttons: {
|
buttons: {
|
||||||
showAll: "Todos",
|
showAll: "Todos",
|
||||||
|
|
Loading…
Reference in New Issue