Compare commits
No commits in common. "6baca795c3b3735398cdf59cf885571e9fe5afcc" and "e71150ff75dbb52d544e3be9f89fb082bb61a2c7" have entirely different histories.
6baca795c3
...
e71150ff75
|
@ -8,7 +8,6 @@
|
||||||
"watch": "tsc -w",
|
"watch": "tsc -w",
|
||||||
"start": "nodemon --expose-gc dist/server.js",
|
"start": "nodemon --expose-gc dist/server.js",
|
||||||
"dev:server": "ts-node-dev --respawn --transpile-only --ignore node_modules src/server.ts",
|
"dev:server": "ts-node-dev --respawn --transpile-only --ignore node_modules src/server.ts",
|
||||||
"dev": "nodemon --exec npm run dev:server",
|
|
||||||
"pretest": "NODE_ENV=test sequelize db:migrate && NODE_ENV=test sequelize db:seed:all",
|
"pretest": "NODE_ENV=test sequelize db:migrate && NODE_ENV=test sequelize db:seed:all",
|
||||||
"test": "NODE_ENV=test jest",
|
"test": "NODE_ENV=test jest",
|
||||||
"posttest": "NODE_ENV=test sequelize db:migrate:undo:all"
|
"posttest": "NODE_ENV=test sequelize db:migrate:undo:all"
|
||||||
|
|
|
@ -66,7 +66,7 @@ export const reportUserByDateStartDateEnd = async (
|
||||||
endDate,
|
endDate,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
createdOrUpdated,
|
createdOrUpdated,
|
||||||
queueId,
|
queueId
|
||||||
});
|
});
|
||||||
|
|
||||||
const queues = await Queue.findAll({ attributes: ["id", "name"] });
|
const queues = await Queue.findAll({ attributes: ["id", "name"] });
|
||||||
|
@ -85,12 +85,11 @@ export const reportUserService = async (
|
||||||
) {
|
) {
|
||||||
throw new AppError("ERR_NO_PERMISSION", 403);
|
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||||
}
|
}
|
||||||
const { userId, startDate, endDate, userQueues} = 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({
|
let usersProfile = await ListUserParamiterService({
|
||||||
profiles: ["user", "supervisor"],
|
profiles: ["user", "supervisor"],
|
||||||
userQueues: userQueues ? userQueues : undefined,
|
|
||||||
raw: true
|
raw: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -358,18 +357,15 @@ export const reportTicksCountByStatusChatEnds = async (
|
||||||
throw new AppError("ERR_NO_PERMISSION", 403);
|
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { startDate, endDate, userQueues } = req.query as IndexQuery;
|
const { startDate, endDate } = req.query as IndexQuery;
|
||||||
|
|
||||||
const dateToday = splitDateTime(
|
const dateToday = splitDateTime(
|
||||||
new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR }))
|
new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR }))
|
||||||
);
|
);
|
||||||
|
|
||||||
const queueIds = userQueues ? userQueues.map(queue => parseInt(queue)) : [];
|
|
||||||
|
|
||||||
const reportStatusChatEnd = await CountStatusChatEndService(
|
const reportStatusChatEnd = await CountStatusChatEndService(
|
||||||
startDate || dateToday.fullDate,
|
startDate || dateToday.fullDate,
|
||||||
endDate || dateToday.fullDate,
|
endDate || dateToday.fullDate
|
||||||
queueIds
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.status(200).json({ reportStatusChatEnd });
|
return res.status(200).json({ reportStatusChatEnd });
|
||||||
|
|
|
@ -409,8 +409,9 @@ export const show = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
|
||||||
export const count = async (req: Request, res: Response): Promise<Response> => {
|
export const count = async (req: Request, res: Response): Promise<Response> => {
|
||||||
// type indexQ = { status: string; date?: string; };
|
// type indexQ = { status: string; date?: string; };
|
||||||
const { status, date, queueIds } = req.query as IndexQuery;
|
const { status, date } = req.query as IndexQuery;
|
||||||
const ticketCount = await CountTicketService(status, date, queueIds);
|
|
||||||
|
const ticketCount = await CountTicketService(status, date);
|
||||||
|
|
||||||
return res.status(200).json(ticketCount);
|
return res.status(200).json(ticketCount);
|
||||||
};
|
};
|
||||||
|
|
|
@ -100,7 +100,7 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||||
// };
|
// };
|
||||||
|
|
||||||
export const all = async (req: Request, res: Response): Promise<Response> => {
|
export const all = async (req: Request, res: Response): Promise<Response> => {
|
||||||
let { userId, profile, transferToOtherQueues }: any = req.query as IndexQuery;
|
let { userId, profile }: any = req.query as IndexQuery;
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
"userId: ",
|
"userId: ",
|
||||||
|
@ -111,7 +111,7 @@ export const all = async (req: Request, res: Response): Promise<Response> => {
|
||||||
getSettingValue("queueTransferByWhatsappScope")?.value
|
getSettingValue("queueTransferByWhatsappScope")?.value
|
||||||
);
|
);
|
||||||
|
|
||||||
if (getSettingValue("queueTransferByWhatsappScope")?.value == "enabled" && !transferToOtherQueues) {
|
if (getSettingValue("queueTransferByWhatsappScope")?.value == "enabled") {
|
||||||
if (!userId) return res.json({ users: [], queues: [] });
|
if (!userId) return res.json({ users: [], queues: [] });
|
||||||
|
|
||||||
const obj = await ListUserByWhatsappQueuesService(
|
const obj = await ListUserByWhatsappQueuesService(
|
||||||
|
@ -145,8 +145,7 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
profile,
|
profile,
|
||||||
positionCompany,
|
positionCompany,
|
||||||
positionId,
|
positionId,
|
||||||
queueIds,
|
queueIds
|
||||||
transferToOtherQueues
|
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
console.log("===========> req.url: ", req.url);
|
console.log("===========> req.url: ", req.url);
|
||||||
|
@ -173,8 +172,7 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
positionCompany,
|
positionCompany,
|
||||||
positionId,
|
positionId,
|
||||||
profile,
|
profile,
|
||||||
queueIds,
|
queueIds
|
||||||
transferToOtherQueues
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { QueryInterface, DataTypes } from "sequelize";
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
up: (queryInterface: QueryInterface) => {
|
|
||||||
return queryInterface.addColumn("Users", "transferToOtherQueues", {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
down: (queryInterface: QueryInterface) => {
|
|
||||||
return queryInterface.removeColumn("Users", "transferToOtherQueues");
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,22 +0,0 @@
|
||||||
import { QueryInterface } from "sequelize";
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
up: (queryInterface: QueryInterface) => {
|
|
||||||
return queryInterface.bulkInsert(
|
|
||||||
"Settings",
|
|
||||||
[
|
|
||||||
{
|
|
||||||
key: "blockAudioVideoMedia",
|
|
||||||
value: "disabled",
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
}
|
|
||||||
],
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
down: (queryInterface: QueryInterface) => {
|
|
||||||
return queryInterface.bulkDelete("Settings", {});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,22 +0,0 @@
|
||||||
import { QueryInterface } from "sequelize";
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
up: (queryInterface: QueryInterface) => {
|
|
||||||
return queryInterface.bulkInsert(
|
|
||||||
"Settings",
|
|
||||||
[
|
|
||||||
{
|
|
||||||
key: "waitingTimeTickets",
|
|
||||||
value: "disabled",
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
}
|
|
||||||
],
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
down: (queryInterface: QueryInterface) => {
|
|
||||||
return queryInterface.bulkDelete("Settings", {});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,22 +0,0 @@
|
||||||
import { QueryInterface } from "sequelize";
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
up: (queryInterface: QueryInterface) => {
|
|
||||||
return queryInterface.bulkInsert(
|
|
||||||
"Settings",
|
|
||||||
[
|
|
||||||
{
|
|
||||||
key: "notificationTransferQueue",
|
|
||||||
value: "disabled",
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
}
|
|
||||||
],
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
down: (queryInterface: QueryInterface) => {
|
|
||||||
return queryInterface.bulkDelete("Settings", {});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -51,9 +51,6 @@ class User extends Model<User> {
|
||||||
@Column
|
@Column
|
||||||
secondaryId: string;
|
secondaryId: string;
|
||||||
|
|
||||||
@Column
|
|
||||||
transferToOtherQueues: boolean;
|
|
||||||
|
|
||||||
@Default("admin")
|
@Default("admin")
|
||||||
@Column
|
@Column
|
||||||
profile: string;
|
profile: string;
|
||||||
|
|
|
@ -11,29 +11,15 @@ const { QueryTypes } = require("sequelize");
|
||||||
|
|
||||||
const CountStatusChatEndService = async (
|
const CountStatusChatEndService = async (
|
||||||
startDate: string,
|
startDate: string,
|
||||||
endDate: string,
|
endDate: string
|
||||||
queueIds?: number[]
|
|
||||||
) => {
|
) => {
|
||||||
let countStatusChatEnd: any
|
|
||||||
|
|
||||||
if(queueIds && queueIds.length > 0){
|
const countStatusChatEnd: any = await sequelize.query(
|
||||||
countStatusChatEnd = await sequelize.query(
|
|
||||||
`select t.id, s.name, count(t.id) as count from Tickets t join StatusChatEnds s on
|
|
||||||
t.statusChatEndId = s.id and DATE(t.createdAt) BETWEEN '${startDate} 00:00:00.000000' AND '${endDate} 23:59:59.999999'
|
|
||||||
AND t.queueId IN (${queueIds})
|
|
||||||
group by s.id;`,
|
|
||||||
{ type: QueryTypes.SELECT }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
countStatusChatEnd = await sequelize.query(
|
|
||||||
`select t.id, s.name, count(t.id) as count from Tickets t join StatusChatEnds s on
|
`select t.id, s.name, count(t.id) as count from Tickets t join StatusChatEnds s on
|
||||||
t.statusChatEndId = s.id and DATE(t.createdAt) BETWEEN '${startDate} 00:00:00.000000' AND '${endDate} 23:59:59.999999'
|
t.statusChatEndId = s.id and DATE(t.createdAt) BETWEEN '${startDate} 00:00:00.000000' AND '${endDate} 23:59:59.999999'
|
||||||
group by s.id;`,
|
group by s.id;`,
|
||||||
{ type: QueryTypes.SELECT }
|
{ type: QueryTypes.SELECT }
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return countStatusChatEnd;
|
return countStatusChatEnd;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,7 @@ import ptBR from 'date-fns/locale/pt-BR';
|
||||||
import { splitDateTime } from "../../helpers/SplitDateTime";
|
import { splitDateTime } from "../../helpers/SplitDateTime";
|
||||||
const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR })))
|
const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR })))
|
||||||
|
|
||||||
const CountTicketService = async (status: string, date?: string, queueIds?: string): Promise<any> => {
|
const CountTicketService = async (status: string, date?: string): Promise<any> => {
|
||||||
|
|
||||||
let where_clause = {}
|
let where_clause = {}
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@ const CountTicketService = async (status: string, date?: string, queueIds?: stri
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if(queueIds) where_clause = { ...where_clause, status: status, queueId: { [Op.or]: [queueIds, null] } };
|
|
||||||
else where_clause = { ...where_clause, status: status};
|
where_clause = { ...where_clause, status: status }
|
||||||
|
|
||||||
const ticket = await Ticket.findAll({
|
const ticket = await Ticket.findAll({
|
||||||
where: where_clause,
|
where: where_clause,
|
||||||
|
|
|
@ -257,8 +257,7 @@ const ListTicketsService = async ({
|
||||||
whereCondition = {
|
whereCondition = {
|
||||||
createdAt: {
|
createdAt: {
|
||||||
[Op.between]: [+startOfDay(parseISO(date)), +endOfDay(parseISO(date))]
|
[Op.between]: [+startOfDay(parseISO(date)), +endOfDay(parseISO(date))]
|
||||||
},
|
}
|
||||||
queueId: { [Op.or]: [queueIds, null] },
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,6 @@ const ShowTicketReport = async ({
|
||||||
"id",
|
"id",
|
||||||
"status",
|
"status",
|
||||||
"statusChatEnd",
|
"statusChatEnd",
|
||||||
"isRemote",
|
|
||||||
[
|
[
|
||||||
Sequelize.fn(
|
Sequelize.fn(
|
||||||
"DATE_FORMAT",
|
"DATE_FORMAT",
|
||||||
|
|
|
@ -14,7 +14,6 @@ interface Request {
|
||||||
queueIds?: number[];
|
queueIds?: number[];
|
||||||
profile?: string;
|
profile?: string;
|
||||||
ignoreThrow?: boolean;
|
ignoreThrow?: boolean;
|
||||||
transferToOtherQueues?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Response {
|
interface Response {
|
||||||
|
@ -24,7 +23,6 @@ interface Response {
|
||||||
positionId: string;
|
positionId: string;
|
||||||
id: number;
|
id: number;
|
||||||
profile: string;
|
profile: string;
|
||||||
transferToOtherQueues: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CreateUserService = async ({
|
const CreateUserService = async ({
|
||||||
|
@ -35,8 +33,7 @@ const CreateUserService = async ({
|
||||||
positionId,
|
positionId,
|
||||||
queueIds = [],
|
queueIds = [],
|
||||||
profile = "master",
|
profile = "master",
|
||||||
ignoreThrow = false,
|
ignoreThrow = false
|
||||||
transferToOtherQueues
|
|
||||||
}: Request): Promise<Response | any> => {
|
}: Request): Promise<Response | any> => {
|
||||||
try {
|
try {
|
||||||
const schema = Yup.object().shape({
|
const schema = Yup.object().shape({
|
||||||
|
@ -87,8 +84,7 @@ const CreateUserService = async ({
|
||||||
name,
|
name,
|
||||||
positionCompany,
|
positionCompany,
|
||||||
positionId: !positionId ? null : positionId,
|
positionId: !positionId ? null : positionId,
|
||||||
profile,
|
profile
|
||||||
transferToOtherQueues: transferToOtherQueues? transferToOtherQueues : false
|
|
||||||
},
|
},
|
||||||
{ include: ["queues"] }
|
{ include: ["queues"] }
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,7 +10,6 @@ interface Request {
|
||||||
profiles?: Array<string>;
|
profiles?: Array<string>;
|
||||||
raw?: boolean;
|
raw?: boolean;
|
||||||
userIds?: string | number;
|
userIds?: string | number;
|
||||||
userQueues?: string[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ListUser = async ({
|
const ListUser = async ({
|
||||||
|
@ -18,31 +17,10 @@ const ListUser = async ({
|
||||||
userId,
|
userId,
|
||||||
raw,
|
raw,
|
||||||
userIds,
|
userIds,
|
||||||
profiles,
|
profiles
|
||||||
userQueues: userQueuesToNumber
|
|
||||||
}: Request): Promise<User[]> => {
|
}: Request): Promise<User[]> => {
|
||||||
let where_clause = {};
|
let where_clause = {};
|
||||||
let userIdInQueues: number[] = [];
|
|
||||||
|
|
||||||
if(userQueuesToNumber !== undefined){
|
|
||||||
let userQueues = userQueuesToNumber.map(id => parseInt(id));
|
|
||||||
const userQueuesFiltered = await UserQueue.findAll({
|
|
||||||
where: { queueId: { [Op.or]: [userQueues, null] } },
|
|
||||||
order: [
|
|
||||||
['userId', 'ASC']
|
|
||||||
],
|
|
||||||
raw: true
|
|
||||||
});
|
|
||||||
if(userQueuesFiltered) for(let queueId of userQueues){
|
|
||||||
for(let userQueue of userQueuesFiltered){
|
|
||||||
if(queueId == userQueue.queueId){
|
|
||||||
const isAlready = userIdInQueues.indexOf(userQueue.userId);
|
|
||||||
|
|
||||||
if(isAlready === -1) userIdInQueues.push(userQueue.userId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (userId && profile) {
|
if (userId && profile) {
|
||||||
where_clause = {
|
where_clause = {
|
||||||
[Op.and]: [{ userId: userId }, { profile: profile }]
|
[Op.and]: [{ userId: userId }, { profile: profile }]
|
||||||
|
@ -59,23 +37,16 @@ const ListUser = async ({
|
||||||
where_clause = {
|
where_clause = {
|
||||||
id: { [Op.in]: userIds }
|
id: { [Op.in]: userIds }
|
||||||
};
|
};
|
||||||
}
|
} else if (profiles) {
|
||||||
else if (profiles && userIdInQueues.length > 0) {
|
|
||||||
where_clause = {
|
where_clause = {
|
||||||
profile: { [Op.in]: profiles },
|
profile: { [Op.in]: profiles }
|
||||||
id: {[Op.in]: userIdInQueues}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (profiles) {
|
|
||||||
where_clause = {
|
|
||||||
profile: { [Op.in]: profiles },
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const users = await User.findAll({
|
const users = await User.findAll({
|
||||||
where: where_clause,
|
where: where_clause,
|
||||||
raw,
|
raw,
|
||||||
attributes: ["id", "name", "email", "positionCompany", "transferToOtherQueues"],
|
attributes: ["id", "name", "email", "positionCompany"],
|
||||||
|
|
||||||
include: [
|
include: [
|
||||||
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] }
|
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] }
|
||||||
|
|
|
@ -66,8 +66,7 @@ const ListUsersService = async ({
|
||||||
"email",
|
"email",
|
||||||
"positionCompany",
|
"positionCompany",
|
||||||
"profile",
|
"profile",
|
||||||
"createdAt",
|
"createdAt"
|
||||||
"transferToOtherQueues"
|
|
||||||
],
|
],
|
||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
|
|
|
@ -12,8 +12,7 @@ const ShowUserService = async (id: string | number): Promise<User> => {
|
||||||
"profile",
|
"profile",
|
||||||
"positionCompany",
|
"positionCompany",
|
||||||
"positionId",
|
"positionId",
|
||||||
"tokenVersion",
|
"tokenVersion"
|
||||||
"transferToOtherQueues"
|
|
||||||
],
|
],
|
||||||
include: [
|
include: [
|
||||||
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] },
|
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] },
|
||||||
|
|
|
@ -12,7 +12,6 @@ interface UserData {
|
||||||
positionId?: string;
|
positionId?: string;
|
||||||
profile?: string;
|
profile?: string;
|
||||||
queueIds?: number[];
|
queueIds?: number[];
|
||||||
transferToOtherQueues?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Request {
|
interface Request {
|
||||||
|
@ -76,8 +75,7 @@ const UpdateUserService = async ({
|
||||||
name,
|
name,
|
||||||
positionCompany,
|
positionCompany,
|
||||||
positionId,
|
positionId,
|
||||||
queueIds = [],
|
queueIds = []
|
||||||
transferToOtherQueues
|
|
||||||
} = userData;
|
} = userData;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -92,8 +90,7 @@ const UpdateUserService = async ({
|
||||||
profile,
|
profile,
|
||||||
positionCompany,
|
positionCompany,
|
||||||
positionId: !positionId ? null : positionId,
|
positionId: !positionId ? null : positionId,
|
||||||
name,
|
name
|
||||||
transferToOtherQueues
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await user.$set("queues", queueIds);
|
await user.$set("queues", queueIds);
|
||||||
|
@ -120,8 +117,7 @@ const UpdateUserService = async ({
|
||||||
profile: _user.profile,
|
profile: _user.profile,
|
||||||
queues: _user.queues,
|
queues: _user.queues,
|
||||||
positionId: _user?.positionId,
|
positionId: _user?.positionId,
|
||||||
position: _user.position,
|
position: _user.position
|
||||||
transferToOtherQueues: _user.transferToOtherQueues
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return serializedUser;
|
return serializedUser;
|
||||||
|
|
|
@ -170,7 +170,7 @@ const verifyMediaMessage = async (
|
||||||
if (!media) {
|
if (!media) {
|
||||||
throw new Error("ERR_WAPP_DOWNLOAD_MEDIA");
|
throw new Error("ERR_WAPP_DOWNLOAD_MEDIA");
|
||||||
}
|
}
|
||||||
let mediaAuthorized = true;
|
|
||||||
let messageData = {
|
let messageData = {
|
||||||
id: msg.id.id,
|
id: msg.id.id,
|
||||||
ticketId: ticket.id,
|
ticketId: ticket.id,
|
||||||
|
@ -184,9 +184,7 @@ const verifyMediaMessage = async (
|
||||||
phoneNumberId: msg?.phoneNumberId,
|
phoneNumberId: msg?.phoneNumberId,
|
||||||
fromAgent: false
|
fromAgent: false
|
||||||
};
|
};
|
||||||
if(messageData.mediaType === 'video' || messageData.mediaType === 'audio' && getSettingValue('blockAudioVideoMedia')?.value === 'enabled'){
|
|
||||||
mediaAuthorized = false;
|
|
||||||
}
|
|
||||||
if (msg?.fromMe) {
|
if (msg?.fromMe) {
|
||||||
messageData = { ...messageData, fromAgent: true };
|
messageData = { ...messageData, fromAgent: true };
|
||||||
}
|
}
|
||||||
|
@ -201,36 +199,23 @@ const verifyMediaMessage = async (
|
||||||
body: media.filename
|
body: media.filename
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if(mediaAuthorized){
|
|
||||||
try {
|
try {
|
||||||
await writeFileAsync(
|
await writeFileAsync(
|
||||||
join(__dirname, "..", "..", "..", "..", "..", "public", media.filename),
|
join(__dirname, "..", "..", "..", "..", "..", "public", media.filename),
|
||||||
media.data,
|
media.data,
|
||||||
"base64"
|
"base64"
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.captureException(err);
|
|
||||||
logger.error(`There was an error: wbotMessageLitener.ts: ${err}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(mediaAuthorized){
|
|
||||||
await ticket.update({ lastMessage: msg.body || media.filename });
|
|
||||||
const newMessage = await CreateMessageService({ messageData });
|
|
||||||
return newMessage;
|
|
||||||
}else{
|
|
||||||
if (ticket.status !== "queueChoice") {
|
|
||||||
botSendMessage(
|
|
||||||
ticket,
|
|
||||||
`Atenção! Mensagem ignorada, tipo de mídia não suportado.`
|
|
||||||
);
|
);
|
||||||
|
} catch (err) {
|
||||||
|
Sentry.captureException(err);
|
||||||
|
logger.error(`There was an error: wbotMessageLitener.ts: ${err}`);
|
||||||
}
|
}
|
||||||
messageData.body = `Mensagem de *${messageData.mediaType}* ignorada, tipo de mídia não suportado.`;
|
|
||||||
messageData.mediaUrl = '';
|
|
||||||
await ticket.update({ lastMessage: `Mensagem de *${messageData.mediaType}* ignorada, tipo de mídia não suportado.`});
|
|
||||||
const newMessage = await CreateMessageService({ messageData });
|
|
||||||
console.log(`--------->>> Mensagem do tipo: ${messageData.mediaType}, ignorada!`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await ticket.update({ lastMessage: msg.body || media.filename });
|
||||||
|
const newMessage = await CreateMessageService({ messageData });
|
||||||
|
|
||||||
|
return newMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
// const verifyMediaMessage = async (
|
// const verifyMediaMessage = async (
|
||||||
|
@ -428,15 +413,13 @@ const verifyQueue = async (
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = "";
|
let body = "";
|
||||||
const io = getIO();
|
|
||||||
if (botOptions.length > 0) {
|
if (botOptions.length > 0) {
|
||||||
body = `\u200e${choosenQueue.greetingMessage}\n\n${botOptions}\n${final_message.msg}`;
|
body = `\u200e${choosenQueue.greetingMessage}\n\n${botOptions}\n${final_message.msg}`;
|
||||||
} else {
|
} else {
|
||||||
body = `\u200e${choosenQueue.greetingMessage}`;
|
body = `\u200e${choosenQueue.greetingMessage}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
io.emit('notifyPeding', {data: {ticket, queue: choosenQueue}});
|
|
||||||
|
|
||||||
sendWhatsAppMessageSocket(ticket, body);
|
sendWhatsAppMessageSocket(ticket, body);
|
||||||
} else {
|
} else {
|
||||||
//test del transfere o atendimento se entrar na ura infinita
|
//test del transfere o atendimento se entrar na ura infinita
|
||||||
|
|
|
@ -34,7 +34,7 @@ import whatsBackground from "../../assets/wa-background.png"
|
||||||
|
|
||||||
import api from "../../services/api"
|
import api from "../../services/api"
|
||||||
import toastError from "../../errors/toastError"
|
import toastError from "../../errors/toastError"
|
||||||
import { countTicketMsgContext } from "../../context/CountTicketMsgProvider/CountTicketMsgProvider"
|
import { CountTicketMsgProvider, countTicketMsgContext } from "../../context/CountTicketMsgProvider/CountTicketMsgProvider"
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
messagesListWrapper: {
|
messagesListWrapper: {
|
||||||
|
|
|
@ -20,9 +20,6 @@ import useTickets from "../../hooks/useTickets"
|
||||||
import alertSound from "../../assets/sound.mp3"
|
import alertSound from "../../assets/sound.mp3"
|
||||||
import { AuthContext } from "../../context/Auth/AuthContext"
|
import { AuthContext } from "../../context/Auth/AuthContext"
|
||||||
|
|
||||||
import api from "../../services/api";
|
|
||||||
import toastError from "../../errors/toastError";
|
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
tabContainer: {
|
tabContainer: {
|
||||||
overflowY: "auto",
|
overflowY: "auto",
|
||||||
|
@ -86,7 +83,7 @@ const NotificationsPopOver = () => {
|
||||||
const historyRef = useRef(history)
|
const historyRef = useRef(history)
|
||||||
|
|
||||||
const { handleLogout } = useContext(AuthContext)
|
const { handleLogout } = useContext(AuthContext)
|
||||||
const [settings, setSettings] = useState([]);
|
|
||||||
// const [lastRef] = useState(+history.location.pathname.split("/")[2])
|
// const [lastRef] = useState(+history.location.pathname.split("/")[2])
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,22 +110,7 @@ const NotificationsPopOver = () => {
|
||||||
ticketIdRef.current = ticketIdUrl
|
ticketIdRef.current = ticketIdUrl
|
||||||
}, [ticketIdUrl])
|
}, [ticketIdUrl])
|
||||||
|
|
||||||
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(() => {
|
||||||
|
|
||||||
|
@ -273,80 +255,49 @@ const NotificationsPopOver = () => {
|
||||||
|
|
||||||
if (shouldNotNotificate) return
|
if (shouldNotNotificate) return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
handleNotifications(data)
|
handleNotifications(data)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on('notifyPeding', data =>{
|
|
||||||
if(settings?.length > 0 && getSettingValue('notificationTransferQueue') === 'enabled') handleNotifications("", data);
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
socket.disconnect()
|
socket.disconnect()
|
||||||
}
|
}
|
||||||
}, [user, settings])
|
}, [user])
|
||||||
|
|
||||||
const handleNotifications = (data, notify) => {
|
const handleNotifications = data => {
|
||||||
let isQueue = false;
|
const { message, contact, ticket } = data
|
||||||
if(!notify){
|
|
||||||
const { message, contact, ticket } = data
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
body: `${message.body} - ${format(new Date(), "HH:mm")}`,
|
body: `${message.body} - ${format(new Date(), "HH:mm")}`,
|
||||||
icon: contact.profilePicUrl,
|
icon: contact.profilePicUrl,
|
||||||
tag: ticket.id,
|
tag: ticket.id,
|
||||||
renotify: true,
|
renotify: true,
|
||||||
}
|
|
||||||
|
|
||||||
const notification = new Notification(
|
|
||||||
`${i18n.t("tickets.notification.message")} ${contact.name}`,
|
|
||||||
options
|
|
||||||
)
|
|
||||||
|
|
||||||
notification.onclick = e => {
|
|
||||||
e.preventDefault()
|
|
||||||
window.focus()
|
|
||||||
historyRef.current.push(`/tickets/${ticket.id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
setDesktopNotifications(prevState => {
|
|
||||||
const notfiticationIndex = prevState.findIndex(
|
|
||||||
n => n.tag === notification.tag
|
|
||||||
)
|
|
||||||
if (notfiticationIndex !== -1) {
|
|
||||||
prevState[notfiticationIndex] = notification
|
|
||||||
return [...prevState]
|
|
||||||
}
|
|
||||||
return [notification, ...prevState]
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
user.queues.forEach(queue =>{
|
|
||||||
if(queue.id === notify.data?.queue?.id){
|
|
||||||
isQueue = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if(!isQueue){
|
|
||||||
return;
|
|
||||||
}else {
|
|
||||||
const notification = new Notification(`${i18n.t("tickets.notification.messagePeding")} ${notify.data?.queue?.name}`);
|
|
||||||
notification.onclick = e => {
|
|
||||||
e.preventDefault()
|
|
||||||
window.focus()
|
|
||||||
historyRef.current.push(`/tickets`)
|
|
||||||
}
|
|
||||||
|
|
||||||
setDesktopNotifications(prevState => {
|
|
||||||
const notfiticationIndex = prevState.findIndex(
|
|
||||||
n => n.tag === notification.tag
|
|
||||||
)
|
|
||||||
if (notfiticationIndex !== -1) {
|
|
||||||
prevState[notfiticationIndex] = notification
|
|
||||||
return [...prevState]
|
|
||||||
}
|
|
||||||
return [notification, ...prevState]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const notification = new Notification(
|
||||||
|
`${i18n.t("tickets.notification.message")} ${contact.name}`,
|
||||||
|
options
|
||||||
|
)
|
||||||
|
|
||||||
|
notification.onclick = e => {
|
||||||
|
e.preventDefault()
|
||||||
|
window.focus()
|
||||||
|
historyRef.current.push(`/tickets/${ticket.id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
setDesktopNotifications(prevState => {
|
||||||
|
const notfiticationIndex = prevState.findIndex(
|
||||||
|
n => n.tag === notification.tag
|
||||||
|
)
|
||||||
|
if (notfiticationIndex !== -1) {
|
||||||
|
prevState[notfiticationIndex] = notification
|
||||||
|
return [...prevState]
|
||||||
|
}
|
||||||
|
return [notification, ...prevState]
|
||||||
|
})
|
||||||
|
|
||||||
soundAlertRef.current()
|
soundAlertRef.current()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,19 +10,11 @@ const SelectTextFields = (props) => {
|
||||||
if (!props.textBoxFieldSelected) {
|
if (!props.textBoxFieldSelected) {
|
||||||
props.currencies.push({ 'value': 0, 'label': '' })
|
props.currencies.push({ 'value': 0, 'label': '' })
|
||||||
}
|
}
|
||||||
|
|
||||||
if(props.textBoxFieldSelected === 'All'){
|
|
||||||
const already = props.currencies.findIndex(obj => obj.value === 'All');
|
|
||||||
if (already === -1) {
|
|
||||||
props.currencies.push({ 'value': 'All', 'label': 'All' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
props.func(currency)
|
props.func(currency)
|
||||||
|
|
||||||
}, [currency, props.textBoxFieldSelected])
|
}, [currency, props])
|
||||||
|
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { AuthContext } from "../../context/Auth/AuthContext"
|
||||||
|
|
||||||
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket"
|
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket"
|
||||||
import { Divider } from "@material-ui/core"
|
import { Divider } from "@material-ui/core"
|
||||||
import { ticketsContext } from "../../context/TicketsProvider/TicketsProvider"
|
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
ticketsListWrapper: {
|
ticketsListWrapper: {
|
||||||
|
@ -194,8 +193,6 @@ const TicketsList = (props) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSettings(setting)
|
setSettings(setting)
|
||||||
}, [setting])
|
}, [setting])
|
||||||
const { setTickets } = useContext(ticketsContext)
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
@ -349,12 +346,6 @@ const TicketsList = (props) => {
|
||||||
if (typeof updateCount === "function") {
|
if (typeof updateCount === "function") {
|
||||||
updateCount(ticketsList.length)
|
updateCount(ticketsList.length)
|
||||||
}
|
}
|
||||||
if (ticketsList && status === "pending"){
|
|
||||||
setTickets(ticketsList)
|
|
||||||
}
|
|
||||||
// else{
|
|
||||||
// setTickets([])
|
|
||||||
// }
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [ticketsList])
|
}, [ticketsList])
|
||||||
|
|
||||||
|
|
|
@ -1,45 +1,38 @@
|
||||||
import React, { useContext, useEffect, useRef, useState } from "react"
|
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
import { makeStyles } from "@material-ui/core/styles"
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
import { IconButton } from "@mui/material"
|
import { IconButton } from "@mui/material";
|
||||||
import Paper from "@material-ui/core/Paper"
|
import Paper from "@material-ui/core/Paper";
|
||||||
import InputBase from "@material-ui/core/InputBase"
|
import InputBase from "@material-ui/core/InputBase";
|
||||||
import Tabs from "@material-ui/core/Tabs"
|
import Tabs from "@material-ui/core/Tabs";
|
||||||
import Tab from "@material-ui/core/Tab"
|
import Tab from "@material-ui/core/Tab";
|
||||||
import Badge from "@material-ui/core/Badge"
|
import Badge from "@material-ui/core/Badge";
|
||||||
|
|
||||||
import Tooltip from "@material-ui/core/Tooltip"
|
import Tooltip from "@material-ui/core/Tooltip";
|
||||||
|
|
||||||
|
|
||||||
import SearchIcon from "@material-ui/icons/Search"
|
import SearchIcon from "@material-ui/icons/Search";
|
||||||
import MoveToInboxIcon from "@material-ui/icons/MoveToInbox"
|
import MoveToInboxIcon from "@material-ui/icons/MoveToInbox";
|
||||||
import CheckBoxIcon from "@material-ui/icons/CheckBox"
|
import CheckBoxIcon from "@material-ui/icons/CheckBox";
|
||||||
import MenuIcon from "@material-ui/icons/Menu"
|
import MenuIcon from "@material-ui/icons/Menu";
|
||||||
import FindInPageIcon from '@material-ui/icons/FindInPage'
|
import FindInPageIcon from '@material-ui/icons/FindInPage';
|
||||||
|
|
||||||
import FormControlLabel from "@material-ui/core/FormControlLabel"
|
import FormControlLabel from "@material-ui/core/FormControlLabel";
|
||||||
import Switch from "@material-ui/core/Switch"
|
import Switch from "@material-ui/core/Switch";
|
||||||
import openSocket from "socket.io-client"
|
|
||||||
|
|
||||||
import NewTicketModal from "../NewTicketModal"
|
import NewTicketModal from "../NewTicketModal";
|
||||||
import TicketsList from "../TicketsList"
|
import TicketsList from "../TicketsList";
|
||||||
import TabPanel from "../TabPanel"
|
import TabPanel from "../TabPanel";
|
||||||
|
|
||||||
import { i18n } from "../../translate/i18n"
|
import { i18n } from "../../translate/i18n";
|
||||||
import { AuthContext } from "../../context/Auth/AuthContext"
|
import { AuthContext } from "../../context/Auth/AuthContext";
|
||||||
import { Can } from "../Can"
|
import { Can } from "../Can";
|
||||||
import TicketsQueueSelect from "../TicketsQueueSelect"
|
import TicketsQueueSelect from "../TicketsQueueSelect";
|
||||||
import { Button } from "@material-ui/core"
|
import { Button } from "@material-ui/core";
|
||||||
|
|
||||||
import { TabTicketContext } from "../../context/TabTicketHeaderOption/TabTicketHeaderOption"
|
import { TabTicketContext } from "../../context/TabTicketHeaderOption/TabTicketHeaderOption";
|
||||||
|
|
||||||
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket"
|
|
||||||
import useTickets from "../../hooks/useTickets"
|
|
||||||
import api from "../../services/api"
|
|
||||||
import toastError from "../../errors/toastError"
|
|
||||||
|
|
||||||
import { ticketsContext } from "../../context/TicketsProvider/TicketsProvider"
|
|
||||||
|
|
||||||
|
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
ticketsWrapper: {
|
ticketsWrapper: {
|
||||||
|
@ -131,106 +124,59 @@ const useStyles = makeStyles((theme) => ({
|
||||||
hide: {
|
hide: {
|
||||||
display: "none !important",
|
display: "none !important",
|
||||||
},
|
},
|
||||||
}))
|
}));
|
||||||
|
|
||||||
const DEFAULT_SEARCH_PARAM = { searchParam: "", searchParamContent: "" }
|
const DEFAULT_SEARCH_PARAM = { searchParam: "", searchParamContent: "" }
|
||||||
|
|
||||||
const TicketsManager = () => {
|
const TicketsManager = () => {
|
||||||
|
|
||||||
const { tabOption, setTabOption } = useContext(TabTicketContext)
|
const { tabOption, setTabOption } = useContext(TabTicketContext);
|
||||||
|
|
||||||
const { setSearchTicket } = useContext(SearchTicketContext)
|
const { setSearchTicket } = useContext(SearchTicketContext)
|
||||||
|
|
||||||
const classes = useStyles()
|
const classes = useStyles();
|
||||||
|
|
||||||
const [searchParam, setSearchParam] = useState(DEFAULT_SEARCH_PARAM)
|
const [searchParam, setSearchParam] = useState(DEFAULT_SEARCH_PARAM);
|
||||||
const [tab, setTab] = useState("open")
|
const [tab, setTab] = useState("open");
|
||||||
const [tabOpen, setTabOpen] = useState("open")
|
const [tabOpen, setTabOpen] = useState("open");
|
||||||
const [newTicketModalOpen, setNewTicketModalOpen] = useState(false)
|
const [newTicketModalOpen, setNewTicketModalOpen] = useState(false);
|
||||||
const [showAllTickets, setShowAllTickets] = useState(false)
|
const [showAllTickets, setShowAllTickets] = useState(false);
|
||||||
const { user, setting, getSettingValue } = useContext(AuthContext)
|
const { user } = useContext(AuthContext);
|
||||||
|
|
||||||
const [openCount, setOpenCount] = useState(0)
|
const [openCount, setOpenCount] = useState(0);
|
||||||
const [pendingCount, setPendingCount] = useState(0)
|
const [pendingCount, setPendingCount] = useState(0);
|
||||||
|
|
||||||
const userQueueIds = user.queues.map((q) => q.id)
|
const userQueueIds = user.queues.map((q) => q.id);
|
||||||
const [selectedQueueIds, setSelectedQueueIds] = useState(userQueueIds || [])
|
const [selectedQueueIds, setSelectedQueueIds] = useState(userQueueIds || []);
|
||||||
|
|
||||||
const [showContentSearch, setShowContentSearch] = useState(false)
|
const [showContentSearch, setShowContentSearch] = useState(false)
|
||||||
const searchInputRef = useRef()
|
const searchInputRef = useRef();
|
||||||
const searchContentInputRef = useRef()
|
const searchContentInputRef = useRef();
|
||||||
const [inputSearch, setInputSearch] = useState('')
|
const [inputSearch, setInputSearch] = useState('');
|
||||||
const [inputContentSearch, setInputContentSearch] = useState("")
|
const [inputContentSearch, setInputContentSearch] = useState("")
|
||||||
|
|
||||||
const [openTooltipSearch, setOpenTooltipSearch] = useState(false)
|
const [openTooltipSearch, setOpenTooltipSearch] = useState(false)
|
||||||
|
|
||||||
const [waitingTime, setWaitingTime] = useState('00:00')
|
let searchTimeout;
|
||||||
// const [tickets, setTickets] = useState([]);
|
let searchContentTimeout;
|
||||||
const [settings, setSettings] = useState([])
|
|
||||||
|
|
||||||
let searchTimeout
|
|
||||||
let searchContentTimeout
|
|
||||||
|
|
||||||
const { tickets, } = useContext(ticketsContext)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setSettings(setting)
|
|
||||||
}, [setting])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user.profile.toUpperCase() === "ADMIN" ||
|
if (user.profile.toUpperCase() === "ADMIN" ||
|
||||||
user.profile.toUpperCase() === "SUPERVISOR" ||
|
user.profile.toUpperCase() === "SUPERVISOR" ||
|
||||||
user.profile.toUpperCase() === "MASTER") {
|
user.profile.toUpperCase() === "MASTER") {
|
||||||
setShowAllTickets(true)
|
setShowAllTickets(true);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (tab === "search") {
|
if (tab === "search") {
|
||||||
searchInputRef.current.focus()
|
searchInputRef.current.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
setTabOption(tab)
|
setTabOption(tab)
|
||||||
|
|
||||||
}, [tab, setTabOption])
|
}, [tab, setTabOption]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
|
|
||||||
if (settings?.length > 0 && getSettingValue('waitingTimeTickets') !== 'enabled') return
|
|
||||||
|
|
||||||
const calculateAverageTime = () => {
|
|
||||||
if (tickets.length > 0) {
|
|
||||||
const now = new Date()
|
|
||||||
const differenceTime = tickets?.map(ticket => {
|
|
||||||
const createdAt = new Date(ticket.createdAt)
|
|
||||||
const difference = now - createdAt
|
|
||||||
return difference
|
|
||||||
})
|
|
||||||
const sumDifferences = differenceTime.reduce((total, difference) => total + difference, 0)
|
|
||||||
const averageTimeMilliseconds = sumDifferences / tickets?.length
|
|
||||||
let hours = Math.floor(averageTimeMilliseconds / 3600000)
|
|
||||||
const minutes = Math.floor((averageTimeMilliseconds % 3600000) / 60000)
|
|
||||||
|
|
||||||
let days = hours >= 24 ? parseInt(hours / 24) : ''
|
|
||||||
|
|
||||||
if (days != '') hours = hours - (24 * days)
|
|
||||||
|
|
||||||
const averageTimeFormated = `${days != '' ? `${days}d ` : days}${hours.toString().padStart(2, '0')}h${minutes.toString().padStart(2, '0')}`
|
|
||||||
|
|
||||||
return averageTimeFormated
|
|
||||||
} else return '00:00'
|
|
||||||
}
|
|
||||||
|
|
||||||
setWaitingTime(calculateAverageTime())
|
|
||||||
|
|
||||||
const intervalId = setInterval(() => {
|
|
||||||
setWaitingTime(calculateAverageTime())
|
|
||||||
}, 10000)
|
|
||||||
|
|
||||||
return () => clearInterval(intervalId)
|
|
||||||
|
|
||||||
}, [tickets])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
@ -248,24 +194,24 @@ const TicketsManager = () => {
|
||||||
|
|
||||||
// }, 500);
|
// }, 500);
|
||||||
|
|
||||||
clearTimeout(searchContentTimeout)
|
clearTimeout(searchContentTimeout);
|
||||||
|
|
||||||
setSearchParam(prev => ({ ...prev, searchParamContent: "" }))
|
setSearchParam(prev => ({ ...prev, searchParamContent: "" }))
|
||||||
|
|
||||||
|
|
||||||
}, [inputContentSearch, searchContentTimeout])
|
}, [inputContentSearch, searchContentTimeout]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
//console.log(selectedQueueIds);
|
|
||||||
if (tabOption === 'open') {
|
if (tabOption === 'open') {
|
||||||
|
|
||||||
setTabOption('')
|
setTabOption('')
|
||||||
setSearchParam(DEFAULT_SEARCH_PARAM)
|
setSearchParam(DEFAULT_SEARCH_PARAM);
|
||||||
setInputSearch('')
|
setInputSearch('');
|
||||||
setInputContentSearch('')
|
setInputContentSearch('')
|
||||||
setTab("open")
|
setTab("open");
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [tabOption, setTabOption])
|
}, [tabOption, setTabOption])
|
||||||
|
@ -285,14 +231,14 @@ const TicketsManager = () => {
|
||||||
|
|
||||||
setSearchTicket(searchParam.searchParam)
|
setSearchTicket(searchParam.searchParam)
|
||||||
|
|
||||||
clearTimeout(searchTimeout)
|
clearTimeout(searchTimeout);
|
||||||
|
|
||||||
if (searchedTerm === "") {
|
if (searchedTerm === "") {
|
||||||
setSearchParam(prev => ({ ...prev, searchParam: searchedTerm }))
|
setSearchParam(prev => ({ ...prev, searchParam: searchedTerm }))
|
||||||
setInputSearch(searchedTerm)
|
setInputSearch(searchedTerm)
|
||||||
setShowContentSearch(false)
|
setShowContentSearch(false)
|
||||||
setTab("open")
|
setTab("open");
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchedTerm.length < 4) {
|
if (searchedTerm.length < 4) {
|
||||||
|
@ -303,10 +249,10 @@ const TicketsManager = () => {
|
||||||
|
|
||||||
searchTimeout = setTimeout(() => {
|
searchTimeout = setTimeout(() => {
|
||||||
|
|
||||||
setSearchParam(prev => ({ ...prev, searchParam: searchedTerm }))
|
setSearchParam(prev => ({ ...prev, searchParam: searchedTerm }));
|
||||||
|
|
||||||
}, 500)
|
}, 500);
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleContentSearch = e => {
|
const handleContentSearch = e => {
|
||||||
|
|
||||||
|
@ -316,9 +262,9 @@ const TicketsManager = () => {
|
||||||
|
|
||||||
searchContentTimeout = setTimeout(() => {
|
searchContentTimeout = setTimeout(() => {
|
||||||
|
|
||||||
setSearchParam(prev => ({ ...prev, searchParamContent: searchedContentText }))
|
setSearchParam(prev => ({ ...prev, searchParamContent: searchedContentText }));
|
||||||
|
|
||||||
}, 500)
|
}, 500);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,18 +282,18 @@ const TicketsManager = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChangeTab = (e, newValue) => {
|
const handleChangeTab = (e, newValue) => {
|
||||||
setTab(newValue)
|
setTab(newValue);
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleChangeTabOpen = (e, newValue) => {
|
const handleChangeTabOpen = (e, newValue) => {
|
||||||
setTabOpen(newValue)
|
setTabOpen(newValue);
|
||||||
}
|
};
|
||||||
|
|
||||||
const applyPanelStyle = (status) => {
|
const applyPanelStyle = (status) => {
|
||||||
if (tabOpen !== status) {
|
if (tabOpen !== status) {
|
||||||
return { width: 0, height: 0 }
|
return { width: 0, height: 0 };
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper elevation={0} variant="outlined" className={classes.ticketsWrapper}>
|
<Paper elevation={0} variant="outlined" className={classes.ticketsWrapper}>
|
||||||
|
@ -502,25 +448,7 @@ const TicketsManager = () => {
|
||||||
</Badge>
|
</Badge>
|
||||||
}
|
}
|
||||||
value={"pending"}
|
value={"pending"}
|
||||||
/>{
|
/>
|
||||||
(settings?.length > 0 && getSettingValue('waitingTimeTickets') === 'enabled') &&
|
|
||||||
|
|
||||||
<Tooltip
|
|
||||||
arrow
|
|
||||||
placement="right"
|
|
||||||
title={"Tempo de espera aguardando"}
|
|
||||||
>
|
|
||||||
<span style={{ display: 'flex', alignItems: 'center', flexDirection: 'column', justifyContent: 'flex-start', marginRight: '20px', marginTop: '10px' }}>
|
|
||||||
{/* <label style={{ color: 'red', fontWeight: 'bold', padding: '.1rem', fontSize: '8px', textAlign: 'center', margin: '0' }}>
|
|
||||||
<i>ESPERA</i>
|
|
||||||
</label> */}
|
|
||||||
<label style={{ color: 'gray', fontWeight: 'bold', padding: '5px'/*, textDecoration: 'underline'*/, fontSize: '13px' }}>
|
|
||||||
{waitingTime}
|
|
||||||
</label>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
}
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<Paper className={classes.ticketsWrapper}>
|
<Paper className={classes.ticketsWrapper}>
|
||||||
<TicketsList
|
<TicketsList
|
||||||
|
@ -558,7 +486,7 @@ const TicketsManager = () => {
|
||||||
|
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</Paper>
|
</Paper>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default TicketsManager
|
export default TicketsManager;
|
|
@ -97,7 +97,7 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
if (settings?.find(e => e?.key === 'queueTransferByWhatsappScope')?.value === 'enabled' && !user.transferToOtherQueues) {
|
if (settings?.find(e => e?.key === 'queueTransferByWhatsappScope')?.value === 'enabled') {
|
||||||
setQueues(_queues)
|
setQueues(_queues)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -190,7 +190,7 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
|
||||||
if (settings?.find(e => e?.key === 'queueTransferByWhatsappScope')?.value === 'enabled' && !user.transferToOtherQueues) {
|
if (settings?.find(e => e?.key === 'queueTransferByWhatsappScope')?.value === 'enabled') {
|
||||||
const { data } = await api.get(`/users/all`, {
|
const { data } = await api.get(`/users/all`, {
|
||||||
params: { userId: user.id },
|
params: { userId: user.id },
|
||||||
})
|
})
|
||||||
|
@ -202,7 +202,7 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
|
||||||
else {
|
else {
|
||||||
|
|
||||||
const { data } = await api.get(`/users/all`, {
|
const { data } = await api.get(`/users/all`, {
|
||||||
params: { profile: 'user', transferToOtherQueues: user.transferToOtherQueues },
|
params: { profile: 'user' },
|
||||||
})
|
})
|
||||||
|
|
||||||
setUsers(data.users)
|
setUsers(data.users)
|
||||||
|
|
|
@ -32,7 +32,6 @@ import toastError from "../../errors/toastError"
|
||||||
import QueueSelect from "../QueueSelect"
|
import QueueSelect from "../QueueSelect"
|
||||||
import { AuthContext } from "../../context/Auth/AuthContext"
|
import { AuthContext } from "../../context/Auth/AuthContext"
|
||||||
import { Can } from "../Can"
|
import { Can } from "../Can"
|
||||||
import Switch from '@mui/material/Switch'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
root: {
|
root: {
|
||||||
|
@ -96,7 +95,6 @@ const UserModal = ({ open, onClose, userId, }) => {
|
||||||
const [showPassword, setShowPassword] = useState(false)
|
const [showPassword, setShowPassword] = useState(false)
|
||||||
const [positions, setPositions] = useState([])
|
const [positions, setPositions] = useState([])
|
||||||
const [selectedPosition, setSelectedPosition] = useState('')
|
const [selectedPosition, setSelectedPosition] = useState('')
|
||||||
const [checked, setChecked] = useState(false)
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchUser = async () => {
|
const fetchUser = async () => {
|
||||||
|
@ -114,9 +112,6 @@ const UserModal = ({ open, onClose, userId, }) => {
|
||||||
setSelectedPosition(data.positionId)
|
setSelectedPosition(data.positionId)
|
||||||
else
|
else
|
||||||
setSelectedPosition('')
|
setSelectedPosition('')
|
||||||
|
|
||||||
|
|
||||||
if(data.transferToOtherQueues) setChecked(data.transferToOtherQueues);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toastError(err)
|
toastError(err)
|
||||||
}
|
}
|
||||||
|
@ -141,15 +136,10 @@ const UserModal = ({ open, onClose, userId, }) => {
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
onClose()
|
onClose()
|
||||||
setUser(initialState)
|
setUser(initialState)
|
||||||
setChecked(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleChange = (event) => {
|
|
||||||
setChecked(event.target.checked)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSaveUser = async values => {
|
const handleSaveUser = async values => {
|
||||||
const userData = { ...values, queueIds: selectedQueueIds, positionId: selectedPosition, transferToOtherQueues: checked}
|
const userData = { ...values, queueIds: selectedQueueIds, positionId: selectedPosition }
|
||||||
try {
|
try {
|
||||||
if (userId) {
|
if (userId) {
|
||||||
|
|
||||||
|
@ -262,7 +252,7 @@ const UserModal = ({ open, onClose, userId, }) => {
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
<div className={classes.multFieldLine}>
|
<div className={classes.multFieldLine}>
|
||||||
{/* <Field
|
<Field
|
||||||
as={TextField}
|
as={TextField}
|
||||||
label="Cargo"
|
label="Cargo"
|
||||||
name="positionCompany"
|
name="positionCompany"
|
||||||
|
@ -271,17 +261,7 @@ const UserModal = ({ open, onClose, userId, }) => {
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
margin="dense"
|
margin="dense"
|
||||||
fullWidth
|
fullWidth
|
||||||
/> */}
|
/>
|
||||||
<label style={{display: 'flex', alignItems:'center'}}>
|
|
||||||
Transferir para outras filas
|
|
||||||
<Switch
|
|
||||||
name= 'transferToOtherQueues'
|
|
||||||
checked={checked}
|
|
||||||
onChange={handleChange}
|
|
||||||
inputProps={{ 'aria-label': 'controlled' }}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<FormControl
|
<FormControl
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
className={classes.formControl}
|
className={classes.formControl}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import React, { useState, createContext } from "react"
|
|
||||||
|
|
||||||
const ticketsContext = createContext()
|
|
||||||
|
|
||||||
|
|
||||||
const TicketsProvider = ({ children }) => {
|
|
||||||
|
|
||||||
const [tickets, setTickets] = useState(0)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ticketsContext.Provider value={{ tickets, setTickets }}>
|
|
||||||
{children}
|
|
||||||
</ticketsContext.Provider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export { ticketsContext, TicketsProvider }
|
|
|
@ -20,10 +20,9 @@ const Chart = (props) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const date = useRef(new Date().toISOString());
|
const date = useRef(new Date().toISOString());
|
||||||
const queueIds = JSON.stringify( props.selectedQueue) || {};
|
let { tickets } = useTickets({ date: date.current, unlimited: "current" });
|
||||||
let {tickets} = useTickets({ date: date.current, unlimited: "current", queueIds });
|
|
||||||
|
|
||||||
const modelChar = [
|
const [chartData, setChartData] = useState([
|
||||||
{ time: "08:00", amount: 0 },
|
{ time: "08:00", amount: 0 },
|
||||||
{ time: "09:00", amount: 0 },
|
{ time: "09:00", amount: 0 },
|
||||||
{ time: "10:00", amount: 0 },
|
{ time: "10:00", amount: 0 },
|
||||||
|
@ -36,12 +35,11 @@ const Chart = (props) => {
|
||||||
{ time: "17:00", amount: 0 },
|
{ time: "17:00", amount: 0 },
|
||||||
{ time: "18:00", amount: 0 },
|
{ time: "18:00", amount: 0 },
|
||||||
{ time: "19:00", amount: 0 },
|
{ time: "19:00", amount: 0 },
|
||||||
]
|
]);
|
||||||
const [chartData, setChartData] = useState(modelChar);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setChartData(prevState => {
|
setChartData(prevState => {
|
||||||
let aux = modelChar;
|
let aux = [...prevState];
|
||||||
|
|
||||||
aux.forEach(a => {
|
aux.forEach(a => {
|
||||||
tickets.forEach(ticket => { format(startOfHour(parseISO(ticket.createdAt)), "HH:mm") === a.time && a.amount++; });
|
tickets.forEach(ticket => { format(startOfHour(parseISO(ticket.createdAt)), "HH:mm") === a.time && a.amount++; });
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useContext, useReducer, useEffect, useState, useCallback } 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"
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ 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 SelectField from "../../components/Report/SelectField"
|
|
||||||
|
|
||||||
import { AuthContext } from "../../context/Auth/AuthContext"
|
import { AuthContext } from "../../context/Auth/AuthContext"
|
||||||
// import { i18n } from "../../translate/i18n";
|
// import { i18n } from "../../translate/i18n";
|
||||||
|
@ -255,15 +254,12 @@ const reducer = (state, action) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
const { user } = useContext(AuthContext)
|
|
||||||
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 [ticketStatusChatEnd, setTicketStatusChatEnd] = useState([])
|
const [ticketStatusChatEnd, setTicketStatusChatEnd] = useState([])
|
||||||
|
const { user } = useContext(AuthContext)
|
||||||
const userQueueIds = user.queues?.map((q) => q.id);
|
|
||||||
const [selectedQueue, setSelectedQueue] = useState(userQueueIds || []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch({ type: "RESET" })
|
dispatch({ type: "RESET" })
|
||||||
|
@ -290,14 +286,14 @@ const Dashboard = () => {
|
||||||
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, userQueues: selectedQueue },
|
params: { userId: null, startDate: dateToday, endDate: dateToday },
|
||||||
})
|
})
|
||||||
|
|
||||||
dispatch({ type: "RESET" })
|
dispatch({ type: "RESET" })
|
||||||
dispatch({ type: "LOAD_QUERY", payload: data.usersProfile })
|
dispatch({ type: "LOAD_QUERY", payload: data.usersProfile })
|
||||||
|
|
||||||
const { data: ticketStatusChatEndData } = await api.get("/reports/count/statusChatEnd", {
|
const { data: ticketStatusChatEndData } = await api.get("/reports/count/statusChatEnd", {
|
||||||
params: { startDate: dateToday, endDate: dateToday, userQueues: selectedQueue },
|
params: { startDate: dateToday, endDate: dateToday },
|
||||||
})
|
})
|
||||||
|
|
||||||
setTicketStatusChatEnd(ticketStatusChatEndData.reportStatusChatEnd)
|
setTicketStatusChatEnd(ticketStatusChatEndData.reportStatusChatEnd)
|
||||||
|
@ -310,7 +306,7 @@ const Dashboard = () => {
|
||||||
fetchQueries()
|
fetchQueries()
|
||||||
}, 500)
|
}, 500)
|
||||||
return () => clearTimeout(delayDebounceFn)
|
return () => clearTimeout(delayDebounceFn)
|
||||||
}, [selectedQueue])
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -385,18 +381,6 @@ const Dashboard = () => {
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleSelectedQueue = useCallback((queueSelected) => {
|
|
||||||
if(queueSelected !== 'All'){
|
|
||||||
const queueIndex = user?.queues?.findIndex((q) => q.id === parseInt(queueSelected));
|
|
||||||
const queueIds = []
|
|
||||||
queueIds.push(user?.queues[queueIndex]?.id);
|
|
||||||
setSelectedQueue(queueIds);
|
|
||||||
}else{
|
|
||||||
const queueIds = user?.queues?.map((queue) => queue.id);
|
|
||||||
setSelectedQueue(queueIds);
|
|
||||||
}
|
|
||||||
},[user, setSelectedQueue])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ticketStatusChange === "") return
|
if (ticketStatusChange === "") return
|
||||||
const delayDebounceFn = setTimeout(() => {
|
const delayDebounceFn = setTimeout(() => {
|
||||||
|
@ -406,17 +390,17 @@ const Dashboard = () => {
|
||||||
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, queueIds: selectedQueue },
|
params: { status: "open", date: dateToday },
|
||||||
})
|
})
|
||||||
const _closed = await api.get("/tickets/count", {
|
const _closed = await api.get("/tickets/count", {
|
||||||
params: { status: "closed", date: dateToday, queueIds: selectedQueue },
|
params: { status: "closed", date: dateToday },
|
||||||
})
|
})
|
||||||
const _pending = await api.get("/tickets/count", {
|
const _pending = await api.get("/tickets/count", {
|
||||||
params: { status: "pending", queueIds: selectedQueue },
|
params: { status: "pending" },
|
||||||
})
|
})
|
||||||
|
|
||||||
const _openAll = await api.get("/tickets/count", {
|
const _openAll = await api.get("/tickets/count", {
|
||||||
params: { status: "open", queueIds: selectedQueue },
|
params: { status: "open" },
|
||||||
})
|
})
|
||||||
setTicktsStatus({
|
setTicktsStatus({
|
||||||
open: _open.data.count,
|
open: _open.data.count,
|
||||||
|
@ -435,7 +419,7 @@ const Dashboard = () => {
|
||||||
fetchQueries()
|
fetchQueries()
|
||||||
}, 500)
|
}, 500)
|
||||||
return () => clearTimeout(delayDebounceFn)
|
return () => clearTimeout(delayDebounceFn)
|
||||||
}, [ticketStatusChange, selectedQueue])
|
}, [ticketStatusChange])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Can
|
<Can
|
||||||
|
@ -467,16 +451,6 @@ const Dashboard = () => {
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid style={{ display: 'flex', flexDirection: 'column', padding: '10px 0', alignItems: 'start' }}>
|
|
||||||
<SelectField
|
|
||||||
func={handleSelectedQueue}
|
|
||||||
textBoxFieldSelected={'All'}
|
|
||||||
emptyField={false}
|
|
||||||
header={'Filas'}
|
|
||||||
currencies={user.queues.map((obj) => {
|
|
||||||
return { 'value': obj.id, 'label': obj.name }
|
|
||||||
})} />
|
|
||||||
</Grid>
|
|
||||||
<Grid container spacing={3}>
|
<Grid container spacing={3}>
|
||||||
<Grid item xs={12} sm={6} md={6} lg={4}>
|
<Grid item xs={12} sm={6} md={6} lg={4}>
|
||||||
<Paper
|
<Paper
|
||||||
|
@ -532,7 +506,7 @@ const Dashboard = () => {
|
||||||
<Grid item container spacing={3}>
|
<Grid item container spacing={3}>
|
||||||
<Grid item xs={12} sm={12} md={6} lg={6}>
|
<Grid item xs={12} sm={12} md={6} lg={6}>
|
||||||
<Paper className={classes.fixedHeightPaper} variant="outlined">
|
<Paper className={classes.fixedHeightPaper} variant="outlined">
|
||||||
<Chart allTickets={usersOnlineInfo} selectedQueue = {selectedQueue}/>
|
<Chart allTickets={usersOnlineInfo} />
|
||||||
</Paper>
|
</Paper>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={12} md={6} lg={6}>
|
<Grid item xs={12} sm={12} md={6} lg={6}>
|
||||||
|
|
|
@ -224,7 +224,6 @@ Item.propTypes = {
|
||||||
|
|
||||||
|
|
||||||
let columnsData = [
|
let columnsData = [
|
||||||
{ title: `Tipo`, field: 'isRemote' },
|
|
||||||
{ title: `${i18n.t("reports.listColumns.column1_1")}`, field: 'whatsapp.name' },
|
{ title: `${i18n.t("reports.listColumns.column1_1")}`, field: 'whatsapp.name' },
|
||||||
{ title: `${i18n.t("reports.listColumns.column1_2")}`, field: 'user.name' },
|
{ title: `${i18n.t("reports.listColumns.column1_2")}`, field: 'user.name' },
|
||||||
{ title: `${i18n.t("reports.listColumns.column0_4")}`, field: 'contact.number' },
|
{ title: `${i18n.t("reports.listColumns.column0_4")}`, field: 'contact.number' },
|
||||||
|
@ -238,12 +237,9 @@ let columnsData = [
|
||||||
{ title: `${i18n.t("reports.listColumns.column1_9")}`, field: 'statusChatEnd' },
|
{ title: `${i18n.t("reports.listColumns.column1_9")}`, field: 'statusChatEnd' },
|
||||||
{ title: `Espera`, field: 'waiting_time' },
|
{ title: `Espera`, field: 'waiting_time' },
|
||||||
{ title: `Mensagens`, field: 'messagesToFilter', searchable: true, hidden: true },
|
{ title: `Mensagens`, field: 'messagesToFilter', searchable: true, hidden: true },
|
||||||
{ title: `Link`, field: 'link', searchable: false, hidden: true, export: true },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
let columnsDataSuper = [
|
let columnsDataSuper = [
|
||||||
{ title: `Tipo`, field: 'isRemote' },
|
|
||||||
{ title: `${i18n.t("reports.listColumns.column1_0")}`, field: 'isRemote' },
|
|
||||||
{ title: `${i18n.t("reports.listColumns.column1_1")}`, field: 'whatsapp.name' },
|
{ title: `${i18n.t("reports.listColumns.column1_1")}`, field: 'whatsapp.name' },
|
||||||
{ title: `${i18n.t("reports.listColumns.column1_2")}`, field: 'user.name' },
|
{ title: `${i18n.t("reports.listColumns.column1_2")}`, field: 'user.name' },
|
||||||
{ title: `${i18n.t("reports.listColumns.column0_3")}`, field: 'contact.name' },
|
{ title: `${i18n.t("reports.listColumns.column0_3")}`, field: 'contact.name' },
|
||||||
|
@ -256,7 +252,6 @@ let columnsDataSuper = [
|
||||||
{ title: `${i18n.t("reports.listColumns.column1_9")}`, field: 'statusChatEnd' },
|
{ title: `${i18n.t("reports.listColumns.column1_9")}`, field: 'statusChatEnd' },
|
||||||
{ title: `Espera`, field: 'waiting_time' },
|
{ title: `Espera`, field: 'waiting_time' },
|
||||||
{ title: `Mensagens`, field: 'messagesToFilter', searchable: true, hidden: true },
|
{ title: `Mensagens`, field: 'messagesToFilter', searchable: true, hidden: true },
|
||||||
{ title: `Link`, field: 'link', searchable: false, hidden: true, export: true },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -379,15 +374,12 @@ const Report = () => {
|
||||||
filterQueuesTickets = ticketsQueue.filter(ticket => ticket?.queue?.name === userQueues[0]?.name)
|
filterQueuesTickets = ticketsQueue.filter(ticket => ticket?.queue?.name === userQueues[0]?.name)
|
||||||
}
|
}
|
||||||
data.tickets = filterQueuesTickets
|
data.tickets = filterQueuesTickets
|
||||||
const tickets = data.tickets.map(ticket => {
|
const tickets = data.tickets.map(ticket => ({
|
||||||
ticket.isRemote = ticket.isRemote ? 'Remoto' : 'Comum';
|
|
||||||
return ({
|
|
||||||
...ticket,
|
...ticket,
|
||||||
messagesToFilter: ticket.messages.map(message => message.body).join(' '),
|
messagesToFilter: ticket.messages.map(message => message.body).join(' '),
|
||||||
link: `${process.env.REACT_APP_FRONTEND_URL}/tickets/${ticket.id}`
|
}))
|
||||||
})
|
|
||||||
})
|
|
||||||
dispatchQ({ type: "LOAD_QUERY", payload: tickets })
|
dispatchQ({ type: "LOAD_QUERY", payload: tickets })
|
||||||
|
// console.log(tickets)
|
||||||
setHasMore(data.hasMore)
|
setHasMore(data.hasMore)
|
||||||
setTotalCountTickets(data.count)
|
setTotalCountTickets(data.count)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
@ -688,56 +680,54 @@ const Report = () => {
|
||||||
|
|
||||||
|
|
||||||
const renderSwitch = (param) => {
|
const renderSwitch = (param) => {
|
||||||
if(userA.profile !== 'supervisor'){
|
switch (param) {
|
||||||
switch (param) {
|
case 'empty':
|
||||||
case 'empty':
|
return (
|
||||||
return (
|
<>
|
||||||
<>
|
{query && query.length > 0 &&
|
||||||
{query && query.length > 0 &&
|
<ReportModalType currencies={reportTypeList} func={reportTypeValue} reportOption={reportType} />
|
||||||
<ReportModalType currencies={reportTypeList} func={reportTypeValue} reportOption={reportType} />
|
}
|
||||||
}
|
{/* <Button
|
||||||
{/* <Button
|
disabled={query && query.length > 0 ? false : true}
|
||||||
disabled={query && query.length > 0 ? false : true}
|
variant="contained"
|
||||||
variant="contained"
|
color="primary"
|
||||||
color="primary"
|
onClick={(e) => {
|
||||||
onClick={(e) => {
|
handleCSVMessages()
|
||||||
handleCSVMessages()
|
}}
|
||||||
}}
|
>
|
||||||
>
|
{"CSV ALL"}
|
||||||
{"CSV ALL"}
|
|
||||||
|
|
||||||
</Button> */}
|
</Button> */}
|
||||||
</>)
|
</>)
|
||||||
|
|
||||||
case 'pending' || 'processing':
|
case 'pending' || 'processing':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span>PROCESSING...</span>
|
<span>PROCESSING...</span>
|
||||||
</>)
|
</>)
|
||||||
|
|
||||||
case 'success':
|
case 'success':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
handleCSVDownload(e)
|
handleCSVDownload(e)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{'CSV DOWNLOAD'}
|
{'CSV DOWNLOAD'}
|
||||||
</Button>
|
</Button>
|
||||||
</>)
|
</>)
|
||||||
case 'downloading':
|
case 'downloading':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span>DOWNLOADING...</span>
|
<span>DOWNLOADING...</span>
|
||||||
</>)
|
</>)
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return (<><span>WAITING...</span></>)
|
return (<><span>WAITING...</span></>)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -881,7 +871,7 @@ const Report = () => {
|
||||||
<>
|
<>
|
||||||
<MTable data={query}
|
<MTable data={query}
|
||||||
columns={userA.profile !== 'supervisor' ? columnsData : columnsDataSuper}
|
columns={userA.profile !== 'supervisor' ? columnsData : columnsDataSuper}
|
||||||
hasChild={userA.profile !== 'supervisor' ? true :false}
|
hasChild={true}
|
||||||
removeClickRow={false}
|
removeClickRow={false}
|
||||||
|
|
||||||
handleScroll={handleScroll}
|
handleScroll={handleScroll}
|
||||||
|
|
|
@ -560,88 +560,6 @@ const Settings = () => {
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={classes.root}>
|
|
||||||
<Container className={classes.container} maxWidth="sm">
|
|
||||||
<Paper className={classes.paper}>
|
|
||||||
<Typography variant="body1">
|
|
||||||
Noficar quando entrar novo ticket na fila
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
margin="dense"
|
|
||||||
variant="outlined"
|
|
||||||
native
|
|
||||||
id="notificationTransferQueue-setting"
|
|
||||||
name="notificationTransferQueue"
|
|
||||||
value={
|
|
||||||
settings &&
|
|
||||||
settings.length > 0 &&
|
|
||||||
getSettingValue('notificationTransferQueue')
|
|
||||||
}
|
|
||||||
className={classes.settingOption}
|
|
||||||
onChange={handleChangeSetting}
|
|
||||||
>
|
|
||||||
<option value="enabled">Ativado</option>
|
|
||||||
<option value="disabled">Desativado</option>
|
|
||||||
</Select>
|
|
||||||
</Paper>
|
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
<div className={classes.root}>
|
|
||||||
<Container className={classes.container} maxWidth="sm">
|
|
||||||
<Paper className={classes.paper}>
|
|
||||||
<Typography variant="body1">
|
|
||||||
Bloquear mídias de Audio e Video
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
margin="dense"
|
|
||||||
variant="outlined"
|
|
||||||
native
|
|
||||||
id="blockAudioVideoMedia-setting"
|
|
||||||
name="blockAudioVideoMedia"
|
|
||||||
value={
|
|
||||||
settings &&
|
|
||||||
settings.length > 0 &&
|
|
||||||
getSettingValue('blockAudioVideoMedia')
|
|
||||||
}
|
|
||||||
className={classes.settingOption}
|
|
||||||
onChange={handleChangeSetting}
|
|
||||||
>
|
|
||||||
<option value="enabled">Ativado</option>
|
|
||||||
<option value="disabled">Desativado</option>
|
|
||||||
</Select>
|
|
||||||
</Paper>
|
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={classes.root}>
|
|
||||||
<Container className={classes.container} maxWidth="sm">
|
|
||||||
<Paper className={classes.paper}>
|
|
||||||
<Typography variant="body1">
|
|
||||||
Mostrar tempo de espera dos tickets aguardando
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
margin="dense"
|
|
||||||
variant="outlined"
|
|
||||||
native
|
|
||||||
id="waitingTimeTickets-setting"
|
|
||||||
name="waitingTimeTickets"
|
|
||||||
value={
|
|
||||||
settings &&
|
|
||||||
settings.length > 0 &&
|
|
||||||
getSettingValue('waitingTimeTickets')
|
|
||||||
}
|
|
||||||
className={classes.settingOption}
|
|
||||||
onChange={handleChangeSetting}
|
|
||||||
>
|
|
||||||
<option value="enabled">Ativado</option>
|
|
||||||
<option value="disabled">Desativado</option>
|
|
||||||
</Select>
|
|
||||||
</Paper>
|
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -11,7 +11,6 @@ import { i18n } from "../../translate/i18n";
|
||||||
import Hidden from "@material-ui/core/Hidden";
|
import Hidden from "@material-ui/core/Hidden";
|
||||||
|
|
||||||
import { SearchTicketProvider } from "../../context/SearchTicket/SearchTicket";
|
import { SearchTicketProvider } from "../../context/SearchTicket/SearchTicket";
|
||||||
import { TicketsProvider } from "../../context/TicketsProvider/TicketsProvider"
|
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
chatContainer: {
|
chatContainer: {
|
||||||
|
@ -83,9 +82,7 @@ const Chat = () => {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<SearchTicketProvider>
|
<SearchTicketProvider>
|
||||||
<TicketsProvider>
|
<TicketsManager />
|
||||||
<TicketsManager />
|
|
||||||
</TicketsProvider>
|
|
||||||
</SearchTicketProvider>
|
</SearchTicketProvider>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -252,7 +252,7 @@ const messages = {
|
||||||
search: { title: "Busca" },
|
search: { title: "Busca" },
|
||||||
},
|
},
|
||||||
search: {
|
search: {
|
||||||
placeholder: "Tel/nome/conteúdo",
|
placeholder: "Busca telefone/nome",
|
||||||
},
|
},
|
||||||
buttons: {
|
buttons: {
|
||||||
showAll: "Todos",
|
showAll: "Todos",
|
||||||
|
|
Loading…
Reference in New Issue