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}`
|
||||
} else {
|
||||
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
|
||||
|
||||
|
||||
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 closedByUser = await ShowUserServiceReport({ startDate, endDate, ticketStatus: 'closed', userId });
|
||||
|
|
|
@ -5,6 +5,12 @@ import AuthUserService from "../services/UserServices/AuthUserService";
|
|||
import { SendRefreshToken } from "../helpers/SendRefreshToken";
|
||||
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> => {
|
||||
const { email, password } = req.body;
|
||||
|
||||
|
@ -15,6 +21,11 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
|||
|
||||
SendRefreshToken(res, refreshToken);
|
||||
|
||||
const userOnline = await createOrUpdateOnlineUserService({
|
||||
userId: serializedUser.id,
|
||||
status: "online"
|
||||
});
|
||||
|
||||
return res.status(200).json({
|
||||
token,
|
||||
user: serializedUser
|
||||
|
@ -47,5 +58,14 @@ export const remove = async (
|
|||
): Promise<Response> => {
|
||||
res.clearCookie("jrt");
|
||||
|
||||
const { userId } = req.params;
|
||||
|
||||
removeUserFromOlineList(userId);
|
||||
|
||||
const userOnline = await createOrUpdateOnlineUserService({
|
||||
userId,
|
||||
status: "offline"
|
||||
});
|
||||
|
||||
return res.send();
|
||||
};
|
||||
|
|
|
@ -64,6 +64,10 @@ import Contact from "../models/Contact";
|
|||
import BotIsOnQueue from "../helpers/BotIsOnQueue";
|
||||
import { setMessageAsRead } from "../helpers/SetMessageAsRead";
|
||||
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> => {
|
||||
const {
|
||||
|
@ -129,17 +133,17 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
|||
ticketData: { status: "open", userId: userId, queueId },
|
||||
ticketId: ticket.id
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!ticket){
|
||||
ticket = await CreateTicketService({
|
||||
contactId,
|
||||
status,
|
||||
userId,
|
||||
queueId,
|
||||
whatsappId
|
||||
});
|
||||
if (!ticket) {
|
||||
ticket = await CreateTicketService({
|
||||
contactId,
|
||||
status,
|
||||
userId,
|
||||
queueId,
|
||||
whatsappId
|
||||
});
|
||||
}
|
||||
|
||||
const io = getIO();
|
||||
|
@ -249,24 +253,88 @@ export const update = async (
|
|||
req.body.userId = null;
|
||||
}
|
||||
|
||||
console.log("REQ.BODY: ", JSON.stringify(req.body, null, 6));
|
||||
|
||||
let ticketData: TicketData = req.body;
|
||||
|
||||
if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") {
|
||||
if (ticketData.transfer) {
|
||||
const defaultWhatsapp: any = await GetDefaultWhatsApp({
|
||||
userId: ticketData.userId
|
||||
});
|
||||
const whatsappsByqueue = await ListWhatsAppsForQueueService(
|
||||
ticketData.queueId
|
||||
);
|
||||
|
||||
const _ticket: any = await Ticket.findByPk(ticketId);
|
||||
if (userOldInfo) {
|
||||
let listTicketOpenPending: any = [];
|
||||
|
||||
if (defaultWhatsapp && ticketData.status != "open") {
|
||||
await CheckContactOpenTickets(
|
||||
_ticket.dataValues.contactId,
|
||||
defaultWhatsapp.dataValues.id
|
||||
);
|
||||
for (const w of whatsappsByqueue) {
|
||||
let whats = await ListWhatsAppsNumber(w.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 DeleteUserService from "../services/UserServices/DeleteUserService";
|
||||
|
||||
import ListUserParamiterService from "../services/UserServices/ListUserParamiterService"
|
||||
import ListUser from "../services/UserServices/ListUserParamiterService";
|
||||
import User from "../models/User";
|
||||
|
||||
import { startWhoIsOnlineMonitor, stopWhoIsOnlineMonitor } from "../helpers/WhoIsOnlineMonitor"
|
||||
import UserOnlineTIme from '../models/UserOnlineTime'
|
||||
import {
|
||||
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 = {
|
||||
searchParam: string;
|
||||
pageNumber: string;
|
||||
profile?: string;
|
||||
userId: string;
|
||||
};
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
if (req.user.profile !== 'master') {
|
||||
|
||||
if (req.user.profile !== "master") {
|
||||
let auxUsers: Array<object> = [];
|
||||
|
||||
// for (var user of users) {
|
||||
// if (user.profile !== 'master') {
|
||||
// auxUsers.push(user)
|
||||
// }
|
||||
// }
|
||||
|
||||
for (var user of users) {
|
||||
if (user.profile !== 'master') {
|
||||
auxUsers.push(user)
|
||||
if (user.profile !== "master") {
|
||||
if (req.user.profile == "supervisor" && user.profile == "admin")
|
||||
continue;
|
||||
|
||||
auxUsers.push(user);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,34 +66,80 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
|
|||
|
||||
return res.json({ users, count, hasMore });
|
||||
|
||||
|
||||
|
||||
// const { users, count, hasMore } = await ListUsersService({
|
||||
// searchParam,
|
||||
// pageNumber
|
||||
// });
|
||||
|
||||
// if(req.user.profile!=='master'){
|
||||
// if(req.user.profile!=='master'){
|
||||
|
||||
// let auxUsers: Array<object> = [];
|
||||
// let auxUsers: Array<object> = [];
|
||||
|
||||
// for (var user of users) {
|
||||
// for (var user of users) {
|
||||
// if(user.profile!=='master'){
|
||||
// auxUsers.push(user)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return res.json({ users: auxUsers, count, hasMore });
|
||||
// }
|
||||
// return res.json({ users: auxUsers, 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> => {
|
||||
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);
|
||||
} else if (req.url !== "/signup" && req.user.profile !== "master") {
|
||||
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||
|
@ -93,9 +159,8 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
|||
user
|
||||
});
|
||||
|
||||
|
||||
// await stopWhoIsOnlineMonitor()
|
||||
await startWhoIsOnlineMonitor()
|
||||
await startWhoIsOnlineMonitor();
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
export const logoutUser = async (req: Request, res: Response): Promise<Response> => {
|
||||
export const logoutUser = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<Response> => {
|
||||
const { userId } = req.params;
|
||||
|
||||
|
||||
await stopWhoIsOnlineMonitor()
|
||||
await stopWhoIsOnlineMonitor();
|
||||
|
||||
let onlineTime = {
|
||||
userId: userId,
|
||||
status: 'logout...'
|
||||
}
|
||||
status: "logout..."
|
||||
};
|
||||
|
||||
const io = getIO();
|
||||
io.emit("onlineStatus", {
|
||||
|
@ -126,25 +192,73 @@ export const logoutUser = async (req: Request, res: Response): Promise<Response>
|
|||
userOnlineTime: onlineTime
|
||||
});
|
||||
|
||||
await startWhoIsOnlineMonitor()
|
||||
await startWhoIsOnlineMonitor();
|
||||
//
|
||||
|
||||
return res.status(200).json({});
|
||||
};
|
||||
|
||||
|
||||
export const update = async (
|
||||
req: Request,
|
||||
res: 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);
|
||||
}
|
||||
|
||||
const { userId } = req.params;
|
||||
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();
|
||||
io.emit("user", {
|
||||
|
@ -152,6 +266,8 @@ export const update = async (
|
|||
user
|
||||
});
|
||||
|
||||
user.userQueuesAttendance = userQueuesAttendance;
|
||||
|
||||
return res.status(200).json(user);
|
||||
};
|
||||
|
||||
|
@ -165,26 +281,23 @@ export const remove = async (
|
|||
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||
}
|
||||
|
||||
|
||||
await DeleteUserService(userId);
|
||||
|
||||
|
||||
const io = getIO();
|
||||
io.emit("user", {
|
||||
action: "delete",
|
||||
userId
|
||||
});
|
||||
|
||||
|
||||
//test del
|
||||
await stopWhoIsOnlineMonitor()
|
||||
//test del
|
||||
await stopWhoIsOnlineMonitor();
|
||||
|
||||
io.emit("onlineStatus", {
|
||||
action: "delete",
|
||||
userOnlineTime: userId
|
||||
});
|
||||
|
||||
await startWhoIsOnlineMonitor()
|
||||
await startWhoIsOnlineMonitor();
|
||||
//
|
||||
|
||||
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 ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber";
|
||||
import { getSettingValue } from "./WhaticketSettings";
|
||||
import ListWhatsAppsForQueueService from "../services/WhatsappService/ListWhatsAppsForQueueService";
|
||||
|
||||
const CheckContactOpenTickets = async (
|
||||
contactId: number,
|
||||
whatsappId: number | string
|
||||
): Promise<void> => {
|
||||
whatsappId: number | string,
|
||||
handle?: boolean
|
||||
): Promise<void | any> => {
|
||||
let ticket;
|
||||
|
||||
if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") {
|
||||
let whats = await ListWhatsAppsNumber(whatsappId);
|
||||
|
||||
console.log("contactId: ", contactId, " | whatsappId: ", whatsappId);
|
||||
|
||||
console.log("WHATS: ", JSON.stringify(whats, null, 6));
|
||||
|
||||
ticket = await Ticket.findOne({
|
||||
where: {
|
||||
[Op.and]: [
|
||||
|
@ -22,6 +28,8 @@ const CheckContactOpenTickets = async (
|
|||
]
|
||||
}
|
||||
});
|
||||
|
||||
console.log("TICKET: ", JSON.stringify(ticket, null, 6));
|
||||
} else {
|
||||
ticket = await Ticket.findOne({
|
||||
where: { contactId, status: { [Op.or]: ["open", "pending"] } }
|
||||
|
@ -29,8 +37,12 @@ const CheckContactOpenTickets = async (
|
|||
}
|
||||
|
||||
if (ticket) {
|
||||
if (handle) return true;
|
||||
|
||||
throw new AppError("ERR_OTHER_OPEN_TICKET");
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
export default CheckContactOpenTickets;
|
||||
|
|
|
@ -67,7 +67,7 @@ const monitor = async () => {
|
|||
|
||||
const usersSocket = require('./../libs/socket');
|
||||
|
||||
if (usersSocket.ob) {
|
||||
if (usersSocket?.ob) {
|
||||
|
||||
if (count > 1) {
|
||||
count = 0
|
||||
|
@ -81,7 +81,7 @@ const monitor = async () => {
|
|||
if (uuid) {
|
||||
if (uuid == usersSocket.ob.uuid) {
|
||||
|
||||
console.log('ALL USERS CLIENTS OFFLINE 1...........')
|
||||
console.log('ALL USERS CLIENTS OFFLINE 1...........')
|
||||
|
||||
usersSocket.ob.listOnline = []
|
||||
usersSocket.ob.listOnlineAux = []
|
||||
|
@ -103,7 +103,7 @@ const monitor = async () => {
|
|||
|
||||
const userOnline = await createOrUpdateOnlineUserService({ userId: el.id, status: 'online' })
|
||||
|
||||
if (userOnline) {
|
||||
if (userOnline) {
|
||||
|
||||
el.onlineTime = userOnline.onlineTime
|
||||
el.updatedAt = userOnline.updatedAt,
|
||||
|
|
|
@ -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 });
|
||||
|
||||
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;
|
||||
} else {
|
||||
|
@ -154,7 +154,7 @@ export const initIO = (httpServer: Server): SocketIO => {
|
|||
if (index == -1) {
|
||||
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;
|
||||
} else {
|
||||
|
|
|
@ -11,6 +11,6 @@ authRoutes.post("/login", SessionController.store);
|
|||
|
||||
authRoutes.post("/refresh_token", SessionController.update);
|
||||
|
||||
authRoutes.delete("/logout", isAuth, SessionController.remove);
|
||||
authRoutes.delete("/logout/:userId", isAuth, SessionController.remove);
|
||||
|
||||
export default authRoutes;
|
||||
|
|
|
@ -6,6 +6,8 @@ import * as UserController from "../controllers/UserController";
|
|||
const userRoutes = Router();
|
||||
|
||||
|
||||
userRoutes.get("/users/all", isAuth, UserController.all);
|
||||
|
||||
userRoutes.get("/users", isAuth, UserController.index);
|
||||
|
||||
userRoutes.post("/users", isAuth, UserController.store);
|
||||
|
|
|
@ -16,6 +16,8 @@ import { createOrUpdateTicketCache } from "../../helpers/TicketCache";
|
|||
import User from "../../models/User";
|
||||
import whatsappQueueMatchingUserQueue from "../../helpers/whatsappQueueMatchingUserQueue";
|
||||
import Whatsapp from "../../models/Whatsapp";
|
||||
import ListWhatsAppsForQueueService from "../WhatsappService/ListWhatsAppsForQueueService";
|
||||
import { json } from "sequelize";
|
||||
let flatten = require("flat");
|
||||
|
||||
interface Request {
|
||||
|
@ -42,6 +44,27 @@ const CreateTicketService = async ({
|
|||
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));
|
||||
// throw new AppError("test error");
|
||||
|
||||
|
@ -59,6 +82,13 @@ const CreateTicketService = async ({
|
|||
queueId = matchingQueue ? matchingQueue.queueId : undefined;
|
||||
}
|
||||
|
||||
console.log(
|
||||
"xxxxxxxxxxxx contactId: ",
|
||||
contactId,
|
||||
" | defaultWhatsapp.id: ",
|
||||
defaultWhatsapp.id
|
||||
);
|
||||
|
||||
await CheckContactOpenTickets(contactId, defaultWhatsapp.id);
|
||||
|
||||
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 Queue from "../../models/Queue";
|
||||
import User from "../../models/User";
|
||||
|
@ -7,65 +6,44 @@ import UserQueue from "../../models/UserQueue";
|
|||
interface Request {
|
||||
userId?: string | number;
|
||||
profile?: string;
|
||||
raw?: boolean;
|
||||
userIds?: string | number
|
||||
}
|
||||
|
||||
|
||||
const ListUser = async ({ profile, userId }: Request): Promise<User[]> => {
|
||||
|
||||
let where_clause = {}
|
||||
const ListUser = async ({ profile, userId, raw, userIds }: Request): Promise<User[]> => {
|
||||
let where_clause = {};
|
||||
|
||||
if (userId && profile) {
|
||||
where_clause = {
|
||||
[Op.and]: [
|
||||
{ userId: userId },
|
||||
{ profile: profile }
|
||||
]
|
||||
}
|
||||
}
|
||||
else if (userId) {
|
||||
[Op.and]: [{ userId: userId }, { profile: profile }]
|
||||
};
|
||||
} else if (userId) {
|
||||
where_clause = {
|
||||
[Op.and]: [
|
||||
{ userId: userId },
|
||||
]
|
||||
}
|
||||
}
|
||||
else if (profile) {
|
||||
[Op.and]: [{ userId: userId }]
|
||||
};
|
||||
} else if (profile) {
|
||||
where_clause = {
|
||||
profile: profile
|
||||
}
|
||||
};
|
||||
} else if (userIds) {
|
||||
where_clause = {
|
||||
id: { [Op.in]: userIds }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const users = await User.findAll({
|
||||
where: where_clause,
|
||||
raw: true,
|
||||
attributes: ['id', 'name', 'email'],
|
||||
|
||||
raw,
|
||||
attributes: ["id", "name", "email"],
|
||||
|
||||
// include: [
|
||||
// {
|
||||
// model: UserQueue,
|
||||
// separate: true,
|
||||
|
||||
// attributes: ['id',],
|
||||
|
||||
// order: [
|
||||
// ['createdAt', 'ASC']
|
||||
// ]
|
||||
// },
|
||||
// ],
|
||||
|
||||
|
||||
|
||||
order: [["id", "ASC"]],
|
||||
})
|
||||
include: [
|
||||
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] }
|
||||
],
|
||||
|
||||
order: [["id", "ASC"]]
|
||||
});
|
||||
|
||||
return users;
|
||||
};
|
||||
|
||||
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) {
|
||||
setSelectedContact(newValue);
|
||||
} 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 { useHistory } from "react-router-dom";
|
||||
import React, { useState, useContext, useMemo, useEffect } from "react"
|
||||
import { useHistory } from "react-router-dom"
|
||||
import openSocket from "socket.io-client"
|
||||
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Dialog from "@material-ui/core/Dialog";
|
||||
import Select from "@material-ui/core/Select";
|
||||
import FormControl from "@material-ui/core/FormControl";
|
||||
import InputLabel from "@material-ui/core/InputLabel";
|
||||
import MenuItem from "@material-ui/core/MenuItem";
|
||||
import { makeStyles } from "@material-ui/core";
|
||||
import Button from "@material-ui/core/Button"
|
||||
import Dialog from "@material-ui/core/Dialog"
|
||||
import Select from "@material-ui/core/Select"
|
||||
import FormControl from "@material-ui/core/FormControl"
|
||||
import InputLabel from "@material-ui/core/InputLabel"
|
||||
import MenuItem from "@material-ui/core/MenuItem"
|
||||
import { makeStyles } from "@material-ui/core"
|
||||
|
||||
import DialogActions from "@material-ui/core/DialogActions";
|
||||
import DialogContent from "@material-ui/core/DialogContent";
|
||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||
import DialogActions from "@material-ui/core/DialogActions"
|
||||
import DialogContent from "@material-ui/core/DialogContent"
|
||||
import DialogTitle from "@material-ui/core/DialogTitle"
|
||||
|
||||
import { i18n } from "../../translate/i18n";
|
||||
import api from "../../services/api";
|
||||
import ButtonWithSpinner from "../ButtonWithSpinner";
|
||||
import toastError from "../../errors/toastError";
|
||||
import { i18n } from "../../translate/i18n"
|
||||
import api from "../../services/api"
|
||||
import ButtonWithSpinner from "../ButtonWithSpinner"
|
||||
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) => ({
|
||||
maxWidth: {
|
||||
width: "100%",
|
||||
},
|
||||
}));
|
||||
}))
|
||||
|
||||
// Receive array of queues arrays
|
||||
// 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 history = useHistory();
|
||||
const { whatsApps } = useContext(WhatsAppsContext);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [selectedQueue, setSelectedQueue] = useState('');
|
||||
const classes = useStyles();
|
||||
const queues = useMemo(() => {
|
||||
if (!whatsApps) return []
|
||||
const history = useHistory()
|
||||
const { whatsApps } = useContext(WhatsAppsContext)
|
||||
const { user } = useContext(AuthContext)
|
||||
|
||||
const [loading, setLoading] = useState(false)
|
||||
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 []
|
||||
const whatsAppsQueues = whatsApps.map(({ queues }) => queues)
|
||||
//const whatsAppsQueues = whatsApps.filter(({ status }) => status === "CONNECTED" ).map(({ queues }) => queues)
|
||||
const uniqueQueuesAvailable = queueArraysToOneArray(whatsAppsQueues)
|
||||
return uniqueQueuesAvailable
|
||||
}, [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 = () => {
|
||||
onClose();
|
||||
};
|
||||
onClose()
|
||||
}
|
||||
|
||||
const handleSaveTicket = async e => {
|
||||
e.preventDefault();
|
||||
if (!ticketid) return;
|
||||
if (!selectedQueue) return;
|
||||
setLoading(true);
|
||||
e.preventDefault()
|
||||
if (!ticketid) return
|
||||
if (!selectedQueue) return
|
||||
setLoading(true)
|
||||
try {
|
||||
let data = {};
|
||||
let data = {}
|
||||
|
||||
if (selectedQueue && selectedQueue !== null) {
|
||||
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);
|
||||
history.push(`/tickets`);
|
||||
await api.put(`/tickets/${ticketid}`, data)
|
||||
|
||||
setLoading(false)
|
||||
history.push(`/tickets`)
|
||||
} catch (err) {
|
||||
setLoading(false);
|
||||
toastError(err);
|
||||
setLoading(false)
|
||||
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 (
|
||||
<Dialog open={modalOpen} onClose={handleClose} maxWidth="lg" scroll="paper">
|
||||
|
@ -98,6 +230,7 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
|
|||
<DialogContent dividers>
|
||||
<FormControl variant="outlined" className={classes.maxWidth}>
|
||||
<InputLabel>{i18n.t("transferTicketModal.fieldQueueLabel")}</InputLabel>
|
||||
|
||||
<Select
|
||||
value={selectedQueue}
|
||||
onChange={(e) => setSelectedQueue(e.target.value)}
|
||||
|
@ -118,6 +251,26 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
|
|||
</MenuItem>
|
||||
))}
|
||||
</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>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
|
@ -140,7 +293,7 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
|
|||
</DialogActions>
|
||||
</form>
|
||||
</Dialog >
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default TransferTicketModal;
|
||||
export default TransferTicketModal
|
|
@ -121,7 +121,31 @@ const UserModal = ({ open, onClose, userId }) => {
|
|||
const userData = { ...values, queueIds: selectedQueueIds };
|
||||
try {
|
||||
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 {
|
||||
await api.post("/users", userData);
|
||||
}
|
||||
|
@ -229,6 +253,7 @@ const UserModal = ({ open, onClose, userId }) => {
|
|||
id="profile-selection"
|
||||
required
|
||||
>
|
||||
<MenuItem value="supervisor">Supervisor</MenuItem>
|
||||
<MenuItem value="admin">Admin</MenuItem>
|
||||
<MenuItem value="user">User</MenuItem>
|
||||
</Field>
|
||||
|
|
|
@ -130,8 +130,9 @@ const useAuth = () => {
|
|||
const handleLogout = async () => {
|
||||
setLoading(true)
|
||||
|
||||
try {
|
||||
await api.delete('/auth/logout')
|
||||
try {
|
||||
await api.delete(`/auth/logout/${user.id}`);
|
||||
|
||||
setIsAuth(false)
|
||||
setUser({})
|
||||
localStorage.removeItem('token')
|
||||
|
|
|
@ -103,20 +103,31 @@ const MainListItems = (props) => {
|
|||
primary={i18n.t('mainDrawer.listItems.quickAnswers')}
|
||||
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
|
||||
role={user.profile}
|
||||
perform="drawer-admin-items:view"
|
||||
yes={() => (
|
||||
<>
|
||||
<Divider />
|
||||
<ListSubheader inset>
|
||||
{i18n.t('mainDrawer.listItems.administration')}
|
||||
</ListSubheader>
|
||||
<ListItemLink
|
||||
to="/users"
|
||||
primary={i18n.t('mainDrawer.listItems.users')}
|
||||
icon={<PeopleAltOutlinedIcon />}
|
||||
/>
|
||||
|
||||
<ListItemLink
|
||||
to="/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 { toast } from "react-toastify"
|
||||
import { useHistory } from "react-router-dom"
|
||||
|
@ -116,6 +116,7 @@ const Contacts = () => {
|
|||
const [deletingContact, setDeletingContact] = useState(null)
|
||||
const [confirmOpen, setConfirmOpen] = useState(false)
|
||||
const [hasMore, setHasMore] = useState(false)
|
||||
const [settings, setSettings] = useState([])
|
||||
|
||||
|
||||
const [onQueueStatus, setOnQueueProcessStatus] = useState(undefined)
|
||||
|
@ -161,10 +162,25 @@ 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(() => {
|
||||
|
||||
const delayDebounceFn = setTimeout(() => {
|
||||
|
||||
|
@ -301,9 +317,44 @@ const Contacts = () => {
|
|||
setContactModalOpen(false)
|
||||
}
|
||||
|
||||
const handleOpenCreateTicketModal = (contactId) => {
|
||||
|
||||
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) => {
|
||||
|
||||
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 = () => {
|
||||
|
|
|
@ -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 Container from "@material-ui/core/Container";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Zoom from "@mui/material/Zoom";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import Info from "@material-ui/icons/Info";
|
||||
import Paper from "@material-ui/core/Paper"
|
||||
import Container from "@material-ui/core/Container"
|
||||
import Grid from "@material-ui/core/Grid"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import Typography from "@material-ui/core/Typography"
|
||||
import Tooltip from "@mui/material/Tooltip"
|
||||
import Zoom from "@mui/material/Zoom"
|
||||
import IconButton from "@mui/material/IconButton"
|
||||
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 Chart from "./Chart";
|
||||
import openSocket from "socket.io-client";
|
||||
import api from "../../services/api";
|
||||
import Chart from "./Chart"
|
||||
import openSocket from "socket.io-client"
|
||||
import api from "../../services/api"
|
||||
|
||||
import { Can } from "../../components/Can";
|
||||
import TableUser from "../../components/DashboardUser/TableUser";
|
||||
import { Can } from "../../components/Can"
|
||||
import TableUser from "../../components/DashboardUser/TableUser"
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
container: {
|
||||
|
@ -104,15 +104,15 @@ const useStyles = makeStyles((theme) => ({
|
|||
textAlign: "center",
|
||||
borderRadius: "5px",
|
||||
},
|
||||
}));
|
||||
}))
|
||||
|
||||
var _fifo
|
||||
|
||||
const sumOnlineTimeNow = (oldOnlineTimeSum) => {
|
||||
const sumOnlineTimeNow = (oldOnlineTimeSum) => {
|
||||
|
||||
let onlineTime = new Date()
|
||||
|
||||
if (!oldOnlineTimeSum.onlineTime) {
|
||||
if (!oldOnlineTimeSum.onlineTime) {
|
||||
|
||||
oldOnlineTimeSum.onlineTime = `${oldOnlineTimeSum.updatedAt.split(' ')[0]} 00:00:00`
|
||||
|
||||
|
@ -136,70 +136,70 @@ const sumOnlineTimeNow = (oldOnlineTimeSum) => {
|
|||
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
|
||||
}
|
||||
|
||||
const reducer = (state, action) => {
|
||||
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) {
|
||||
state.splice(userIndex, 1);
|
||||
state.splice(userIndex, 1)
|
||||
}
|
||||
|
||||
return [...state];
|
||||
return [...state]
|
||||
}
|
||||
|
||||
if (action.type === "LOAD_QUERY") {
|
||||
const queries = action.payload;
|
||||
const newQueries = [];
|
||||
const queries = action.payload
|
||||
const newQueries = []
|
||||
|
||||
queries.forEach((query) => {
|
||||
const queryIndex = state.findIndex((q) => q.id === query.id);
|
||||
const queryIndex = state.findIndex((q) => q.id === query.id)
|
||||
|
||||
if (queryIndex !== -1) {
|
||||
state[queryIndex] = query;
|
||||
state[queryIndex] = query
|
||||
} else {
|
||||
newQueries.push(query);
|
||||
newQueries.push(query)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
return [...state, ...newQueries];
|
||||
return [...state, ...newQueries]
|
||||
}
|
||||
|
||||
if (action.type === "UPDATE_STATUS_ONLINE") {
|
||||
let onlineUser = action.payload;
|
||||
let index = -1;
|
||||
let onlineUser = action.payload
|
||||
let index = -1
|
||||
|
||||
// console.log('UPDATE_STATUS_ONLINE: ', onlineUser)
|
||||
|
||||
let onlySumOpenClosed = false;
|
||||
let onlySumOpenClosed = false
|
||||
|
||||
if (onlineUser.sumOpen || onlineUser.sumClosed) {
|
||||
index = state.findIndex(
|
||||
(e) =>
|
||||
(onlineUser.sumOpen && e.id === onlineUser.sumOpen.userId) ||
|
||||
(onlineUser.sumClosed && e.id === onlineUser.sumClosed.userId)
|
||||
);
|
||||
)
|
||||
|
||||
onlySumOpenClosed = true;
|
||||
onlySumOpenClosed = true
|
||||
} else {
|
||||
index = state.findIndex((e) => `${e.id}` === `${onlineUser.userId}`);
|
||||
index = state.findIndex((e) => `${e.id}` === `${onlineUser.userId}`)
|
||||
}
|
||||
|
||||
if (index !== -1) {
|
||||
if (!onlySumOpenClosed) {
|
||||
if (!("statusOnline" in state[index])) {
|
||||
state[index].statusOnline = onlineUser;
|
||||
state[index].statusOnline = onlineUser
|
||||
} else if ("statusOnline" in state[index]) {
|
||||
|
||||
state[index].statusOnline["status"] = onlineUser.status;
|
||||
state[index].statusOnline["status"] = onlineUser.status
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -207,73 +207,72 @@ const reducer = (state, action) => {
|
|||
|
||||
if ("onlineTime" in onlineUser) {
|
||||
|
||||
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])) {
|
||||
|
||||
state[index].sumOnlineTime = {
|
||||
userId: onlineUser.userId,
|
||||
sum: onlineUser.onlineTime.split(" ")[1],
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (onlineUser.sumOpen) {
|
||||
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])) {
|
||||
state[index].sumOpen = onlineUser.sumOpen;
|
||||
state[index].sumOpen = onlineUser.sumOpen
|
||||
}
|
||||
}
|
||||
|
||||
if (onlineUser.sumClosed) {
|
||||
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])) {
|
||||
state[index].sumClosed = onlineUser.sumClosed;
|
||||
state[index].sumClosed = onlineUser.sumClosed
|
||||
}
|
||||
}
|
||||
|
||||
if (onlineUser.openClosedInQueue) {
|
||||
state[index].openClosedInQueue = onlineUser.openClosedInQueue;
|
||||
state[index].openClosedInQueue = onlineUser.openClosedInQueue
|
||||
}
|
||||
if (onlineUser.openClosedOutQueue) {
|
||||
state[index].openClosedOutQueue = onlineUser.openClosedOutQueue;
|
||||
state[index].openClosedOutQueue = onlineUser.openClosedOutQueue
|
||||
}
|
||||
}
|
||||
return [...state];
|
||||
return [...state]
|
||||
}
|
||||
|
||||
if (action.type === "RESET") {
|
||||
return [];
|
||||
return []
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const Dashboard = () => {
|
||||
const classes = useStyles();
|
||||
const [usersOnlineInfo, dispatch] = useReducer(reducer, []);
|
||||
const [ticketStatusChange, setStatus] = useState();
|
||||
const [ticketsStatus, setTicktsStatus] = useState({ open: 0, openAll: 0, pending: 0, closed: 0 });
|
||||
const classes = useStyles()
|
||||
const [usersOnlineInfo, dispatch] = useReducer(reducer, [])
|
||||
const [ticketStatusChange, setStatus] = useState()
|
||||
const [ticketsStatus, setTicktsStatus] = useState({ open: 0, openAll: 0, pending: 0, closed: 0 })
|
||||
|
||||
const { user } = useContext(AuthContext);
|
||||
const { user } = useContext(AuthContext)
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({ type: "RESET" });
|
||||
}, []);
|
||||
dispatch({ type: "RESET" })
|
||||
}, [])
|
||||
|
||||
const handleLogouOnlineUser = async (userId) => {
|
||||
try {
|
||||
await api.get(`/users/logout/${userId}`);
|
||||
await api.get(`/users/logout/${userId}`)
|
||||
//toast.success(("Desloged!"));
|
||||
//handleDeleteRows(scheduleId)
|
||||
} catch (err) {
|
||||
// toastError(err);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
//setLoading(true);
|
||||
|
@ -282,26 +281,26 @@ const Dashboard = () => {
|
|||
// setLoading(true);
|
||||
const fetchQueries = async () => {
|
||||
try {
|
||||
let date = new Date().toLocaleDateString("pt-BR").split("/");
|
||||
let dateToday = `${date[2]}-${date[1]}-${date[0]}`;
|
||||
let date = new Date().toLocaleDateString("pt-BR").split("/")
|
||||
let dateToday = `${date[2]}-${date[1]}-${date[0]}`
|
||||
|
||||
const { data } = await api.get("/reports/user/services", {
|
||||
params: { userId: null, startDate: dateToday, endDate: dateToday },
|
||||
});
|
||||
})
|
||||
|
||||
// console.log('data.data: ', data.usersProfile)
|
||||
|
||||
dispatch({ type: "RESET" });
|
||||
dispatch({ type: "LOAD_QUERY", payload: data.usersProfile });
|
||||
dispatch({ type: "RESET" })
|
||||
dispatch({ type: "LOAD_QUERY", payload: data.usersProfile })
|
||||
} catch (err) {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fetchQueries();
|
||||
}, 500);
|
||||
return () => clearTimeout(delayDebounceFn);
|
||||
}, []);
|
||||
fetchQueries()
|
||||
}, 500)
|
||||
return () => clearTimeout(delayDebounceFn)
|
||||
}, [])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -310,18 +309,18 @@ const Dashboard = () => {
|
|||
if (!usersOnlineInfo || usersOnlineInfo.length === 0) return
|
||||
|
||||
if (_fifo) {
|
||||
clearInterval(_fifo);
|
||||
clearInterval(_fifo)
|
||||
}
|
||||
|
||||
_fifo = setInterval(() => {
|
||||
|
||||
for (let i = 0; i < usersOnlineInfo.length; i++) {
|
||||
|
||||
if (usersOnlineInfo[i].statusOnline && usersOnlineInfo[i].statusOnline.status === 'online') {
|
||||
|
||||
let onlineTimeCurrent = sumOnlineTimeNow({ onlineTime: usersOnlineInfo[i].statusOnline.onlineTime, updatedAt: usersOnlineInfo[i].statusOnline.updatedAt })
|
||||
if (usersOnlineInfo[i].statusOnline && usersOnlineInfo[i].statusOnline.status === 'online') {
|
||||
|
||||
dispatch({ type: "UPDATE_STATUS_ONLINE", payload: { userId: usersOnlineInfo[i].id, status: usersOnlineInfo[i].statusOnline.status, onlineTime: onlineTimeCurrent } });
|
||||
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 } })
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -340,80 +339,81 @@ const Dashboard = () => {
|
|||
// })
|
||||
|
||||
|
||||
}, 3000);
|
||||
}, 3000)
|
||||
|
||||
|
||||
}, [usersOnlineInfo])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
|
||||
const socket = openSocket(process.env.REACT_APP_BACKEND_URL)
|
||||
|
||||
socket.on("ticketStatus", (data) => {
|
||||
if (data.action === "update") {
|
||||
setStatus("");
|
||||
setStatus(data.ticketStatus.status);
|
||||
setStatus("")
|
||||
setStatus(data.ticketStatus.status)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
socket.on("onlineStatus", (data) => {
|
||||
if (data.action === "logout" || data.action === "update") {
|
||||
dispatch({ type: "UPDATE_STATUS_ONLINE", payload: data.userOnlineTime });
|
||||
if (data.action === "logout" || data.action === "update") {
|
||||
|
||||
dispatch({ type: "UPDATE_STATUS_ONLINE", payload: data.userOnlineTime })
|
||||
} else if (data.action === "delete") {
|
||||
dispatch({ type: "DELETE_USER_STATUS", payload: data.userOnlineTime });
|
||||
dispatch({ type: "DELETE_USER_STATUS", payload: data.userOnlineTime })
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
socket.on("user", (data) => {
|
||||
if (data.action === "delete") {
|
||||
dispatch({ type: "DELETE_USER", payload: +data.userId });
|
||||
dispatch({ type: "DELETE_USER", payload: +data.userId })
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
return () => {
|
||||
socket.disconnect();
|
||||
};
|
||||
}, []);
|
||||
socket.disconnect()
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (ticketStatusChange === "") return
|
||||
const delayDebounceFn = setTimeout(() => {
|
||||
const fetchQueries = async () => {
|
||||
try {
|
||||
let date = new Date().toLocaleDateString("pt-BR").split("/");
|
||||
let dateToday = `${date[2]}-${date[1]}-${date[0]}`;
|
||||
let date = new Date().toLocaleDateString("pt-BR").split("/")
|
||||
let dateToday = `${date[2]}-${date[1]}-${date[0]}`
|
||||
|
||||
const _open = await api.get("/tickets/count", {
|
||||
params: { status: "open", date: dateToday },
|
||||
});
|
||||
})
|
||||
const _closed = await api.get("/tickets/count", {
|
||||
params: { status: "closed", date: dateToday },
|
||||
});
|
||||
})
|
||||
const _pending = await api.get("/tickets/count", {
|
||||
params: { status: "pending" },
|
||||
});
|
||||
})
|
||||
|
||||
const _openAll = await api.get("/tickets/count", {
|
||||
params: { status: "open" },
|
||||
});
|
||||
})
|
||||
setTicktsStatus({
|
||||
open: _open.data.count,
|
||||
openAll: _openAll.data.count,
|
||||
closed: _closed.data.count,
|
||||
pending: _pending.data.count,
|
||||
});
|
||||
})
|
||||
// setOpen(_open.data.count);
|
||||
// setClosed(_closed.data.count);
|
||||
// setPending(_pending.data.count);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log(err)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fetchQueries();
|
||||
}, 500);
|
||||
return () => clearTimeout(delayDebounceFn);
|
||||
}, [ticketStatusChange]);
|
||||
fetchQueries()
|
||||
}, 500)
|
||||
return () => clearTimeout(delayDebounceFn)
|
||||
}, [ticketStatusChange])
|
||||
|
||||
return (
|
||||
<Can
|
||||
|
@ -602,7 +602,7 @@ const Dashboard = () => {
|
|||
</Container>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default Dashboard;
|
||||
export default Dashboard
|
||||
|
|
|
@ -257,6 +257,35 @@ const Settings = () => {
|
|||
</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>
|
||||
)}
|
||||
/>
|
||||
|
|
|
@ -3,11 +3,20 @@ const rules = {
|
|||
static: [],
|
||||
},
|
||||
|
||||
supervisor: {
|
||||
static: [
|
||||
"menu-users:view",
|
||||
"user-view:show",
|
||||
"user-modal:editQueues"
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
admin: {
|
||||
static: [
|
||||
'show-icon-edit-whatsapp',
|
||||
'show-icon-edit-queue',
|
||||
|
||||
'menu-users:view',
|
||||
'drawer-admin-items:view',
|
||||
'tickets-manager:showall',
|
||||
'user-modal:editProfile',
|
||||
|
@ -25,6 +34,7 @@ const rules = {
|
|||
|
||||
master: {
|
||||
static: [
|
||||
'menu-users:view',
|
||||
'url-remote-session:show',
|
||||
'show-icon-edit-whatsapp',
|
||||
'show-icon-add-queue',
|
||||
|
|
Loading…
Reference in New Issue