feat: Enable users to transfer to other queues and users with the same WhatsApp connection.
parent
d12a47f062
commit
bc134c827c
|
@ -289,7 +289,7 @@ app.post('/api/session', async function (req, res) {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (whatsapp[0]['name'].split('->').length > 0) {
|
if (whatsapp[0]['name']?.split('->')?.length > 0) {
|
||||||
whatsName = `${whatsapp[0]['name'].split('->')[0]} -> S${numberSession}`
|
whatsName = `${whatsapp[0]['name'].split('->')[0]} -> S${numberSession}`
|
||||||
} else {
|
} else {
|
||||||
whatsName = `${whatsapp[0]['name']} -> S${numberSession}`
|
whatsName = `${whatsapp[0]['name']} -> S${numberSession}`
|
||||||
|
|
|
@ -64,7 +64,11 @@ export const reportUserService = async (req: Request, res: Response): Promise<Re
|
||||||
const { userId, startDate, endDate } = req.query as IndexQuery
|
const { userId, startDate, endDate } = req.query as IndexQuery
|
||||||
|
|
||||||
|
|
||||||
let usersProfile = await ListUserParamiterService({ profile: 'user' })
|
// let usersProfile = await ListUserParamiterService({ profile: 'user' })
|
||||||
|
let usersProfile = await ListUserParamiterService({
|
||||||
|
profile: "user",
|
||||||
|
raw: true
|
||||||
|
});
|
||||||
|
|
||||||
const sumUserOlineTime = await ShowUserServiceReport({ startDate, endDate, userId });
|
const sumUserOlineTime = await ShowUserServiceReport({ startDate, endDate, userId });
|
||||||
const closedByUser = await ShowUserServiceReport({ startDate, endDate, ticketStatus: 'closed', userId });
|
const closedByUser = await ShowUserServiceReport({ startDate, endDate, ticketStatus: 'closed', userId });
|
||||||
|
|
|
@ -5,6 +5,12 @@ import AuthUserService from "../services/UserServices/AuthUserService";
|
||||||
import { SendRefreshToken } from "../helpers/SendRefreshToken";
|
import { SendRefreshToken } from "../helpers/SendRefreshToken";
|
||||||
import { RefreshTokenService } from "../services/AuthServices/RefreshTokenService";
|
import { RefreshTokenService } from "../services/AuthServices/RefreshTokenService";
|
||||||
|
|
||||||
|
import createOrUpdateOnlineUserService from "../services/UserServices/CreateOrUpdateOnlineUserService";
|
||||||
|
import { removeUserFromOlineList } from "../helpers/removeUserFromOnlineList";
|
||||||
|
|
||||||
|
// const usersSocket = require("./../libs/socket");
|
||||||
|
const usersSocket = require("../libs/socket");
|
||||||
|
|
||||||
export const store = async (req: Request, res: Response): Promise<Response> => {
|
export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
const { email, password } = req.body;
|
const { email, password } = req.body;
|
||||||
|
|
||||||
|
@ -15,6 +21,11 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
|
||||||
SendRefreshToken(res, refreshToken);
|
SendRefreshToken(res, refreshToken);
|
||||||
|
|
||||||
|
const userOnline = await createOrUpdateOnlineUserService({
|
||||||
|
userId: serializedUser.id,
|
||||||
|
status: "online"
|
||||||
|
});
|
||||||
|
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
token,
|
token,
|
||||||
user: serializedUser
|
user: serializedUser
|
||||||
|
@ -47,5 +58,14 @@ export const remove = async (
|
||||||
): Promise<Response> => {
|
): Promise<Response> => {
|
||||||
res.clearCookie("jrt");
|
res.clearCookie("jrt");
|
||||||
|
|
||||||
|
const { userId } = req.params;
|
||||||
|
|
||||||
|
removeUserFromOlineList(userId);
|
||||||
|
|
||||||
|
const userOnline = await createOrUpdateOnlineUserService({
|
||||||
|
userId,
|
||||||
|
status: "offline"
|
||||||
|
});
|
||||||
|
|
||||||
return res.send();
|
return res.send();
|
||||||
};
|
};
|
||||||
|
|
|
@ -64,6 +64,10 @@ import Contact from "../models/Contact";
|
||||||
import BotIsOnQueue from "../helpers/BotIsOnQueue";
|
import BotIsOnQueue from "../helpers/BotIsOnQueue";
|
||||||
import { setMessageAsRead } from "../helpers/SetMessageAsRead";
|
import { setMessageAsRead } from "../helpers/SetMessageAsRead";
|
||||||
import { getSettingValue } from "../helpers/WhaticketSettings";
|
import { getSettingValue } from "../helpers/WhaticketSettings";
|
||||||
|
import ListWhatsAppsForQueueService from "../services/WhatsappService/ListWhatsAppsForQueueService";
|
||||||
|
import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber";
|
||||||
|
import Whatsapp from "../models/Whatsapp";
|
||||||
|
import AppError from "../errors/AppError";
|
||||||
|
|
||||||
export const index = async (req: Request, res: Response): Promise<Response> => {
|
export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||||
const {
|
const {
|
||||||
|
@ -132,14 +136,14 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ticket){
|
if (!ticket) {
|
||||||
ticket = await CreateTicketService({
|
ticket = await CreateTicketService({
|
||||||
contactId,
|
contactId,
|
||||||
status,
|
status,
|
||||||
userId,
|
userId,
|
||||||
queueId,
|
queueId,
|
||||||
whatsappId
|
whatsappId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const io = getIO();
|
const io = getIO();
|
||||||
|
@ -249,24 +253,88 @@ export const update = async (
|
||||||
req.body.userId = null;
|
req.body.userId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("REQ.BODY: ", JSON.stringify(req.body, null, 6));
|
||||||
|
|
||||||
let ticketData: TicketData = req.body;
|
let ticketData: TicketData = req.body;
|
||||||
|
|
||||||
if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") {
|
if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") {
|
||||||
if (ticketData.transfer) {
|
if (ticketData.transfer) {
|
||||||
const defaultWhatsapp: any = await GetDefaultWhatsApp({
|
const whatsappsByqueue = await ListWhatsAppsForQueueService(
|
||||||
userId: ticketData.userId
|
ticketData.queueId
|
||||||
});
|
);
|
||||||
|
|
||||||
const _ticket: any = await Ticket.findByPk(ticketId);
|
if (userOldInfo) {
|
||||||
|
let listTicketOpenPending: any = [];
|
||||||
|
|
||||||
if (defaultWhatsapp && ticketData.status != "open") {
|
for (const w of whatsappsByqueue) {
|
||||||
await CheckContactOpenTickets(
|
let whats = await ListWhatsAppsNumber(w.id);
|
||||||
_ticket.dataValues.contactId,
|
|
||||||
defaultWhatsapp.dataValues.id
|
console.log("-------> WHATS: ", JSON.stringify(whats, null, 6));
|
||||||
);
|
const ticket = await Ticket.findOne({
|
||||||
|
where: {
|
||||||
|
[Op.and]: [
|
||||||
|
{ contactId: userOldInfo.contactId },
|
||||||
|
{
|
||||||
|
whatsappId: {
|
||||||
|
[Op.in]: whats.whatsapps.map((w: any) => w.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ status: { [Op.or]: ["open", "pending"] } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ticket) {
|
||||||
|
listTicketOpenPending.push({
|
||||||
|
ticketId: ticket.id,
|
||||||
|
status: ticket.status,
|
||||||
|
userId: ticket.userId,
|
||||||
|
contactId: ticket.contactId,
|
||||||
|
whatsappId: ticket.whatsappId,
|
||||||
|
queueId: ticket.queueId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log("userOldInfo: ", JSON.stringify(userOldInfo, null, 6));
|
||||||
|
// console.log("##########")
|
||||||
|
// console.log(
|
||||||
|
// "listTicketOpenPending: ",
|
||||||
|
// JSON.stringify(listTicketOpenPending)
|
||||||
|
// );
|
||||||
|
|
||||||
|
if (
|
||||||
|
listTicketOpenPending.filter(
|
||||||
|
(ob: any) => userOldInfo.whatsappId != ob.whatsappId
|
||||||
|
)?.length > 0
|
||||||
|
) {
|
||||||
|
throw new AppError("ERR_OTHER_OPEN_TICKET");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ticketData.whatsappId = defaultWhatsapp.dataValues.id;
|
//////////////////////////////////////////////
|
||||||
|
|
||||||
|
// const defaultWhatsapp: any = await GetDefaultWhatsApp({
|
||||||
|
// userId: ticketData.userId
|
||||||
|
// });
|
||||||
|
|
||||||
|
// console.log(
|
||||||
|
// "ticketData.userId: ",
|
||||||
|
// ticketData.userId,
|
||||||
|
// " | defaultWhatsapp: ",
|
||||||
|
// JSON.stringify(defaultWhatsapp, null, 6)
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const _ticket: any = await Ticket.findByPk(ticketId);
|
||||||
|
|
||||||
|
// if (defaultWhatsapp && ticketData.status != "open") {
|
||||||
|
// await CheckContactOpenTickets(
|
||||||
|
// _ticket.dataValues.contactId,
|
||||||
|
// defaultWhatsapp.dataValues.id
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ticketData.whatsappId = defaultWhatsapp.dataValues.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,16 +10,28 @@ import UpdateUserService from "../services/UserServices/UpdateUserService";
|
||||||
import ShowUserService from "../services/UserServices/ShowUserService";
|
import ShowUserService from "../services/UserServices/ShowUserService";
|
||||||
import DeleteUserService from "../services/UserServices/DeleteUserService";
|
import DeleteUserService from "../services/UserServices/DeleteUserService";
|
||||||
|
|
||||||
import ListUserParamiterService from "../services/UserServices/ListUserParamiterService"
|
import ListUser from "../services/UserServices/ListUserParamiterService";
|
||||||
import User from "../models/User";
|
import User from "../models/User";
|
||||||
|
|
||||||
import { startWhoIsOnlineMonitor, stopWhoIsOnlineMonitor } from "../helpers/WhoIsOnlineMonitor"
|
import {
|
||||||
import UserOnlineTIme from '../models/UserOnlineTime'
|
startWhoIsOnlineMonitor,
|
||||||
|
stopWhoIsOnlineMonitor
|
||||||
|
} from "../helpers/WhoIsOnlineMonitor";
|
||||||
|
import UserOnlineTIme from "../models/UserOnlineTime";
|
||||||
|
|
||||||
|
import { format, subMonths } from "date-fns";
|
||||||
|
import { ptBR } from "date-fns/locale";
|
||||||
|
import CountTicketsByUserQueue from "../services/UserServices/CountTicketsByUserQueue";
|
||||||
|
import { splitDateTime } from "../helpers/SplitDateTime";
|
||||||
|
import ListUserByWhatsappQueuesService from "../services/UserServices/ListUserByWhatsappQueuesService";
|
||||||
|
import { json } from "sequelize";
|
||||||
|
import { getSettingValue } from "../helpers/WhaticketSettings";
|
||||||
|
|
||||||
type IndexQuery = {
|
type IndexQuery = {
|
||||||
searchParam: string;
|
searchParam: string;
|
||||||
pageNumber: string;
|
pageNumber: string;
|
||||||
profile?: string;
|
profile?: string;
|
||||||
|
userId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const index = async (req: Request, res: Response): Promise<Response> => {
|
export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
@ -31,13 +43,21 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||||
profile
|
profile
|
||||||
});
|
});
|
||||||
|
|
||||||
if (req.user.profile !== 'master') {
|
if (req.user.profile !== "master") {
|
||||||
|
|
||||||
let auxUsers: Array<object> = [];
|
let auxUsers: Array<object> = [];
|
||||||
|
|
||||||
|
// for (var user of users) {
|
||||||
|
// if (user.profile !== 'master') {
|
||||||
|
// auxUsers.push(user)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
for (var user of users) {
|
for (var user of users) {
|
||||||
if (user.profile !== 'master') {
|
if (user.profile !== "master") {
|
||||||
auxUsers.push(user)
|
if (req.user.profile == "supervisor" && user.profile == "admin")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auxUsers.push(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,8 +66,6 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
|
||||||
return res.json({ users, count, hasMore });
|
return res.json({ users, count, hasMore });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// const { users, count, hasMore } = await ListUsersService({
|
// const { users, count, hasMore } = await ListUsersService({
|
||||||
// searchParam,
|
// searchParam,
|
||||||
// pageNumber
|
// pageNumber
|
||||||
|
@ -69,11 +87,59 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||||
// return res.json({ users, count, hasMore });
|
// return res.json({ users, count, hasMore });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// export const usersByWhatsappQueue = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
// const { profile } = req.query as IndexQuery;
|
||||||
|
|
||||||
|
// const users = await ListUser({
|
||||||
|
// profile
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return res.json({ users });
|
||||||
|
// };
|
||||||
|
|
||||||
|
export const all = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
const { userId, profile } = req.query as IndexQuery;
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"userId: ",
|
||||||
|
userId,
|
||||||
|
" | profile: ",
|
||||||
|
profile,
|
||||||
|
' | getSettingValue("queueTransferByWhatsappScope")?.value: ',
|
||||||
|
getSettingValue("queueTransferByWhatsappScope")?.value
|
||||||
|
);
|
||||||
|
|
||||||
|
if (getSettingValue("queueTransferByWhatsappScope")?.value == "enabled") {
|
||||||
|
const obj = await ListUserByWhatsappQueuesService(
|
||||||
|
userId,
|
||||||
|
'"admin", "user", "supervisor"'
|
||||||
|
);
|
||||||
|
|
||||||
|
const usersByWhatsqueue = obj.users;
|
||||||
|
const queues = obj.queues;
|
||||||
|
|
||||||
|
let userIds = usersByWhatsqueue.map((w: any) => w.userId);
|
||||||
|
|
||||||
|
const users = await ListUser({
|
||||||
|
userIds
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.json({ users, queues });
|
||||||
|
} else {
|
||||||
|
const users = await ListUser({
|
||||||
|
profile
|
||||||
|
});
|
||||||
|
return res.json({ users });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const store = async (req: Request, res: Response): Promise<Response> => {
|
export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
const { email, password, name, profile, queueIds } = req.body;
|
const { email, password, name, profile, queueIds } = req.body;
|
||||||
|
|
||||||
if (req.url === "/signup" && (await CheckSettingsHelper("userCreation")) === "disabled") {
|
if (
|
||||||
|
req.url === "/signup" &&
|
||||||
|
(await CheckSettingsHelper("userCreation")) === "disabled"
|
||||||
|
) {
|
||||||
throw new AppError("ERR_USER_CREATION_DISABLED", 403);
|
throw new AppError("ERR_USER_CREATION_DISABLED", 403);
|
||||||
} else if (req.url !== "/signup" && req.user.profile !== "master") {
|
} else if (req.url !== "/signup" && req.user.profile !== "master") {
|
||||||
throw new AppError("ERR_NO_PERMISSION", 403);
|
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||||
|
@ -93,9 +159,8 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
user
|
user
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// await stopWhoIsOnlineMonitor()
|
// await stopWhoIsOnlineMonitor()
|
||||||
await startWhoIsOnlineMonitor()
|
await startWhoIsOnlineMonitor();
|
||||||
|
|
||||||
return res.status(200).json(user);
|
return res.status(200).json(user);
|
||||||
};
|
};
|
||||||
|
@ -108,17 +173,18 @@ export const show = async (req: Request, res: Response): Promise<Response> => {
|
||||||
return res.status(200).json(user);
|
return res.status(200).json(user);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const logoutUser = async (
|
||||||
export const logoutUser = async (req: Request, res: Response): Promise<Response> => {
|
req: Request,
|
||||||
|
res: Response
|
||||||
|
): Promise<Response> => {
|
||||||
const { userId } = req.params;
|
const { userId } = req.params;
|
||||||
|
|
||||||
|
await stopWhoIsOnlineMonitor();
|
||||||
await stopWhoIsOnlineMonitor()
|
|
||||||
|
|
||||||
let onlineTime = {
|
let onlineTime = {
|
||||||
userId: userId,
|
userId: userId,
|
||||||
status: 'logout...'
|
status: "logout..."
|
||||||
}
|
};
|
||||||
|
|
||||||
const io = getIO();
|
const io = getIO();
|
||||||
io.emit("onlineStatus", {
|
io.emit("onlineStatus", {
|
||||||
|
@ -126,25 +192,73 @@ export const logoutUser = async (req: Request, res: Response): Promise<Response>
|
||||||
userOnlineTime: onlineTime
|
userOnlineTime: onlineTime
|
||||||
});
|
});
|
||||||
|
|
||||||
await startWhoIsOnlineMonitor()
|
await startWhoIsOnlineMonitor();
|
||||||
//
|
//
|
||||||
|
|
||||||
return res.status(200).json({});
|
return res.status(200).json({});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const update = async (
|
export const update = async (
|
||||||
req: Request,
|
req: Request,
|
||||||
res: Response
|
res: Response
|
||||||
): Promise<Response> => {
|
): Promise<Response> => {
|
||||||
if (req.user.profile !== "admin" && req.user.profile !== "master") {
|
if (
|
||||||
|
req.user.profile !== "admin" &&
|
||||||
|
req.user.profile !== "master" &&
|
||||||
|
req.user.profile !== "supervisor"
|
||||||
|
) {
|
||||||
throw new AppError("ERR_NO_PERMISSION", 403);
|
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { userId } = req.params;
|
const { userId } = req.params;
|
||||||
const userData = req.body;
|
const userData = req.body;
|
||||||
|
|
||||||
const user = await UpdateUserService({ userData, userId });
|
const dateToday = splitDateTime(
|
||||||
|
new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR }))
|
||||||
|
);
|
||||||
|
|
||||||
|
const currentDate = new Date();
|
||||||
|
const tenMonthsAgo = subMonths(currentDate, 10);
|
||||||
|
const formattedDate = format(tenMonthsAgo, "yyyy-MM-dd");
|
||||||
|
console.log("dateToday.fullDate: ", dateToday.fullDate);
|
||||||
|
console.log("formattedDate 10 months ago: ", formattedDate);
|
||||||
|
|
||||||
|
const openByUserOnQueue: any[] = await CountTicketsByUserQueue({
|
||||||
|
startDate: formattedDate,
|
||||||
|
endDate: dateToday.fullDate,
|
||||||
|
status: "open",
|
||||||
|
clientChatStart: true,
|
||||||
|
userId: userId
|
||||||
|
});
|
||||||
|
|
||||||
|
// console.log('------> openByUserOnQueue: ', openByUserOnQueue)
|
||||||
|
// console.log()
|
||||||
|
// console.log('------> 1 userData.queueIds: ', userData.queueIds)
|
||||||
|
|
||||||
|
let userQueuesAttendance = [];
|
||||||
|
|
||||||
|
if ((openByUserOnQueue && openByUserOnQueue.length) > 0) {
|
||||||
|
userQueuesAttendance = openByUserOnQueue.filter(
|
||||||
|
(e: any) => !userData.queueIds.includes(e.queueId)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (userQueuesAttendance && userQueuesAttendance.length > 0) {
|
||||||
|
const queueInAttendance = userQueuesAttendance.map(e => e.queueId);
|
||||||
|
|
||||||
|
const mergedSet = new Set([...userData.queueIds, ...queueInAttendance]);
|
||||||
|
|
||||||
|
// Convert the Set back to an array
|
||||||
|
userData.queueIds = Array.from(mergedSet);
|
||||||
|
|
||||||
|
// console.log('------> 2 userData.queueIds: ', userData.queueIds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log('userQueuesAttendance: ', userQueuesAttendance)
|
||||||
|
|
||||||
|
// return res.status(200).json({});
|
||||||
|
|
||||||
|
let user: any = await UpdateUserService({ userData, userId });
|
||||||
|
|
||||||
const io = getIO();
|
const io = getIO();
|
||||||
io.emit("user", {
|
io.emit("user", {
|
||||||
|
@ -152,6 +266,8 @@ export const update = async (
|
||||||
user
|
user
|
||||||
});
|
});
|
||||||
|
|
||||||
|
user.userQueuesAttendance = userQueuesAttendance;
|
||||||
|
|
||||||
return res.status(200).json(user);
|
return res.status(200).json(user);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -165,26 +281,23 @@ export const remove = async (
|
||||||
throw new AppError("ERR_NO_PERMISSION", 403);
|
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
await DeleteUserService(userId);
|
await DeleteUserService(userId);
|
||||||
|
|
||||||
|
|
||||||
const io = getIO();
|
const io = getIO();
|
||||||
io.emit("user", {
|
io.emit("user", {
|
||||||
action: "delete",
|
action: "delete",
|
||||||
userId
|
userId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
//test del
|
//test del
|
||||||
await stopWhoIsOnlineMonitor()
|
await stopWhoIsOnlineMonitor();
|
||||||
|
|
||||||
io.emit("onlineStatus", {
|
io.emit("onlineStatus", {
|
||||||
action: "delete",
|
action: "delete",
|
||||||
userOnlineTime: userId
|
userOnlineTime: userId
|
||||||
});
|
});
|
||||||
|
|
||||||
await startWhoIsOnlineMonitor()
|
await startWhoIsOnlineMonitor();
|
||||||
//
|
//
|
||||||
|
|
||||||
return res.status(200).json({ message: "User deleted" });
|
return res.status(200).json({ message: "User deleted" });
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { QueryInterface } from "sequelize";
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface: QueryInterface) => {
|
||||||
|
return queryInterface.bulkInsert(
|
||||||
|
"Settings",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
key: "queueTransferByWhatsappScope",
|
||||||
|
value: "disabled",
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date()
|
||||||
|
}
|
||||||
|
],
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
down: (queryInterface: QueryInterface) => {
|
||||||
|
return queryInterface.bulkDelete("Settings", {});
|
||||||
|
}
|
||||||
|
};
|
|
@ -3,16 +3,22 @@ import AppError from "../errors/AppError";
|
||||||
import Ticket from "../models/Ticket";
|
import Ticket from "../models/Ticket";
|
||||||
import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber";
|
import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber";
|
||||||
import { getSettingValue } from "./WhaticketSettings";
|
import { getSettingValue } from "./WhaticketSettings";
|
||||||
|
import ListWhatsAppsForQueueService from "../services/WhatsappService/ListWhatsAppsForQueueService";
|
||||||
|
|
||||||
const CheckContactOpenTickets = async (
|
const CheckContactOpenTickets = async (
|
||||||
contactId: number,
|
contactId: number,
|
||||||
whatsappId: number | string
|
whatsappId: number | string,
|
||||||
): Promise<void> => {
|
handle?: boolean
|
||||||
|
): Promise<void | any> => {
|
||||||
let ticket;
|
let ticket;
|
||||||
|
|
||||||
if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") {
|
if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") {
|
||||||
let whats = await ListWhatsAppsNumber(whatsappId);
|
let whats = await ListWhatsAppsNumber(whatsappId);
|
||||||
|
|
||||||
|
console.log("contactId: ", contactId, " | whatsappId: ", whatsappId);
|
||||||
|
|
||||||
|
console.log("WHATS: ", JSON.stringify(whats, null, 6));
|
||||||
|
|
||||||
ticket = await Ticket.findOne({
|
ticket = await Ticket.findOne({
|
||||||
where: {
|
where: {
|
||||||
[Op.and]: [
|
[Op.and]: [
|
||||||
|
@ -22,6 +28,8 @@ const CheckContactOpenTickets = async (
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("TICKET: ", JSON.stringify(ticket, null, 6));
|
||||||
} else {
|
} else {
|
||||||
ticket = await Ticket.findOne({
|
ticket = await Ticket.findOne({
|
||||||
where: { contactId, status: { [Op.or]: ["open", "pending"] } }
|
where: { contactId, status: { [Op.or]: ["open", "pending"] } }
|
||||||
|
@ -29,8 +37,12 @@ const CheckContactOpenTickets = async (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ticket) {
|
if (ticket) {
|
||||||
|
if (handle) return true;
|
||||||
|
|
||||||
throw new AppError("ERR_OTHER_OPEN_TICKET");
|
throw new AppError("ERR_OTHER_OPEN_TICKET");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CheckContactOpenTickets;
|
export default CheckContactOpenTickets;
|
||||||
|
|
|
@ -67,7 +67,7 @@ const monitor = async () => {
|
||||||
|
|
||||||
const usersSocket = require('./../libs/socket');
|
const usersSocket = require('./../libs/socket');
|
||||||
|
|
||||||
if (usersSocket.ob) {
|
if (usersSocket?.ob) {
|
||||||
|
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
count = 0
|
count = 0
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
const usersSocket = require("../libs/socket");
|
||||||
|
|
||||||
|
export const removeUserFromOlineList = (userId: any) => {
|
||||||
|
let index = usersSocket.ob.listOnline.findIndex((o: any) => o.id == userId);
|
||||||
|
|
||||||
|
if (index != -1) {
|
||||||
|
usersSocket.ob.listOnline.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
index = -1;
|
||||||
|
|
||||||
|
index = usersSocket.ob.listOnlineAux.findIndex((o: any) => o.id == userId);
|
||||||
|
|
||||||
|
if (index != -1) {
|
||||||
|
usersSocket.ob.listOnlineAux.splice(index, 1);
|
||||||
|
}
|
||||||
|
};
|
|
@ -139,7 +139,7 @@ export const initIO = (httpServer: Server): SocketIO => {
|
||||||
lstOnline.push({ id: userId, status: "online", try: 0 });
|
lstOnline.push({ id: userId, status: "online", try: 0 });
|
||||||
|
|
||||||
lstOnlineAux.push({ id: userId });
|
lstOnlineAux.push({ id: userId });
|
||||||
console.log(" 1 PUSHED NEW USER ID 1: ", userId);
|
console.log(" 1 - PUSHED NEW USER ID 1: ", userId);
|
||||||
|
|
||||||
obj.listOnline = lstOnline;
|
obj.listOnline = lstOnline;
|
||||||
} else {
|
} else {
|
||||||
|
@ -154,7 +154,7 @@ export const initIO = (httpServer: Server): SocketIO => {
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
lstOnline.push({ id: userId, status: "online", try: 0 });
|
lstOnline.push({ id: userId, status: "online", try: 0 });
|
||||||
|
|
||||||
console.log(" 2 PUSHED NEW USER ID: ", userId);
|
console.log(" 2 - PUSHED NEW USER ID: ", userId);
|
||||||
|
|
||||||
obj.listOnline = lstOnline;
|
obj.listOnline = lstOnline;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,6 +11,6 @@ authRoutes.post("/login", SessionController.store);
|
||||||
|
|
||||||
authRoutes.post("/refresh_token", SessionController.update);
|
authRoutes.post("/refresh_token", SessionController.update);
|
||||||
|
|
||||||
authRoutes.delete("/logout", isAuth, SessionController.remove);
|
authRoutes.delete("/logout/:userId", isAuth, SessionController.remove);
|
||||||
|
|
||||||
export default authRoutes;
|
export default authRoutes;
|
||||||
|
|
|
@ -6,6 +6,8 @@ import * as UserController from "../controllers/UserController";
|
||||||
const userRoutes = Router();
|
const userRoutes = Router();
|
||||||
|
|
||||||
|
|
||||||
|
userRoutes.get("/users/all", isAuth, UserController.all);
|
||||||
|
|
||||||
userRoutes.get("/users", isAuth, UserController.index);
|
userRoutes.get("/users", isAuth, UserController.index);
|
||||||
|
|
||||||
userRoutes.post("/users", isAuth, UserController.store);
|
userRoutes.post("/users", isAuth, UserController.store);
|
||||||
|
|
|
@ -16,6 +16,8 @@ import { createOrUpdateTicketCache } from "../../helpers/TicketCache";
|
||||||
import User from "../../models/User";
|
import User from "../../models/User";
|
||||||
import whatsappQueueMatchingUserQueue from "../../helpers/whatsappQueueMatchingUserQueue";
|
import whatsappQueueMatchingUserQueue from "../../helpers/whatsappQueueMatchingUserQueue";
|
||||||
import Whatsapp from "../../models/Whatsapp";
|
import Whatsapp from "../../models/Whatsapp";
|
||||||
|
import ListWhatsAppsForQueueService from "../WhatsappService/ListWhatsAppsForQueueService";
|
||||||
|
import { json } from "sequelize";
|
||||||
let flatten = require("flat");
|
let flatten = require("flat");
|
||||||
|
|
||||||
interface Request {
|
interface Request {
|
||||||
|
@ -42,6 +44,27 @@ const CreateTicketService = async ({
|
||||||
defaultWhatsapp = await GetDefaultWhatsApp({ userId, queueId });
|
defaultWhatsapp = await GetDefaultWhatsApp({ userId, queueId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (queueId) {
|
||||||
|
// const whatsappsByQueue = await ListWhatsAppsForQueueService(queueId);
|
||||||
|
|
||||||
|
// const exist = await CheckContactOpenTickets(
|
||||||
|
// contactId,
|
||||||
|
// defaultWhatsapp.id,
|
||||||
|
// true
|
||||||
|
// );
|
||||||
|
|
||||||
|
// console.log(
|
||||||
|
// "whatsappsByQueue: ",
|
||||||
|
// JSON.stringify(whatsappsByQueue, null, 6)
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (exist) {
|
||||||
|
// console.log("kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return new Ticket();
|
||||||
|
// }
|
||||||
|
|
||||||
// console.log(JSON.stringify(defaultWhatsapp, null, 2));
|
// console.log(JSON.stringify(defaultWhatsapp, null, 2));
|
||||||
// throw new AppError("test error");
|
// throw new AppError("test error");
|
||||||
|
|
||||||
|
@ -59,6 +82,13 @@ const CreateTicketService = async ({
|
||||||
queueId = matchingQueue ? matchingQueue.queueId : undefined;
|
queueId = matchingQueue ? matchingQueue.queueId : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"xxxxxxxxxxxx contactId: ",
|
||||||
|
contactId,
|
||||||
|
" | defaultWhatsapp.id: ",
|
||||||
|
defaultWhatsapp.id
|
||||||
|
);
|
||||||
|
|
||||||
await CheckContactOpenTickets(contactId, defaultWhatsapp.id);
|
await CheckContactOpenTickets(contactId, defaultWhatsapp.id);
|
||||||
|
|
||||||
const { isGroup } = await ShowContactService(contactId);
|
const { isGroup } = await ShowContactService(contactId);
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { Sequelize } from "sequelize";
|
||||||
|
import Whatsapp from "../../models/Whatsapp";
|
||||||
|
import WhatsappQueue from "../../models/WhatsappQueue";
|
||||||
|
import { List } from "whatsapp-web.js";
|
||||||
|
const dbConfig = require("../../config/database");
|
||||||
|
const { QueryTypes } = require("sequelize");
|
||||||
|
|
||||||
|
const sequelize = new Sequelize(dbConfig);
|
||||||
|
|
||||||
|
const ListWhatsappQueueByUserQueue = async (
|
||||||
|
userId: number | string,
|
||||||
|
profiles: string
|
||||||
|
): Promise<any> => {
|
||||||
|
const users = await sequelize.query(
|
||||||
|
`select wq.whatsappId, wq.queueId, uq.userId, uq.queueId, u.id, u.name, u.profile, w.number
|
||||||
|
from WhatsappQueues wq join UserQueues uq join Users u join Whatsapps w on
|
||||||
|
wq.queueId = uq.queueId where u.id = uq.userId and u.profile in (${profiles}) and u.id = ${userId}
|
||||||
|
and w.id = wq.whatsappId group by w.number ;`,
|
||||||
|
{ type: QueryTypes.SELECT }
|
||||||
|
);
|
||||||
|
|
||||||
|
return users;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ListWhatsappQueesByUser = async (whatsappIds: string): Promise<any> => {
|
||||||
|
const users = await sequelize.query(
|
||||||
|
`SELECT
|
||||||
|
wq.whatsappId, wq.queueId, q.name, q.id, q.name, q.color
|
||||||
|
FROM
|
||||||
|
WhatsappQueues wq
|
||||||
|
JOIN
|
||||||
|
Queues q ON wq.whatsappId IN (${whatsappIds}) AND q.id = wq.queueId group by wq.queueId;
|
||||||
|
|
||||||
|
`,
|
||||||
|
{ type: QueryTypes.SELECT }
|
||||||
|
);
|
||||||
|
|
||||||
|
return users;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ListUserByWhatsappQueuesService = async (
|
||||||
|
userId: number | string,
|
||||||
|
profiles: string
|
||||||
|
): Promise<any> => {
|
||||||
|
const whatsapps: any = await ListWhatsappQueueByUserQueue(userId, profiles);
|
||||||
|
|
||||||
|
let whatsappIds = whatsapps.map((w: any) => w.whatsappId);
|
||||||
|
|
||||||
|
if (whatsappIds.length == 0) return { users: [], queues: [] };
|
||||||
|
|
||||||
|
console.log("----------> whatsappIds: ", whatsappIds, " | userId: ", userId);
|
||||||
|
|
||||||
|
whatsappIds = whatsappIds.join(", ");
|
||||||
|
|
||||||
|
const users: any = await sequelize.query(
|
||||||
|
`select wq.whatsappId, wq.queueId, uq.userId, uq.queueId, u.id, u.name, u.profile
|
||||||
|
from WhatsappQueues wq join UserQueues uq join Users u on
|
||||||
|
wq.queueId = uq.queueId where u.id = uq.userId and u.profile in (${profiles}) and wq.whatsappId in (${whatsappIds}) group by u.id;`,
|
||||||
|
{ type: QueryTypes.SELECT }
|
||||||
|
);
|
||||||
|
|
||||||
|
const queues = await ListWhatsappQueesByUser(whatsappIds);
|
||||||
|
|
||||||
|
return { users, queues };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ListUserByWhatsappQueuesService;
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
import { Op, Sequelize } from "sequelize";
|
import { Op, Sequelize } from "sequelize";
|
||||||
import Queue from "../../models/Queue";
|
import Queue from "../../models/Queue";
|
||||||
import User from "../../models/User";
|
import User from "../../models/User";
|
||||||
|
@ -7,65 +6,44 @@ import UserQueue from "../../models/UserQueue";
|
||||||
interface Request {
|
interface Request {
|
||||||
userId?: string | number;
|
userId?: string | number;
|
||||||
profile?: string;
|
profile?: string;
|
||||||
|
raw?: boolean;
|
||||||
|
userIds?: string | number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ListUser = async ({ profile, userId, raw, userIds }: Request): Promise<User[]> => {
|
||||||
const ListUser = async ({ profile, userId }: Request): Promise<User[]> => {
|
let where_clause = {};
|
||||||
|
|
||||||
let where_clause = {}
|
|
||||||
|
|
||||||
if (userId && profile) {
|
if (userId && profile) {
|
||||||
where_clause = {
|
where_clause = {
|
||||||
[Op.and]: [
|
[Op.and]: [{ userId: userId }, { profile: profile }]
|
||||||
{ userId: userId },
|
};
|
||||||
{ profile: profile }
|
} else if (userId) {
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (userId) {
|
|
||||||
where_clause = {
|
where_clause = {
|
||||||
[Op.and]: [
|
[Op.and]: [{ userId: userId }]
|
||||||
{ userId: userId },
|
};
|
||||||
]
|
} else if (profile) {
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (profile) {
|
|
||||||
where_clause = {
|
where_clause = {
|
||||||
profile: profile
|
profile: profile
|
||||||
}
|
};
|
||||||
|
} else if (userIds) {
|
||||||
|
where_clause = {
|
||||||
|
id: { [Op.in]: userIds }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const users = await User.findAll({
|
const users = await User.findAll({
|
||||||
where: where_clause,
|
where: where_clause,
|
||||||
raw: true,
|
raw,
|
||||||
attributes: ['id', 'name', 'email'],
|
attributes: ["id", "name", "email"],
|
||||||
|
|
||||||
|
include: [
|
||||||
|
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] }
|
||||||
|
],
|
||||||
|
|
||||||
// include: [
|
order: [["id", "ASC"]]
|
||||||
// {
|
});
|
||||||
// model: UserQueue,
|
|
||||||
// separate: true,
|
|
||||||
|
|
||||||
// attributes: ['id',],
|
|
||||||
|
|
||||||
// order: [
|
|
||||||
// ['createdAt', 'ASC']
|
|
||||||
// ]
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
order: [["id", "ASC"]],
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
return users;
|
return users;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ListUser;
|
export default ListUser;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Sequelize } from "sequelize";
|
||||||
|
import Whatsapp from "../../models/Whatsapp";
|
||||||
|
import WhatsappQueue from "../../models/WhatsappQueue";
|
||||||
|
const dbConfig = require("../../config/database");
|
||||||
|
const { QueryTypes } = require("sequelize");
|
||||||
|
|
||||||
|
const sequelize = new Sequelize(dbConfig);
|
||||||
|
|
||||||
|
const ListWhatsAppsForQueueService = async (queueId: number | string): Promise<any> => {
|
||||||
|
const distinctWhatsapps = await sequelize.query(
|
||||||
|
`SELECT w.id, w.number, w.status, wq.whatsappId, wq.queueId
|
||||||
|
FROM Whatsapps w
|
||||||
|
JOIN WhatsappQueues wq ON w.id = wq.whatsappId AND wq.queueId = ${queueId}
|
||||||
|
GROUP BY w.number;`,
|
||||||
|
{ type: QueryTypes.SELECT }
|
||||||
|
);
|
||||||
|
|
||||||
|
return distinctWhatsapps;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ListWhatsAppsForQueueService;
|
||||||
|
|
|
@ -87,8 +87,15 @@ const NewTicketModal = ({ modalOpen, onClose }) => {
|
||||||
if (newValue?.number) {
|
if (newValue?.number) {
|
||||||
setSelectedContact(newValue);
|
setSelectedContact(newValue);
|
||||||
} else if (newValue?.name) {
|
} else if (newValue?.name) {
|
||||||
setNewContact({ name: newValue.name });
|
|
||||||
setContactModalOpen(true);
|
if (/^-?\d+(\.\d+)?$/.test(newValue?.name)) {
|
||||||
|
setNewContact({ number: newValue.name })
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setNewContact({ name: newValue.name })
|
||||||
|
}
|
||||||
|
|
||||||
|
setContactModalOpen(true)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,34 @@
|
||||||
import React, { useState, useContext, useMemo } from "react";
|
import React, { useState, useContext, useMemo, useEffect } from "react"
|
||||||
import { useHistory } from "react-router-dom";
|
import { useHistory } from "react-router-dom"
|
||||||
|
import openSocket from "socket.io-client"
|
||||||
|
|
||||||
import Button from "@material-ui/core/Button";
|
import Button from "@material-ui/core/Button"
|
||||||
import Dialog from "@material-ui/core/Dialog";
|
import Dialog from "@material-ui/core/Dialog"
|
||||||
import Select from "@material-ui/core/Select";
|
import Select from "@material-ui/core/Select"
|
||||||
import FormControl from "@material-ui/core/FormControl";
|
import FormControl from "@material-ui/core/FormControl"
|
||||||
import InputLabel from "@material-ui/core/InputLabel";
|
import InputLabel from "@material-ui/core/InputLabel"
|
||||||
import MenuItem from "@material-ui/core/MenuItem";
|
import MenuItem from "@material-ui/core/MenuItem"
|
||||||
import { makeStyles } from "@material-ui/core";
|
import { makeStyles } from "@material-ui/core"
|
||||||
|
|
||||||
import DialogActions from "@material-ui/core/DialogActions";
|
import DialogActions from "@material-ui/core/DialogActions"
|
||||||
import DialogContent from "@material-ui/core/DialogContent";
|
import DialogContent from "@material-ui/core/DialogContent"
|
||||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
import DialogTitle from "@material-ui/core/DialogTitle"
|
||||||
|
|
||||||
import { i18n } from "../../translate/i18n";
|
import { i18n } from "../../translate/i18n"
|
||||||
import api from "../../services/api";
|
import api from "../../services/api"
|
||||||
import ButtonWithSpinner from "../ButtonWithSpinner";
|
import ButtonWithSpinner from "../ButtonWithSpinner"
|
||||||
import toastError from "../../errors/toastError";
|
import toastError from "../../errors/toastError"
|
||||||
|
|
||||||
import { WhatsAppsContext } from "../../context/WhatsApp/WhatsAppsContext";
|
import { AuthContext } from "../../context/Auth/AuthContext"
|
||||||
|
|
||||||
|
|
||||||
|
import { WhatsAppsContext } from "../../context/WhatsApp/WhatsAppsContext"
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
maxWidth: {
|
maxWidth: {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
},
|
},
|
||||||
}));
|
}))
|
||||||
|
|
||||||
// Receive array of queues arrays
|
// Receive array of queues arrays
|
||||||
// Return a new array with unique queues from all arrays has passed by the parameter
|
// Return a new array with unique queues from all arrays has passed by the parameter
|
||||||
|
@ -45,49 +49,177 @@ const queueArraysToOneArray = (array) => {
|
||||||
|
|
||||||
|
|
||||||
const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
|
const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
|
||||||
const history = useHistory();
|
const history = useHistory()
|
||||||
const { whatsApps } = useContext(WhatsAppsContext);
|
const { whatsApps } = useContext(WhatsAppsContext)
|
||||||
const [loading, setLoading] = useState(false);
|
const { user } = useContext(AuthContext)
|
||||||
const [selectedQueue, setSelectedQueue] = useState('');
|
|
||||||
const classes = useStyles();
|
const [loading, setLoading] = useState(false)
|
||||||
const queues = useMemo(() => {
|
const [selectedQueue, setSelectedQueue] = useState('')
|
||||||
|
const [selectedUser, setSelectedUser] = useState('')
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
const [users, setUsers] = useState([])
|
||||||
|
const [queues, setQueues] = useState([])
|
||||||
|
const [_queues, setQueuesByWhats] = useState([])
|
||||||
|
// const isRun = useRef(false)
|
||||||
|
|
||||||
|
const [itemHover, setItemHover] = useState(-1)
|
||||||
|
const [settings, setSettings] = useState([])
|
||||||
|
|
||||||
|
|
||||||
|
const _queues2 = useMemo(() => {
|
||||||
if (!whatsApps) return []
|
if (!whatsApps) return []
|
||||||
const whatsAppsQueues = whatsApps.map(({ queues }) => queues)
|
const whatsAppsQueues = whatsApps.map(({ queues }) => queues)
|
||||||
//const whatsAppsQueues = whatsApps.filter(({ status }) => status === "CONNECTED" ).map(({ queues }) => queues)
|
//const whatsAppsQueues = whatsApps.filter(({ status }) => status === "CONNECTED" ).map(({ queues }) => queues)
|
||||||
const uniqueQueuesAvailable = queueArraysToOneArray(whatsAppsQueues)
|
const uniqueQueuesAvailable = queueArraysToOneArray(whatsAppsQueues)
|
||||||
return uniqueQueuesAvailable
|
return uniqueQueuesAvailable
|
||||||
}, [whatsApps])
|
}, [whatsApps])
|
||||||
const [itemHover, setItemHover] = useState(-1)
|
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (isRun.current) return
|
||||||
|
// // setQueues(_queues2)
|
||||||
|
// isRun.current = true
|
||||||
|
// }, [whatsApps])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
if (selectedUser) {
|
||||||
|
|
||||||
|
let { queues } = users.find(u => +u.id === +selectedUser)
|
||||||
|
const userQueues = queues.map((q) => {
|
||||||
|
const { id, color, name } = q
|
||||||
|
return { id, color, name }
|
||||||
|
})
|
||||||
|
|
||||||
|
setQueues(userQueues)
|
||||||
|
setSelectedQueue('')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
if (settings?.find(e => e?.key === 'queueTransferByWhatsappScope')?.value === 'enabled') {
|
||||||
|
setQueues(_queues)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setQueues(_queues2)
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelectedUser('')
|
||||||
|
}
|
||||||
|
}, [selectedUser, settings, _queues2, _queues, users])
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const socket = openSocket(process.env.REACT_APP_BACKEND_URL)
|
||||||
|
|
||||||
|
socket.on('settings', (data) => {
|
||||||
|
console.log('settings updated ----------------------------xxxxxxxxxxxx')
|
||||||
|
|
||||||
|
if (data.action === 'update') {
|
||||||
|
setSettings((prevState) => {
|
||||||
|
const aux = [...prevState]
|
||||||
|
const settingIndex = aux.findIndex((s) => s.key === data.setting.key)
|
||||||
|
aux[settingIndex].value = data.setting.value
|
||||||
|
return aux
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
socket.disconnect()
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchSession = async () => {
|
||||||
|
try {
|
||||||
|
const { data } = await api.get('/settings')
|
||||||
|
|
||||||
|
setSettings(data.settings)
|
||||||
|
} catch (err) {
|
||||||
|
toastError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fetchSession()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
onClose();
|
onClose()
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleSaveTicket = async e => {
|
const handleSaveTicket = async e => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
if (!ticketid) return;
|
if (!ticketid) return
|
||||||
if (!selectedQueue) return;
|
if (!selectedQueue) return
|
||||||
setLoading(true);
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
let data = {};
|
let data = {}
|
||||||
|
|
||||||
if (selectedQueue && selectedQueue !== null) {
|
if (selectedQueue && selectedQueue !== null) {
|
||||||
data.queueId = selectedQueue
|
data.queueId = selectedQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
// test del PARA APARECER NA FILA DE OUTRO ATENDENTE E O MESMO CLICAR EM ACEITAR AO INVES DE ENVIAR PARA ATENDENDO
|
|
||||||
data.status = 'pending'
|
|
||||||
data.transfer = true
|
|
||||||
|
|
||||||
await api.put(`/tickets/${ticketid}`, data);
|
if (selectedUser) {
|
||||||
|
data.userId = selectedUser
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// test del PARA APARECER NA FILA DE OUTRO ATENDENTE E O MESMO CLICAR EM ACEITAR AO INVES DE ENVIAR PARA ATENDENDO
|
||||||
|
data.status = 'pending'
|
||||||
|
data.transfer = true
|
||||||
|
}
|
||||||
|
|
||||||
setLoading(false);
|
await api.put(`/tickets/${ticketid}`, data)
|
||||||
history.push(`/tickets`);
|
|
||||||
|
setLoading(false)
|
||||||
|
history.push(`/tickets`)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setLoading(false);
|
setLoading(false)
|
||||||
toastError(err);
|
toastError(err)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
const delayDebounceFn = setTimeout(() => {
|
||||||
|
|
||||||
|
const fetchUsers = async () => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
|
||||||
|
if (settings?.find(e => e?.key === 'queueTransferByWhatsappScope')?.value === 'enabled') {
|
||||||
|
const { data } = await api.get(`/users/all`, {
|
||||||
|
params: { userId: user.id },
|
||||||
|
})
|
||||||
|
|
||||||
|
setUsers(data.users)
|
||||||
|
setQueuesByWhats(data.queues)
|
||||||
|
setQueues(data.queues)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
const { data } = await api.get(`/users/all`, {
|
||||||
|
params: { profile: 'user' },
|
||||||
|
})
|
||||||
|
|
||||||
|
setUsers(data.users)
|
||||||
|
setQueues(_queues2)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchUsers()
|
||||||
|
|
||||||
|
}, 500)
|
||||||
|
return () => clearTimeout(delayDebounceFn)
|
||||||
|
}, [settings, _queues2, user.id])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={modalOpen} onClose={handleClose} maxWidth="lg" scroll="paper">
|
<Dialog open={modalOpen} onClose={handleClose} maxWidth="lg" scroll="paper">
|
||||||
|
@ -98,6 +230,7 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<FormControl variant="outlined" className={classes.maxWidth}>
|
<FormControl variant="outlined" className={classes.maxWidth}>
|
||||||
<InputLabel>{i18n.t("transferTicketModal.fieldQueueLabel")}</InputLabel>
|
<InputLabel>{i18n.t("transferTicketModal.fieldQueueLabel")}</InputLabel>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
value={selectedQueue}
|
value={selectedQueue}
|
||||||
onChange={(e) => setSelectedQueue(e.target.value)}
|
onChange={(e) => setSelectedQueue(e.target.value)}
|
||||||
|
@ -118,6 +251,26 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<Select
|
||||||
|
value={selectedUser}
|
||||||
|
onChange={e => setSelectedUser(e.target.value)}
|
||||||
|
label={'Transfeir para usuario'}
|
||||||
|
>
|
||||||
|
<MenuItem style={{ background: "white", }} value={''}> </MenuItem>
|
||||||
|
{users.map((user) => (
|
||||||
|
<MenuItem
|
||||||
|
key={user.id}
|
||||||
|
value={user.id}
|
||||||
|
>{user.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
|
@ -140,7 +293,7 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</form>
|
</form>
|
||||||
</Dialog >
|
</Dialog >
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default TransferTicketModal;
|
export default TransferTicketModal
|
|
@ -121,7 +121,31 @@ const UserModal = ({ open, onClose, userId }) => {
|
||||||
const userData = { ...values, queueIds: selectedQueueIds };
|
const userData = { ...values, queueIds: selectedQueueIds };
|
||||||
try {
|
try {
|
||||||
if (userId) {
|
if (userId) {
|
||||||
await api.put(`/users/${userId}`, userData);
|
|
||||||
|
const user = await api.put(`/users/${userId}`, userData);
|
||||||
|
|
||||||
|
console.log('USER: ', user.data)
|
||||||
|
|
||||||
|
|
||||||
|
if (user && user.data.userQueuesAttendance.length > 0) {
|
||||||
|
|
||||||
|
const userQueueInAttendance = user.data.userQueuesAttendance.map((e) => ({ "queue": e.queueName, "open": e.totAttendance }))
|
||||||
|
|
||||||
|
console.log('userQueueInAttendance: ', userQueueInAttendance)
|
||||||
|
|
||||||
|
let msg = '\nAVISO \n\nO atendente possui atendimento(s) em aberto na(s) fila(s) abaixo: \n\n'
|
||||||
|
|
||||||
|
userQueueInAttendance.forEach((e) => {
|
||||||
|
msg += `Fila: ${e.queue}\nAberto: ${e.open}\n\n`
|
||||||
|
})
|
||||||
|
|
||||||
|
msg += 'Para remover o atendente da(s) fila(s) acima é necessário que o mesmo encerre os atendimentos aberto(s) nessas filas.\n'
|
||||||
|
|
||||||
|
alert(msg)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
await api.post("/users", userData);
|
await api.post("/users", userData);
|
||||||
}
|
}
|
||||||
|
@ -229,6 +253,7 @@ const UserModal = ({ open, onClose, userId }) => {
|
||||||
id="profile-selection"
|
id="profile-selection"
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
|
<MenuItem value="supervisor">Supervisor</MenuItem>
|
||||||
<MenuItem value="admin">Admin</MenuItem>
|
<MenuItem value="admin">Admin</MenuItem>
|
||||||
<MenuItem value="user">User</MenuItem>
|
<MenuItem value="user">User</MenuItem>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
@ -131,7 +131,8 @@ const useAuth = () => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await api.delete('/auth/logout')
|
await api.delete(`/auth/logout/${user.id}`);
|
||||||
|
|
||||||
setIsAuth(false)
|
setIsAuth(false)
|
||||||
setUser({})
|
setUser({})
|
||||||
localStorage.removeItem('token')
|
localStorage.removeItem('token')
|
||||||
|
|
|
@ -103,20 +103,31 @@ const MainListItems = (props) => {
|
||||||
primary={i18n.t('mainDrawer.listItems.quickAnswers')}
|
primary={i18n.t('mainDrawer.listItems.quickAnswers')}
|
||||||
icon={<QuestionAnswerOutlinedIcon />}
|
icon={<QuestionAnswerOutlinedIcon />}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<Can
|
||||||
|
role={user.profile}
|
||||||
|
perform="menu-users:view"
|
||||||
|
yes={() => (
|
||||||
|
<>
|
||||||
|
<Divider />
|
||||||
|
<ListSubheader inset>{i18n.t("mainDrawer.listItems.administration")}</ListSubheader>
|
||||||
|
<ListItemLink
|
||||||
|
to="/users"
|
||||||
|
primary={i18n.t("mainDrawer.listItems.users")}
|
||||||
|
icon={<PeopleAltOutlinedIcon />}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
<Can
|
<Can
|
||||||
role={user.profile}
|
role={user.profile}
|
||||||
perform="drawer-admin-items:view"
|
perform="drawer-admin-items:view"
|
||||||
yes={() => (
|
yes={() => (
|
||||||
<>
|
<>
|
||||||
<Divider />
|
|
||||||
<ListSubheader inset>
|
|
||||||
{i18n.t('mainDrawer.listItems.administration')}
|
|
||||||
</ListSubheader>
|
|
||||||
<ListItemLink
|
|
||||||
to="/users"
|
|
||||||
primary={i18n.t('mainDrawer.listItems.users')}
|
|
||||||
icon={<PeopleAltOutlinedIcon />}
|
|
||||||
/>
|
|
||||||
<ListItemLink
|
<ListItemLink
|
||||||
to="/queues"
|
to="/queues"
|
||||||
primary={i18n.t('mainDrawer.listItems.queues')}
|
primary={i18n.t('mainDrawer.listItems.queues')}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState, useEffect, useReducer, useContext } from "react"
|
import React, { useState, useEffect, useReducer, useCallback, useContext } from "react"
|
||||||
import openSocket from "socket.io-client"
|
import openSocket from "socket.io-client"
|
||||||
import { toast } from "react-toastify"
|
import { toast } from "react-toastify"
|
||||||
import { useHistory } from "react-router-dom"
|
import { useHistory } from "react-router-dom"
|
||||||
|
@ -116,6 +116,7 @@ const Contacts = () => {
|
||||||
const [deletingContact, setDeletingContact] = useState(null)
|
const [deletingContact, setDeletingContact] = useState(null)
|
||||||
const [confirmOpen, setConfirmOpen] = useState(false)
|
const [confirmOpen, setConfirmOpen] = useState(false)
|
||||||
const [hasMore, setHasMore] = useState(false)
|
const [hasMore, setHasMore] = useState(false)
|
||||||
|
const [settings, setSettings] = useState([])
|
||||||
|
|
||||||
|
|
||||||
const [onQueueStatus, setOnQueueProcessStatus] = useState(undefined)
|
const [onQueueStatus, setOnQueueProcessStatus] = useState(undefined)
|
||||||
|
@ -161,11 +162,26 @@ const Contacts = () => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchSession = async () => {
|
||||||
|
try {
|
||||||
|
const { data } = await api.get('/settings')
|
||||||
|
|
||||||
|
setSettings(data.settings)
|
||||||
|
} catch (err) {
|
||||||
|
toastError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fetchSession()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const getSettingValue = (key) => {
|
||||||
|
const { value } = settings.find((s) => s?.key === key)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const delayDebounceFn = setTimeout(() => {
|
const delayDebounceFn = setTimeout(() => {
|
||||||
|
|
||||||
const fetchReportOnQueue = async () => {
|
const fetchReportOnQueue = async () => {
|
||||||
|
@ -301,9 +317,44 @@ const Contacts = () => {
|
||||||
setContactModalOpen(false)
|
setContactModalOpen(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handleSaveTicketOneQueue = useCallback(async (contactId, userId, queueId) => {
|
||||||
|
if (!contactId || !userId) {
|
||||||
|
console.log("Missing contactId or userId")
|
||||||
|
return
|
||||||
|
};
|
||||||
|
if (!queueId) {
|
||||||
|
toast.warning("Nenhuma Fila Selecionada")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// if (isMounted.current) setLoading(true)
|
||||||
|
try {
|
||||||
|
const { data: ticket } = await api.post("/tickets", {
|
||||||
|
contactId: contactId,
|
||||||
|
userId: userId,
|
||||||
|
queueId: queueId,
|
||||||
|
status: "open",
|
||||||
|
})
|
||||||
|
history.push(`/tickets/${ticket.id}`)
|
||||||
|
} catch (err) {
|
||||||
|
toastError(err)
|
||||||
|
}
|
||||||
|
// if (isMounted.current) setLoading(false)
|
||||||
|
}, [history])
|
||||||
|
|
||||||
const handleOpenCreateTicketModal = (contactId) => {
|
const handleOpenCreateTicketModal = (contactId) => {
|
||||||
|
|
||||||
setSelectedContactId(contactId)
|
setSelectedContactId(contactId)
|
||||||
setIsCreateTicketModalOpen(true)
|
|
||||||
|
if (getSettingValue('whatsaAppCloudApi') === 'disabled' && user?.queues?.length === 1){
|
||||||
|
handleSaveTicketOneQueue(contactId, user.id, user.queues[0].id)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
setIsCreateTicketModalOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setSelectedContactId(contactId)
|
||||||
|
// setIsCreateTicketModalOpen(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCloseCreateTicketModal = () => {
|
const handleCloseCreateTicketModal = () => {
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
import React, { useContext, useReducer, useEffect, useState } from "react";
|
import React, { useContext, useReducer, useEffect, useState } from "react"
|
||||||
|
|
||||||
import { addHours, addMinutes, addSeconds, intervalToDuration } from "date-fns";
|
import { addHours, addMinutes, addSeconds, intervalToDuration } from "date-fns"
|
||||||
|
|
||||||
import Paper from "@material-ui/core/Paper";
|
import Paper from "@material-ui/core/Paper"
|
||||||
import Container from "@material-ui/core/Container";
|
import Container from "@material-ui/core/Container"
|
||||||
import Grid from "@material-ui/core/Grid";
|
import Grid from "@material-ui/core/Grid"
|
||||||
import { makeStyles } from "@material-ui/core/styles";
|
import { makeStyles } from "@material-ui/core/styles"
|
||||||
import Typography from "@material-ui/core/Typography";
|
import Typography from "@material-ui/core/Typography"
|
||||||
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 IconButton from "@mui/material/IconButton";
|
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"
|
||||||
|
|
||||||
import { Can } from "../../components/Can";
|
import { Can } from "../../components/Can"
|
||||||
import TableUser from "../../components/DashboardUser/TableUser";
|
import TableUser from "../../components/DashboardUser/TableUser"
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
container: {
|
container: {
|
||||||
|
@ -104,7 +104,7 @@ const useStyles = makeStyles((theme) => ({
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
borderRadius: "5px",
|
borderRadius: "5px",
|
||||||
},
|
},
|
||||||
}));
|
}))
|
||||||
|
|
||||||
var _fifo
|
var _fifo
|
||||||
|
|
||||||
|
@ -136,70 +136,70 @@ const sumOnlineTimeNow = (oldOnlineTimeSum) => {
|
||||||
onlineTime = addSeconds(onlineTime, newtTime.seconds)
|
onlineTime = addSeconds(onlineTime, newtTime.seconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
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', ' ')
|
||||||
|
|
||||||
return newOnlinetime
|
return newOnlinetime
|
||||||
}
|
}
|
||||||
|
|
||||||
const reducer = (state, action) => {
|
const reducer = (state, action) => {
|
||||||
if (action.type === "DELETE_USER_STATUS") {
|
if (action.type === "DELETE_USER_STATUS") {
|
||||||
const userId = action.payload;
|
const userId = action.payload
|
||||||
|
|
||||||
const userIndex = state.findIndex((u) => `${u.id}` === `${userId}`);
|
const userIndex = state.findIndex((u) => `${u.id}` === `${userId}`)
|
||||||
|
|
||||||
if (userIndex !== -1) {
|
if (userIndex !== -1) {
|
||||||
state.splice(userIndex, 1);
|
state.splice(userIndex, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...state];
|
return [...state]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === "LOAD_QUERY") {
|
if (action.type === "LOAD_QUERY") {
|
||||||
const queries = action.payload;
|
const queries = action.payload
|
||||||
const newQueries = [];
|
const newQueries = []
|
||||||
|
|
||||||
queries.forEach((query) => {
|
queries.forEach((query) => {
|
||||||
const queryIndex = state.findIndex((q) => q.id === query.id);
|
const queryIndex = state.findIndex((q) => q.id === query.id)
|
||||||
|
|
||||||
if (queryIndex !== -1) {
|
if (queryIndex !== -1) {
|
||||||
state[queryIndex] = query;
|
state[queryIndex] = query
|
||||||
} else {
|
} else {
|
||||||
newQueries.push(query);
|
newQueries.push(query)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
return [...state, ...newQueries];
|
return [...state, ...newQueries]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === "UPDATE_STATUS_ONLINE") {
|
if (action.type === "UPDATE_STATUS_ONLINE") {
|
||||||
let onlineUser = action.payload;
|
let onlineUser = action.payload
|
||||||
let index = -1;
|
let index = -1
|
||||||
|
|
||||||
// console.log('UPDATE_STATUS_ONLINE: ', onlineUser)
|
// console.log('UPDATE_STATUS_ONLINE: ', onlineUser)
|
||||||
|
|
||||||
let onlySumOpenClosed = false;
|
let onlySumOpenClosed = false
|
||||||
|
|
||||||
if (onlineUser.sumOpen || onlineUser.sumClosed) {
|
if (onlineUser.sumOpen || onlineUser.sumClosed) {
|
||||||
index = state.findIndex(
|
index = state.findIndex(
|
||||||
(e) =>
|
(e) =>
|
||||||
(onlineUser.sumOpen && e.id === onlineUser.sumOpen.userId) ||
|
(onlineUser.sumOpen && e.id === onlineUser.sumOpen.userId) ||
|
||||||
(onlineUser.sumClosed && e.id === onlineUser.sumClosed.userId)
|
(onlineUser.sumClosed && e.id === onlineUser.sumClosed.userId)
|
||||||
);
|
)
|
||||||
|
|
||||||
onlySumOpenClosed = true;
|
onlySumOpenClosed = true
|
||||||
} else {
|
} else {
|
||||||
index = state.findIndex((e) => `${e.id}` === `${onlineUser.userId}`);
|
index = state.findIndex((e) => `${e.id}` === `${onlineUser.userId}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
if (!onlySumOpenClosed) {
|
if (!onlySumOpenClosed) {
|
||||||
if (!("statusOnline" in state[index])) {
|
if (!("statusOnline" in state[index])) {
|
||||||
state[index].statusOnline = onlineUser;
|
state[index].statusOnline = onlineUser
|
||||||
} else if ("statusOnline" in state[index]) {
|
} else if ("statusOnline" in state[index]) {
|
||||||
|
|
||||||
state[index].statusOnline["status"] = onlineUser.status;
|
state[index].statusOnline["status"] = onlineUser.status
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,6 @@ const reducer = (state, action) => {
|
||||||
|
|
||||||
if ("sumOnlineTime" in state[index]) {
|
if ("sumOnlineTime" in state[index]) {
|
||||||
|
|
||||||
// console.log(' ffffffffffffffffffffffffffff ')
|
|
||||||
state[index].sumOnlineTime.sum = onlineUser.onlineTime.split(" ")[1]
|
state[index].sumOnlineTime.sum = onlineUser.onlineTime.split(" ")[1]
|
||||||
|
|
||||||
} else if (!("sumOnlineTime" in state[index])) {
|
} else if (!("sumOnlineTime" in state[index])) {
|
||||||
|
@ -217,63 +216,63 @@ const reducer = (state, action) => {
|
||||||
state[index].sumOnlineTime = {
|
state[index].sumOnlineTime = {
|
||||||
userId: onlineUser.userId,
|
userId: onlineUser.userId,
|
||||||
sum: onlineUser.onlineTime.split(" ")[1],
|
sum: onlineUser.onlineTime.split(" ")[1],
|
||||||
};
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onlineUser.sumOpen) {
|
if (onlineUser.sumOpen) {
|
||||||
if ("sumOpen" in state[index]) {
|
if ("sumOpen" in state[index]) {
|
||||||
state[index].sumOpen["count"] = onlineUser.sumOpen.count;
|
state[index].sumOpen["count"] = onlineUser.sumOpen.count
|
||||||
} else if (!("sumOpen" in state[index])) {
|
} else if (!("sumOpen" in state[index])) {
|
||||||
state[index].sumOpen = onlineUser.sumOpen;
|
state[index].sumOpen = onlineUser.sumOpen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onlineUser.sumClosed) {
|
if (onlineUser.sumClosed) {
|
||||||
if ("sumClosed" in state[index]) {
|
if ("sumClosed" in state[index]) {
|
||||||
state[index].sumClosed["count"] = onlineUser.sumClosed.count;
|
state[index].sumClosed["count"] = onlineUser.sumClosed.count
|
||||||
} else if (!("sumClosed" in state[index])) {
|
} else if (!("sumClosed" in state[index])) {
|
||||||
state[index].sumClosed = onlineUser.sumClosed;
|
state[index].sumClosed = onlineUser.sumClosed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onlineUser.openClosedInQueue) {
|
if (onlineUser.openClosedInQueue) {
|
||||||
state[index].openClosedInQueue = onlineUser.openClosedInQueue;
|
state[index].openClosedInQueue = onlineUser.openClosedInQueue
|
||||||
}
|
}
|
||||||
if (onlineUser.openClosedOutQueue) {
|
if (onlineUser.openClosedOutQueue) {
|
||||||
state[index].openClosedOutQueue = onlineUser.openClosedOutQueue;
|
state[index].openClosedOutQueue = onlineUser.openClosedOutQueue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [...state];
|
return [...state]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === "RESET") {
|
if (action.type === "RESET") {
|
||||||
return [];
|
return []
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
const classes = useStyles();
|
const classes = useStyles()
|
||||||
const [usersOnlineInfo, dispatch] = useReducer(reducer, []);
|
const [usersOnlineInfo, dispatch] = useReducer(reducer, [])
|
||||||
const [ticketStatusChange, setStatus] = useState();
|
const [ticketStatusChange, setStatus] = useState()
|
||||||
const [ticketsStatus, setTicktsStatus] = useState({ open: 0, openAll: 0, pending: 0, closed: 0 });
|
const [ticketsStatus, setTicktsStatus] = useState({ open: 0, openAll: 0, pending: 0, closed: 0 })
|
||||||
|
|
||||||
const { user } = useContext(AuthContext);
|
const { user } = useContext(AuthContext)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch({ type: "RESET" });
|
dispatch({ type: "RESET" })
|
||||||
}, []);
|
}, [])
|
||||||
|
|
||||||
const handleLogouOnlineUser = async (userId) => {
|
const handleLogouOnlineUser = async (userId) => {
|
||||||
try {
|
try {
|
||||||
await api.get(`/users/logout/${userId}`);
|
await api.get(`/users/logout/${userId}`)
|
||||||
//toast.success(("Desloged!"));
|
//toast.success(("Desloged!"));
|
||||||
//handleDeleteRows(scheduleId)
|
//handleDeleteRows(scheduleId)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// toastError(err);
|
// toastError(err);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//setLoading(true);
|
//setLoading(true);
|
||||||
|
@ -282,26 +281,26 @@ const Dashboard = () => {
|
||||||
// setLoading(true);
|
// setLoading(true);
|
||||||
const fetchQueries = async () => {
|
const fetchQueries = async () => {
|
||||||
try {
|
try {
|
||||||
let date = new Date().toLocaleDateString("pt-BR").split("/");
|
let date = new Date().toLocaleDateString("pt-BR").split("/")
|
||||||
let dateToday = `${date[2]}-${date[1]}-${date[0]}`;
|
let dateToday = `${date[2]}-${date[1]}-${date[0]}`
|
||||||
|
|
||||||
const { data } = await api.get("/reports/user/services", {
|
const { data } = await api.get("/reports/user/services", {
|
||||||
params: { userId: null, startDate: dateToday, endDate: dateToday },
|
params: { userId: null, startDate: dateToday, endDate: dateToday },
|
||||||
});
|
})
|
||||||
|
|
||||||
// console.log('data.data: ', data.usersProfile)
|
// console.log('data.data: ', data.usersProfile)
|
||||||
|
|
||||||
dispatch({ type: "RESET" });
|
dispatch({ type: "RESET" })
|
||||||
dispatch({ type: "LOAD_QUERY", payload: data.usersProfile });
|
dispatch({ type: "LOAD_QUERY", payload: data.usersProfile })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
fetchQueries();
|
fetchQueries()
|
||||||
}, 500);
|
}, 500)
|
||||||
return () => clearTimeout(delayDebounceFn);
|
return () => clearTimeout(delayDebounceFn)
|
||||||
}, []);
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -310,7 +309,7 @@ const Dashboard = () => {
|
||||||
if (!usersOnlineInfo || usersOnlineInfo.length === 0) return
|
if (!usersOnlineInfo || usersOnlineInfo.length === 0) return
|
||||||
|
|
||||||
if (_fifo) {
|
if (_fifo) {
|
||||||
clearInterval(_fifo);
|
clearInterval(_fifo)
|
||||||
}
|
}
|
||||||
|
|
||||||
_fifo = setInterval(() => {
|
_fifo = setInterval(() => {
|
||||||
|
@ -321,7 +320,7 @@ const Dashboard = () => {
|
||||||
|
|
||||||
let onlineTimeCurrent = sumOnlineTimeNow({ onlineTime: usersOnlineInfo[i].statusOnline.onlineTime, updatedAt: usersOnlineInfo[i].statusOnline.updatedAt })
|
let onlineTimeCurrent = sumOnlineTimeNow({ onlineTime: usersOnlineInfo[i].statusOnline.onlineTime, updatedAt: usersOnlineInfo[i].statusOnline.updatedAt })
|
||||||
|
|
||||||
dispatch({ type: "UPDATE_STATUS_ONLINE", payload: { userId: usersOnlineInfo[i].id, status: usersOnlineInfo[i].statusOnline.status, onlineTime: onlineTimeCurrent } });
|
dispatch({ type: "UPDATE_STATUS_ONLINE", payload: { userId: usersOnlineInfo[i].id, status: usersOnlineInfo[i].statusOnline.status, onlineTime: onlineTimeCurrent } })
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,80 +339,81 @@ const Dashboard = () => {
|
||||||
// })
|
// })
|
||||||
|
|
||||||
|
|
||||||
}, 3000);
|
}, 3000)
|
||||||
|
|
||||||
|
|
||||||
}, [usersOnlineInfo])
|
}, [usersOnlineInfo])
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
|
const socket = openSocket(process.env.REACT_APP_BACKEND_URL)
|
||||||
|
|
||||||
socket.on("ticketStatus", (data) => {
|
socket.on("ticketStatus", (data) => {
|
||||||
if (data.action === "update") {
|
if (data.action === "update") {
|
||||||
setStatus("");
|
setStatus("")
|
||||||
setStatus(data.ticketStatus.status);
|
setStatus(data.ticketStatus.status)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
socket.on("onlineStatus", (data) => {
|
socket.on("onlineStatus", (data) => {
|
||||||
if (data.action === "logout" || data.action === "update") {
|
if (data.action === "logout" || data.action === "update") {
|
||||||
dispatch({ type: "UPDATE_STATUS_ONLINE", payload: data.userOnlineTime });
|
|
||||||
|
dispatch({ type: "UPDATE_STATUS_ONLINE", payload: data.userOnlineTime })
|
||||||
} else if (data.action === "delete") {
|
} else if (data.action === "delete") {
|
||||||
dispatch({ type: "DELETE_USER_STATUS", payload: data.userOnlineTime });
|
dispatch({ type: "DELETE_USER_STATUS", payload: data.userOnlineTime })
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
socket.on("user", (data) => {
|
socket.on("user", (data) => {
|
||||||
if (data.action === "delete") {
|
if (data.action === "delete") {
|
||||||
dispatch({ type: "DELETE_USER", payload: +data.userId });
|
dispatch({ type: "DELETE_USER", payload: +data.userId })
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
socket.disconnect();
|
socket.disconnect()
|
||||||
};
|
}
|
||||||
}, []);
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ticketStatusChange === "") return
|
if (ticketStatusChange === "") return
|
||||||
const delayDebounceFn = setTimeout(() => {
|
const delayDebounceFn = setTimeout(() => {
|
||||||
const fetchQueries = async () => {
|
const fetchQueries = async () => {
|
||||||
try {
|
try {
|
||||||
let date = new Date().toLocaleDateString("pt-BR").split("/");
|
let date = new Date().toLocaleDateString("pt-BR").split("/")
|
||||||
let dateToday = `${date[2]}-${date[1]}-${date[0]}`;
|
let dateToday = `${date[2]}-${date[1]}-${date[0]}`
|
||||||
|
|
||||||
const _open = await api.get("/tickets/count", {
|
const _open = await api.get("/tickets/count", {
|
||||||
params: { status: "open", date: dateToday },
|
params: { status: "open", date: dateToday },
|
||||||
});
|
})
|
||||||
const _closed = await api.get("/tickets/count", {
|
const _closed = await api.get("/tickets/count", {
|
||||||
params: { status: "closed", date: dateToday },
|
params: { status: "closed", date: dateToday },
|
||||||
});
|
})
|
||||||
const _pending = await api.get("/tickets/count", {
|
const _pending = await api.get("/tickets/count", {
|
||||||
params: { status: "pending" },
|
params: { status: "pending" },
|
||||||
});
|
})
|
||||||
|
|
||||||
const _openAll = await api.get("/tickets/count", {
|
const _openAll = await api.get("/tickets/count", {
|
||||||
params: { status: "open" },
|
params: { status: "open" },
|
||||||
});
|
})
|
||||||
setTicktsStatus({
|
setTicktsStatus({
|
||||||
open: _open.data.count,
|
open: _open.data.count,
|
||||||
openAll: _openAll.data.count,
|
openAll: _openAll.data.count,
|
||||||
closed: _closed.data.count,
|
closed: _closed.data.count,
|
||||||
pending: _pending.data.count,
|
pending: _pending.data.count,
|
||||||
});
|
})
|
||||||
// setOpen(_open.data.count);
|
// setOpen(_open.data.count);
|
||||||
// setClosed(_closed.data.count);
|
// setClosed(_closed.data.count);
|
||||||
// setPending(_pending.data.count);
|
// setPending(_pending.data.count);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
fetchQueries();
|
fetchQueries()
|
||||||
}, 500);
|
}, 500)
|
||||||
return () => clearTimeout(delayDebounceFn);
|
return () => clearTimeout(delayDebounceFn)
|
||||||
}, [ticketStatusChange]);
|
}, [ticketStatusChange])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Can
|
<Can
|
||||||
|
@ -602,7 +602,7 @@ const Dashboard = () => {
|
||||||
</Container>
|
</Container>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default Dashboard;
|
export default Dashboard
|
||||||
|
|
|
@ -257,6 +257,35 @@ const Settings = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className={classes.root}>
|
||||||
|
<Container className={classes.container} maxWidth="sm">
|
||||||
|
<Paper className={classes.paper}>
|
||||||
|
<Typography variant="body1">
|
||||||
|
Escopo de transferência de usuario por filas atribuidas a conexão e usuarios atribuido a filas
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
margin="dense"
|
||||||
|
variant="outlined"
|
||||||
|
native
|
||||||
|
id="queueTransferByWhatsappScope-setting"
|
||||||
|
name="queueTransferByWhatsappScope"
|
||||||
|
value={
|
||||||
|
settings &&
|
||||||
|
settings.length > 0 &&
|
||||||
|
getSettingValue('queueTransferByWhatsappScope')
|
||||||
|
}
|
||||||
|
className={classes.settingOption}
|
||||||
|
onChange={handleChangeSetting}
|
||||||
|
>
|
||||||
|
<option value="enabled">Ativado</option>
|
||||||
|
<option value="disabled">Desativado</option>
|
||||||
|
</Select>
|
||||||
|
</Paper>
|
||||||
|
</Container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -3,11 +3,20 @@ const rules = {
|
||||||
static: [],
|
static: [],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
supervisor: {
|
||||||
|
static: [
|
||||||
|
"menu-users:view",
|
||||||
|
"user-view:show",
|
||||||
|
"user-modal:editQueues"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
admin: {
|
admin: {
|
||||||
static: [
|
static: [
|
||||||
'show-icon-edit-whatsapp',
|
'show-icon-edit-whatsapp',
|
||||||
'show-icon-edit-queue',
|
'show-icon-edit-queue',
|
||||||
|
'menu-users:view',
|
||||||
'drawer-admin-items:view',
|
'drawer-admin-items:view',
|
||||||
'tickets-manager:showall',
|
'tickets-manager:showall',
|
||||||
'user-modal:editProfile',
|
'user-modal:editProfile',
|
||||||
|
@ -25,6 +34,7 @@ const rules = {
|
||||||
|
|
||||||
master: {
|
master: {
|
||||||
static: [
|
static: [
|
||||||
|
'menu-users:view',
|
||||||
'url-remote-session:show',
|
'url-remote-session:show',
|
||||||
'show-icon-edit-whatsapp',
|
'show-icon-edit-whatsapp',
|
||||||
'show-icon-add-queue',
|
'show-icon-add-queue',
|
||||||
|
|
Loading…
Reference in New Issue