Atualização para habilitar ou desabilitar whatsapp oficial

pull/21/head
adriano 2023-09-16 11:45:44 -03:00
parent 6d525e4224
commit 996e182fb6
22 changed files with 763 additions and 411 deletions

View File

@ -8,6 +8,8 @@ import ListSettingsService from "../services/SettingServices/ListSettingsService
import loadSettings from "../helpers/LoadSettings"; import loadSettings from "../helpers/LoadSettings";
import updateSettingTicket from "../services/SettingServices/UpdateSettingTicket"; import updateSettingTicket from "../services/SettingServices/UpdateSettingTicket";
import SettingTicket from "../models/SettingTicket"; import SettingTicket from "../models/SettingTicket";
import Whatsapp from "../models/Whatsapp";
import whatsappOfficialNumberInfo from "../helpers/WhatsappOfficialNumberInfo";
export const index = async (req: Request, res: Response): Promise<Response> => { export const index = async (req: Request, res: Response): Promise<Response> => {
// if (req.user.profile !== "master") { // if (req.user.profile !== "master") {
@ -76,9 +78,7 @@ export const updateTicketSettings = async (
}); });
} }
return res return res.status(200).json({
.status(200)
.json({
outBusinessHours, outBusinessHours,
ticketExpiration, ticketExpiration,
weekend, weekend,
@ -103,6 +103,40 @@ export const update = async (
value value
}); });
if (key && key == "whatsaAppCloudApi") {
let whatsapps: any = await Whatsapp.findAll();
if (whatsapps) {
for (let i in whatsapps) {
const { id, wabaId, isOfficial } = whatsapps[i];
if (isOfficial && wabaId) {
try {
const whatsapp = await Whatsapp.findByPk(id);
if (whatsapp) {
if (value == "disabled") {
whatsapp.update({ status: "OPENING" });
} else if (value == "enabled") {
const info = await whatsappOfficialNumberInfo(wabaId);
if (info) {
whatsapp.update({
classification: info.quality_rating,
status: "CONNECTED"
});
}
}
}
} catch (error) {
console.log(
"error on try update classification number from oficial whatsapp in SettingControllers.ts: ",
error
);
}
}
}
}
}
loadSettings(); loadSettings();
const io = getIO(); const io = getIO();

View File

@ -115,12 +115,24 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
} }
}); });
if (getSettingValue("whatsaAppCloudApi")?.value == "enabled") {
if (ticket) {
await UpdateTicketService({
ticketData: { status: "closed" },
ticketId: ticket.id
});
ticket = null;
}
} else {
if (ticket) { if (ticket) {
await UpdateTicketService({ await UpdateTicketService({
ticketData: { status: "open", userId: userId, queueId }, ticketData: { status: "open", userId: userId, queueId },
ticketId: ticket.id ticketId: ticket.id
}); });
} else { }
}
if(!ticket){
ticket = await CreateTicketService({ ticket = await CreateTicketService({
contactId, contactId,
status, status,

View File

@ -36,6 +36,10 @@ import ShowUserService from "../services/UserServices/ShowUserService";
import fs from "fs"; import fs from "fs";
import receiveWhatsAppMediaOfficialAPI from "../helpers/ReceiveWhatsAppMediaOfficialAPI"; import receiveWhatsAppMediaOfficialAPI from "../helpers/ReceiveWhatsAppMediaOfficialAPI";
import whatsappOfficialAPI from "../helpers/WhatsappOfficialAPI";
import whatsappOfficialNumberInfo from "../helpers/WhatsappOfficialNumberInfo";
import { getSettingValue } from "../helpers/WhaticketSettings";
interface WhatsappData { interface WhatsappData {
name: string; name: string;
queueIds: number[]; queueIds: number[];
@ -45,10 +49,45 @@ interface WhatsappData {
farewellMessage?: string; farewellMessage?: string;
status?: string; status?: string;
isDefault?: boolean; isDefault?: boolean;
isOfficial?: boolean;
phoneNumberId?: string;
wabaId?: string;
} }
let count: number = 0;
export const index = async (req: Request, res: Response): Promise<Response> => { export const index = async (req: Request, res: Response): Promise<Response> => {
const whatsapps = await ListWhatsAppsService(); let whatsapps = await ListWhatsAppsService();
if (getSettingValue("whatsaAppCloudApi")?.value == "enabled") {
// Atualizar isso quando tiver tempo
if (count > 12) count = 0;
if (count == 0) {
for (let i in whatsapps) {
const { id, wabaId, isOfficial } = whatsapps[i];
if (isOfficial && wabaId) {
try {
const info = await whatsappOfficialNumberInfo(wabaId);
if (info) {
const whatsapp = await Whatsapp.findByPk(id);
if (whatsapp) {
whatsapp.update({
classification: info.quality_rating
});
whatsapps[i].classification = info.quality_rating;
}
}
} catch (error) {
console.log('error on try update classification number from oficial whatsapp in WhatsappController.ts: ', error)
}
}
}
}
console.log("count: ", count);
count++;
}
return res.status(200).json(whatsapps); return res.status(200).json(whatsapps);
}; };
@ -59,7 +98,15 @@ export const whatsAppOfficialMatchQueue = async (
): Promise<Response> => { ): Promise<Response> => {
const { userId, queueId }: any = req.query; const { userId, queueId }: any = req.query;
const whatsapps = await GetDefaultWhatsApp({ userId, queueId }); let whatsapps = await GetDefaultWhatsApp({ userId, queueId });
if (whatsapps && Array.isArray(whatsapps)) {
const uniqueWhatsApps = whatsapps.filter(
(whatsapp, index, self) =>
index === self.findIndex(w => w.number === whatsapp.number)
);
whatsapps = uniqueWhatsApps;
}
return res.status(200).json(whatsapps); return res.status(200).json(whatsapps);
}; };
@ -255,7 +302,7 @@ export const weebhook = async (
}; };
export const store = async (req: Request, res: Response): Promise<Response> => { export const store = async (req: Request, res: Response): Promise<Response> => {
const { let {
name, name,
status, status,
isDefault, isDefault,
@ -263,17 +310,39 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
farewellMessage, farewellMessage,
queueIds, queueIds,
url, url,
urlApi urlApi,
phoneNumberId,
wabaId,
isOfficial
}: WhatsappData = req.body; }: WhatsappData = req.body;
if (req.user.profile !== "master") { if (req.user.profile !== "master") {
throw new AppError("ERR_NO_PERMISSION", 403); throw new AppError("ERR_NO_PERMISSION", 403);
} }
let validate = validatePhoneName(name); const invalid = checkWhatsAppData({
urlApi,
isOfficial,
phoneNumberId,
wabaId
});
if (validate) { if (invalid) {
return res.status(200).json({ message: validate }); return res.status(400).json(invalid);
}
if (isOfficial) {
urlApi = "";
url = "";
} else if (!isOfficial) {
phoneNumberId = "";
wabaId = "";
}
let invalidPhoneName = validatePhoneName(name);
if (invalidPhoneName) {
return res.status(200).json({ message: invalidPhoneName });
} }
const { whatsapp, oldDefaultWhatsapp } = await CreateWhatsAppService({ const { whatsapp, oldDefaultWhatsapp } = await CreateWhatsAppService({
@ -284,19 +353,22 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
isDefault, isDefault,
greetingMessage, greetingMessage,
farewellMessage, farewellMessage,
queueIds queueIds,
phoneNumberId,
wabaId,
isOfficial
}); });
console.log("whatsapp.id: ", whatsapp.id); console.log("whatsapp.id: ", whatsapp.id);
if (!isOfficial) {
postData(`${whatsapp.urlApi}/api/session`, { postData(`${whatsapp.urlApi}/api/session`, {
app_name: process.env.APP_NAME, app_name: process.env.APP_NAME,
whatsappId: whatsapp.id, whatsappId: whatsapp.id,
number: getNumberFromName(name), number: getNumberFromName(name),
client_url: `${process.env.BACKEND_URL_RAW}:${process.env.PORT}` client_url: `${process.env.BACKEND_URL_RAW}:${process.env.PORT}`
}); });
}
// StartWhatsAppSession(whatsapp);
const io = getIO(); const io = getIO();
io.emit("whatsapp", { io.emit("whatsapp", {
@ -329,12 +401,31 @@ export const update = async (
const { whatsappId } = req.params; const { whatsappId } = req.params;
const whatsappData = req.body; const whatsappData = req.body;
let validate = validatePhoneName(whatsappData.name); let invalidPhoneName = validatePhoneName(whatsappData.name);
console.log("validate", validate); if (invalidPhoneName) {
return res.status(200).json({ message: invalidPhoneName });
}
if (validate) { const { urlApi, isOfficial, phoneNumberId, wabaId } = whatsappData;
return res.status(200).json({ message: validate });
const invalid = checkWhatsAppData({
urlApi,
isOfficial,
phoneNumberId,
wabaId
});
if (invalid) {
return res.status(400).json(invalid);
}
if (isOfficial) {
whatsappData.urlApi = "";
whatsappData.url = "";
} else if (!isOfficial) {
whatsappData.phoneNumberId = "";
whatsappData.wabaId = "";
} }
const { whatsapp, oldDefaultWhatsapp } = await UpdateWhatsAppService({ const { whatsapp, oldDefaultWhatsapp } = await UpdateWhatsAppService({
@ -342,12 +433,14 @@ export const update = async (
whatsappId whatsappId
}); });
if (!whatsappData?.isOfficial) {
postData(`${whatsapp.urlApi}/api/session`, { postData(`${whatsapp.urlApi}/api/session`, {
app_name: process.env.APP_NAME, app_name: process.env.APP_NAME,
whatsappId: whatsapp.id, whatsappId: whatsapp.id,
number: getNumberFromName(whatsapp.name), number: getNumberFromName(whatsapp.name),
client_url: `${process.env.BACKEND_URL_RAW}:${process.env.PORT}` client_url: `${process.env.BACKEND_URL_RAW}:${process.env.PORT}`
}); });
}
const io = getIO(); const io = getIO();
io.emit("whatsapp", { io.emit("whatsapp", {
@ -377,10 +470,12 @@ export const remove = async (
const whatsapp: any = await Whatsapp.findByPk(whatsappId, { raw: true }); const whatsapp: any = await Whatsapp.findByPk(whatsappId, { raw: true });
if (!whatsapp?.isOfficial) {
postData(`${whatsapp.urlApi}/api/session/del`, { postData(`${whatsapp.urlApi}/api/session/del`, {
app_name: process.env.APP_NAME, app_name: process.env.APP_NAME,
whatsappId: whatsappId whatsappId: whatsappId
}); });
}
await DeleteWhatsAppService(whatsappId); await DeleteWhatsAppService(whatsappId);
@ -407,3 +502,25 @@ export const remove = async (
return res.status(200).json({ message: "Whatsapp deleted." }); return res.status(200).json({ message: "Whatsapp deleted." });
}; };
interface WhatsappDataValidate {
urlApi?: string;
isOfficial?: boolean;
phoneNumberId?: string;
wabaId?: string;
}
const checkWhatsAppData = ({
urlApi,
isOfficial,
phoneNumberId,
wabaId
}: WhatsappDataValidate) => {
if (isOfficial && (!phoneNumberId || phoneNumberId.trim() == "")) {
return { message: "Phone number Id is required!" };
} else if (isOfficial && (!wabaId || wabaId.trim() == "")) {
return { message: "WABA ID is required!" };
} else if (!isOfficial && (!urlApi || urlApi.trim() == "")) {
return { message: "urlApi is required!" };
}
};

View File

@ -0,0 +1,15 @@
import { QueryInterface, DataTypes } from "sequelize";
module.exports = {
up: (queryInterface: QueryInterface) => {
return queryInterface.addColumn("Whatsapps", "isOfficial", {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
});
},
down: (queryInterface: QueryInterface) => {
return queryInterface.removeColumn("Whatsapps", "isOfficial");
}
};

View File

@ -0,0 +1,14 @@
import { QueryInterface, DataTypes } from "sequelize";
module.exports = {
up: (queryInterface: QueryInterface) => {
return queryInterface.addColumn("Whatsapps", "wabaId", {
type: DataTypes.STRING,
allowNull: true
});
},
down: (queryInterface: QueryInterface) => {
return queryInterface.removeColumn("Whatsapps", "wabaId");
}
};

View File

@ -0,0 +1,14 @@
import { QueryInterface, DataTypes } from "sequelize";
module.exports = {
up: (queryInterface: QueryInterface) => {
return queryInterface.addColumn("Whatsapps", "classification", {
type: DataTypes.STRING,
allowNull: true
});
},
down: (queryInterface: QueryInterface) => {
return queryInterface.removeColumn("Whatsapps", "classification");
}
};

View File

@ -8,8 +8,6 @@ import { Op, where } from "sequelize";
import wbotByUserQueue from "../helpers/GetWbotByUserQueue"; import wbotByUserQueue from "../helpers/GetWbotByUserQueue";
// import WhatsQueueIndex from "./WhatsQueueIndex";
import { WhatsIndex } from "./LoadBalanceWhatsSameQueue"; import { WhatsIndex } from "./LoadBalanceWhatsSameQueue";
interface Request { interface Request {
@ -35,7 +33,7 @@ const GetDefaultWhatsApp = async ({
if (userId && queueId) { if (userId && queueId) {
if (whatsapps.length > 1) { if (whatsapps.length > 1) {
let whatsAppOfficial: any = whatsapps.find( let whatsAppOfficial: any = whatsapps.find(
(w: any) => w.phoneNumberId != null (w: any) => w.phoneNumberId && w.phoneNumberId.trim().length > 0
); );
if (whatsAppOfficial) { if (whatsAppOfficial) {

View File

@ -1,49 +0,0 @@
import Ticket from "../models/Ticket";
import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber";
import GetTicketWbot from "./GetTicketWbot";
const sendMessageMultiSession = async (ticket: Ticket, body?: any, quotedMsgSerializedId?: any, sendSeen?: boolean) => {
let sentMessage: any = ''
const listWhatsapp: any = await ListWhatsAppsNumber(ticket.whatsappId, 'CONNECTED')
if (listWhatsapp.length > 0) {
for (let w = 0; w < listWhatsapp.length; w++) {
if(listWhatsapp[w].id == ticket.whatsappId) continue
try {
console.log('CHANGE THE WHATSAPP SESSION ID: ', listWhatsapp[w].id)
await ticket.update({ whatsappId: listWhatsapp[w].id })
const wbot = await GetTicketWbot(ticket);
if (sendSeen) {
await wbot.sendSeen(`${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`);
}
else if (body) {
sentMessage = await wbot.sendMessage(`${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us`, body, { quotedMessageId: quotedMsgSerializedId, linkPreview: false });
}
break
} catch (error) {
console.log('Cannot send send the message using the whatsapp id: ', listWhatsapp[w].id, ' | error: ', error)
}
}
}
return sentMessage
};
export default sendMessageMultiSession;

View File

@ -0,0 +1,21 @@
import whatsappOfficialAPI from "./WhatsappOfficialAPI";
async function whatsappOfficialNumberInfo(wabaId: string) {
try {
const { data } = await whatsappOfficialAPI.get(
`/${process.env.VERSION}/${wabaId}/phone_numbers`
);
console.log("data: ", data);
if (data && Object.keys(data).length > 0) {
return data.data[0];
}
} catch (error) {
console.log(
`There was an error into whatsappOfficialNumberInfo method : ${error}`
);
}
return null;
}
export default whatsappOfficialNumberInfo;

View File

@ -1,39 +1,28 @@
const fsPromises = require("fs/promises"); const fsPromises = require("fs/promises");
const fs = require('fs') const fs = require("fs");
import axios from 'axios'; import axios from "axios";
import * as https from "https"; import * as https from "https";
const endPointQuery = async (url: string, data: any) => { const endPointQuery = async (url: string, data: any) => {
let response: any = null;
let response: any = null
try { try {
response = await axios.post(url, data); response = await axios.post(url, data);
console.log(`TEST URL CLIENT POST ROUTE: ${url} | STATUS CODE: ${response.status}`); console.log(
`TEST URL CLIENT POST ROUTE: ${url} | STATUS CODE: ${response.status}`
);
} catch (err: any) { } catch (err: any) {
if (err.response) { if (err.response) {
// The client was given an error response (5xx, 4xx) console.log("err.response: ", err.response);
// console.log('err.response: ', err.response)
console.log('err.response: ', err.response)
// return { data: err.response.data, status: err.response.status }
} else if (err.request) { } else if (err.request) {
// The client never received a response, and the request was never left console.log("err.request: ", err.request);
console.log('err.request: ', err.request)
} else { } else {
// Anything else
console.error(`Erro ao consultar endpoint ${url}: ${err}`); console.error(`Erro ao consultar endpoint ${url}: ${err}`);
} }
} }
return response return response;
};
}
export default endPointQuery; export default endPointQuery;

View File

@ -65,6 +65,17 @@ class Whatsapp extends Model<Whatsapp> {
@Column @Column
phoneNumberId: string; phoneNumberId: string;
@Column
classification: string;
@Column
wabaId: string;
@Default(false)
@AllowNull
@Column
isOfficial: boolean;
@Default(false) @Default(false)
@AllowNull @AllowNull
@Column @Column

View File

@ -16,6 +16,10 @@ const DeleteWhatsAppMessage = async (messageId: string): Promise<Message | any>
] ]
}); });
if(message && message?.phoneNumberId){
throw new AppError("Mensagens enviada pela API Oficial do Whatsapp não são deletadas!");
}
if (!message) { if (!message) {
throw new AppError("No message found with this ID."); throw new AppError("No message found with this ID.");
} }
@ -32,18 +36,6 @@ const DeleteWhatsAppMessage = async (messageId: string): Promise<Message | any>
limit: limit limit: limit
}) })
// console.log('messageToDelete.data.data: ',messageToDelete.data.data)
// const { ticket } = message;
// const messageToDelete = await GetWbotMessage(ticket, messageId);
// try {
// await messageToDelete.delete(true);
// } catch (err) {
// throw new AppError("ERR_DELETE_WAPP_MSG");
// }
if (messageToDelete && messageToDelete.data.data) { if (messageToDelete && messageToDelete.data.data) {
await message.update({ isDeleted: true }); await message.update({ isDeleted: true });
} }

View File

@ -21,7 +21,6 @@ import ListWhatsAppsNumber from "../WhatsappService/ListWhatsAppsNumber";
import { getWbot } from "../../libs/wbot"; import { getWbot } from "../../libs/wbot";
import { json } from "sequelize/types"; import { json } from "sequelize/types";
import sendMessageMultiSession from "../../helpers/TrySendMessageMultiSession";
import { restartWhatsSession } from "../../helpers/RestartWhatsSession"; import { restartWhatsSession } from "../../helpers/RestartWhatsSession";
// import { insertOrUpeateWhatsCache, searchWhatsappCache } from "../../helpers/WhatsCache"; // import { insertOrUpeateWhatsCache, searchWhatsappCache } from "../../helpers/WhatsCache";
import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp";
@ -83,6 +82,7 @@ const SendWhatsAppMessage = async ({
if (!listWhatsapp) { if (!listWhatsapp) {
listWhatsapp = await ListWhatsAppsNumber(ticket.whatsappId, "CONNECTED"); listWhatsapp = await ListWhatsAppsNumber(ticket.whatsappId, "CONNECTED");
console.log("@@@@@@@@@@@ listWhatsapp: ", listWhatsapp);
} }
if ( if (
@ -106,20 +106,21 @@ const SendWhatsAppMessage = async ({
listWhatsapp.whatsapps.length == 0 && listWhatsapp.whatsapps.length == 0 &&
listWhatsapp.whatsapp.status != "CONNECTED" listWhatsapp.whatsapp.status != "CONNECTED"
) { ) {
console.log("listWhatsapp.whatsapps == 0");
whatsapps = await wbotByUserQueue({ userId: ticket.userId }); whatsapps = await wbotByUserQueue({ userId: ticket.userId });
console.log("============> The whatsapps: ", whatsapps);
if (whatsapps.length > 0) { if (whatsapps.length > 0) {
whatsapps = whatsapps.filter((w: any) => !w?.isOfficial);
if (whatsapps.length > 1) { if (whatsapps.length > 1) {
await ticket.update({ await ticket.update({
whatsappId: whatsapps[+WhatsIndex(whatsapps)].id whatsappId: whatsapps[+WhatsIndex(whatsapps)].id
}); });
} else { } else if (whatsapps && whatsapps.length == 1) {
await ticket.update({ whatsappId: whatsapps[0].id }); await ticket.update({ whatsappId: whatsapps[0].id });
} }
else{
throw new Error('Sessão de Whatsapp desconectada! Entre em contato com o suporte.')
}
} }
} }

View File

@ -153,7 +153,7 @@ const verifyMediaMessage = async (
throw new Error("ERR_WAPP_DOWNLOAD_MEDIA"); throw new Error("ERR_WAPP_DOWNLOAD_MEDIA");
} }
const messageData = { let messageData = {
id: msg.id.id, id: msg.id.id,
ticketId: ticket.id, ticketId: ticket.id,
contactId: msg.fromMe ? undefined : contact.id, contactId: msg.fromMe ? undefined : contact.id,
@ -165,10 +165,16 @@ const verifyMediaMessage = async (
quotedMsgId: quotedMsg quotedMsgId: quotedMsg
}; };
if (!ticket?.phoneNumberId) { if (!ticket?.phoneNumberId) {
if (!media.filename) { if (!media.filename) {
const ext = media.mimetype.split("/")[1].split(";")[0]; const ext = media.mimetype.split("/")[1].split(";")[0];
media.filename = `${new Date().getTime()}.${ext}`; media.filename = `${new Date().getTime()}.${ext}`;
messageData = {
...messageData,
mediaUrl: media.filename,
body: media.filename
};
} }
try { try {
@ -189,6 +195,77 @@ const verifyMediaMessage = async (
return newMessage; return newMessage;
}; };
// const verifyMediaMessage = async (
// msg: any,
// ticket: Ticket,
// contact: Contact,
// media: any,
// quotedMsg?: any
// ): Promise<Message | any> => {
// // const quotedMsg = await verifyQuotedMessage(msg);
// // const media = await msg.downloadMedia();
// if (!media) {
// throw new Error("ERR_WAPP_DOWNLOAD_MEDIA");
// }
// console.log(
// "MEDIA.FILENAME: ",
// media.fileName,
// " | msg.fromMe: ",
// msg.fromMe
// );
// if (!media.filename) {
// console.log("No file name -----------------------------------------");
// const ext = media.mimetype.split("/")[1].split(";")[0];
// media.filename = `${new Date().getTime()}.${ext}`;
// }
// try {
// // await writeFileAsync(
// // join(__dirname, "..", "..", "..", "public", media.filename),
// // media.data,
// // "base64"
// // );
// console.log("FROM wbotMessageListener.ts media.filename: ", media.filename);
// await writeFileAsync(
// join(__dirname, "..", "..", "..", "..", "..", "public", media.filename),
// media.data,
// "base64"
// );
// } catch (err) {
// Sentry.captureException(err);
// logger.error(`There was an error: wbotMessageLitener.ts: ${err}`);
// }
// const messageData = {
// id: msg.id.id,
// ticketId: ticket.id,
// contactId: msg.fromMe ? undefined : contact.id,
// body: msg.body || media.filename,
// fromMe: msg.fromMe,
// read: msg.fromMe,
// mediaUrl: media.filename,
// mediaType: media.mimetype.split("/")[0],
// quotedMsgId: quotedMsg
// // quotedMsgId: quotedMsg?.id
// };
// await ticket.update({ lastMessage: msg.body || media.filename });
// const newMessage = await CreateMessageService({ messageData });
// return newMessage;
// };
const verifyMessage = async ( const verifyMessage = async (
msg: any, msg: any,
ticket: Ticket, ticket: Ticket,

View File

@ -13,6 +13,9 @@ interface Request {
farewellMessage?: string; farewellMessage?: string;
status?: string; status?: string;
isDefault?: boolean; isDefault?: boolean;
phoneNumberId?: string;
wabaId?: string;
isOfficial?: boolean;
} }
interface Response { interface Response {
@ -29,10 +32,11 @@ const CreateWhatsAppService = async ({
greetingMessage, greetingMessage,
farewellMessage, farewellMessage,
isDefault = false, isDefault = false,
isOfficial = false,
phoneNumberId,
wabaId
}: Request): Promise<Response> => { }: Request): Promise<Response> => {
try { try {
const schema = Yup.object().shape({ const schema = Yup.object().shape({
name: Yup.string() name: Yup.string()
.required() .required()
@ -48,12 +52,11 @@ const CreateWhatsAppService = async ({
return !nameExists; return !nameExists;
} }
), ),
isDefault: Yup.boolean().required(), isDefault: Yup.boolean().required()
urlApi: Yup.string().required()
}); });
try { try {
await schema.validate({ name, status, isDefault, urlApi }); await schema.validate({ name, status, isDefault });
} catch (err: any) { } catch (err: any) {
throw new AppError(err.message); throw new AppError(err.message);
} }
@ -70,7 +73,6 @@ const CreateWhatsAppService = async ({
}); });
if (oldDefaultWhatsapp) { if (oldDefaultWhatsapp) {
await oldDefaultWhatsapp.update({ isDefault: false }); await oldDefaultWhatsapp.update({ isDefault: false });
} }
} }
@ -78,6 +80,12 @@ const CreateWhatsAppService = async ({
throw new AppError("ERR_WAPP_GREETING_REQUIRED"); throw new AppError("ERR_WAPP_GREETING_REQUIRED");
} }
const classification = isOfficial ? "GREEN" : null;
if (isOfficial) {
status = "CONNECTED";
}
const whatsapp = await Whatsapp.create( const whatsapp = await Whatsapp.create(
{ {
name, name,
@ -86,7 +94,11 @@ const CreateWhatsAppService = async ({
urlApi, urlApi,
greetingMessage, greetingMessage,
farewellMessage, farewellMessage,
isDefault isDefault,
phoneNumberId,
wabaId,
isOfficial,
classification
}, },
{ include: ["queues"] } { include: ["queues"] }
); );
@ -94,13 +106,10 @@ const CreateWhatsAppService = async ({
await AssociateWhatsappQueue(whatsapp, queueIds); await AssociateWhatsappQueue(whatsapp, queueIds);
return { whatsapp, oldDefaultWhatsapp }; return { whatsapp, oldDefaultWhatsapp };
} catch (error: any) { } catch (error: any) {
console.error('===> Error on CreateWhatsAppService.ts file: \n', error) console.error("===> Error on CreateWhatsAppService.ts file: \n", error);
throw new AppError(error.message); throw new AppError(error.message);
} }
}; };
export default CreateWhatsAppService; export default CreateWhatsAppService;

View File

@ -12,14 +12,14 @@ const ListWhatsAppsNumber = async (
if (status) { if (status) {
whatsapps = await Whatsapp.findAll({ whatsapps = await Whatsapp.findAll({
raw: true, raw: true,
where: { number: whatsapp.number, status: status }, where: { number: whatsapp.number, status: status, },
attributes: ["id", "number", "status", "isDefault", "url"] attributes: ["id", "number", "status", "isDefault", "url", 'isOfficial']
}); });
} else { } else {
whatsapps = await Whatsapp.findAll({ whatsapps = await Whatsapp.findAll({
raw: true, raw: true,
where: { number: whatsapp.number }, where: { number: whatsapp.number },
attributes: ["id", "number", "status", "isDefault", "url"] attributes: ["id", "number", "status", "isDefault", "url", 'isOfficial']
}); });
} }

View File

@ -9,8 +9,6 @@ import AssociateWhatsappQueue from "./AssociateWhatsappQueue";
import { getWbot } from "../../libs/wbot"; import { getWbot } from "../../libs/wbot";
import { restartWhatsSession } from "../../helpers/RestartWhatsSession"; import { restartWhatsSession } from "../../helpers/RestartWhatsSession";
interface WhatsappData { interface WhatsappData {
name?: string; name?: string;
url?: string; url?: string;
@ -18,6 +16,9 @@ interface WhatsappData {
status?: string; status?: string;
session?: string; session?: string;
isDefault?: boolean; isDefault?: boolean;
isOfficial?: boolean;
phoneNumberId?: string;
wabaId?: string;
greetingMessage?: string; greetingMessage?: string;
farewellMessage?: string; farewellMessage?: string;
queueIds?: number[]; queueIds?: number[];
@ -37,19 +38,20 @@ const UpdateWhatsAppService = async ({
whatsappData, whatsappData,
whatsappId whatsappId
}: Request): Promise<Response> => { }: Request): Promise<Response> => {
try { try {
const schema = Yup.object().shape({ const schema = Yup.object().shape({
name: Yup.string().min(2), name: Yup.string().min(2),
status: Yup.string(), status: Yup.string(),
isDefault: Yup.boolean() isDefault: Yup.boolean()
}); });
const { let {
name, name,
status, status,
isDefault, isDefault,
phoneNumberId,
wabaId,
isOfficial,
url, url,
urlApi, urlApi,
session, session,
@ -58,8 +60,6 @@ const UpdateWhatsAppService = async ({
queueIds = [] queueIds = []
} = whatsappData; } = whatsappData;
try { try {
await schema.validate({ name, status, isDefault }); await schema.validate({ name, status, isDefault });
} catch (err: any) { } catch (err: any) {
@ -85,10 +85,23 @@ const UpdateWhatsAppService = async ({
// console.log('############## whatsapp: ', JSON.parse(JSON.stringify(whatsapp))) // console.log('############## whatsapp: ', JSON.parse(JSON.stringify(whatsapp)))
if (name && !name.includes(whatsapp.number) && whatsapp.status === 'CONNECTED') { if (
name &&
!name.includes(whatsapp.number) &&
whatsapp.status === "CONNECTED" &&
!whatsapp.isOfficial
) {
throw new AppError("ERR_WAPP_WRONG_SESSION_NAME"); throw new AppError("ERR_WAPP_WRONG_SESSION_NAME");
}
const classification = isOfficial ? "GREEN" : null;
if (isOfficial) {
status = "CONNECTED";
}
if (whatsapp.isOfficial && !isOfficial) {
status = "OPENING";
} }
await whatsapp.update({ await whatsapp.update({
@ -99,7 +112,11 @@ const UpdateWhatsAppService = async ({
urlApi, urlApi,
greetingMessage, greetingMessage,
farewellMessage, farewellMessage,
isDefault isDefault,
isOfficial,
phoneNumberId,
wabaId,
classification
}); });
// await insertOrUpeateWhatsCache(`whatsapp:${whatsapp.id}`, { // await insertOrUpeateWhatsCache(`whatsapp:${whatsapp.id}`, {
@ -114,12 +131,10 @@ const UpdateWhatsAppService = async ({
await AssociateWhatsappQueue(whatsapp, queueIds); await AssociateWhatsappQueue(whatsapp, queueIds);
return { whatsapp, oldDefaultWhatsapp }; return { whatsapp, oldDefaultWhatsapp };
} catch (error: any) { } catch (error: any) {
console.error('===> Error on UpdateWhatsAppService.ts file: \n', error) console.error("===> Error on UpdateWhatsAppService.ts file: \n", error);
throw new AppError(error.message); throw new AppError(error.message);
} }
}; };
export default UpdateWhatsAppService; export default UpdateWhatsAppService;

View File

@ -8,7 +8,6 @@ import Select from "@material-ui/core/Select"
import FormControl from "@material-ui/core/FormControl" import FormControl from "@material-ui/core/FormControl"
import InputLabel from "@material-ui/core/InputLabel" import InputLabel from "@material-ui/core/InputLabel"
import MenuItem from "@material-ui/core/MenuItem" import MenuItem from "@material-ui/core/MenuItem"
import LinearProgress from "@material-ui/core/LinearProgress"
import { makeStyles } from "@material-ui/core" import { makeStyles } from "@material-ui/core"
import DialogActions from "@material-ui/core/DialogActions" import DialogActions from "@material-ui/core/DialogActions"
@ -21,9 +20,6 @@ import { AuthContext } from "../../context/Auth/AuthContext"
import toastError from "../../errors/toastError" import toastError from "../../errors/toastError"
import { WhatsAppsContext } from "../../context/WhatsApp/WhatsAppsContext"
import api from "../../services/api" import api from "../../services/api"
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
@ -40,7 +36,6 @@ const useStyles = makeStyles((theme) => ({
const ContactCreateTicketModal = ({ modalOpen, onClose, contactId }) => { const ContactCreateTicketModal = ({ modalOpen, onClose, contactId }) => {
const { user } = useContext(AuthContext) const { user } = useContext(AuthContext)
const { whatsApps } = useContext(WhatsAppsContext)
let isMounted = useRef(true) let isMounted = useRef(true)
@ -65,8 +60,6 @@ const ContactCreateTicketModal = ({ modalOpen, onClose, contactId }) => {
const { data } = await api.get("/whatsapp/official/matchQueueUser", { params: { userId: user.id, queueId: selectedQueue }, }) const { data } = await api.get("/whatsapp/official/matchQueueUser", { params: { userId: user.id, queueId: selectedQueue }, })
console.log('DATA: ', data)
setQueues(data) setQueues(data)
} catch (err) { } catch (err) {
@ -79,7 +72,7 @@ const ContactCreateTicketModal = ({ modalOpen, onClose, contactId }) => {
}, 500) }, 500)
return () => clearTimeout(delayDebounceFn) return () => clearTimeout(delayDebounceFn)
}, [user]) }, [user, selectedQueue])
const handleClose = () => { const handleClose = () => {
onClose() onClose()
@ -87,9 +80,7 @@ const ContactCreateTicketModal = ({ modalOpen, onClose, contactId }) => {
const handleSaveTicket = useCallback(async (contactId, userId, queueId, selectedWhatsId, whatsQueue, queues) => { const handleSaveTicket = useCallback(async (contactId, userId, queueId, selectedWhatsId, whatsQueue, queues) => {
console.log(`contactId: ${contactId}, userId: ${userId}, queueId: ${queueId}, selectedWhatsId: ${selectedWhatsId}, whatsQueue: ${whatsQueue}, queues: ${queues}`) if (queues && queues.length === 1 && queues[0].disable) {
if (queues && queues.length == 1 && queues[0].disable) {
toast.warn('Não é possível criar um Ticket porque a fila a qual você esta adicionado(a) não está associado a nenhum numero!') toast.warn('Não é possível criar um Ticket porque a fila a qual você esta adicionado(a) não está associado a nenhum numero!')
return return
} }
@ -137,15 +128,11 @@ const ContactCreateTicketModal = ({ modalOpen, onClose, contactId }) => {
useEffect(() => { useEffect(() => {
if (selectedQueue && selectedQueue.length === 0 || !selectedQueue) { if (selectedQueue && (selectedQueue.length === 0 || !selectedQueue)) {
setDisabled(true) setDisabled(true)
setWhatsQueue(null) setWhatsQueue(null)
} }
// if (modalOpen && queues.length <= 1) {
// handleSaveTicket(contactId, user.id, selectedQueue, selectedWhatsId, whatsQueue, queues)
// }
if (!Array.isArray(whatsQueue)) { if (!Array.isArray(whatsQueue)) {
setSelectedWhatsId(null) setSelectedWhatsId(null)
setWhatsQueue(null) setWhatsQueue(null)
@ -170,6 +157,8 @@ const ContactCreateTicketModal = ({ modalOpen, onClose, contactId }) => {
const { data } = await api.get("/whatsapp/official/matchQueue", { params: { userId: user.id, queueId: selectedQueue }, }) const { data } = await api.get("/whatsapp/official/matchQueue", { params: { userId: user.id, queueId: selectedQueue }, })
console.log('WHATSAPP DATA: ', data)
setWhatsQueue(data) setWhatsQueue(data)
setDisabled(false) setDisabled(false)
@ -186,10 +175,10 @@ const ContactCreateTicketModal = ({ modalOpen, onClose, contactId }) => {
}, [selectedQueue, user.id]) }, [selectedQueue, user.id])
useEffect(() => {
// if (modalOpen && queues.length <= 1) { console.log('selectedWhatsId: ', selectedWhatsId)
// return <LinearProgress /> console.log('whatsQuee: ', whatsQueue)
// } }, [whatsQueue])
return ( return (
<Dialog open={modalOpen} onClose={handleClose} maxWidth="xs" scroll="paper" classes={{ paper: classes.paper }}> <Dialog open={modalOpen} onClose={handleClose} maxWidth="xs" scroll="paper" classes={{ paper: classes.paper }}>

View File

@ -41,28 +41,6 @@ const useStyles = makeStyles(theme => ({
})) }))
let _fifo
// const onlineEmitter = async (socket, user) => {
// try {
// clearInterval(_fifo);
// socket.emit("online", user.id)
// } catch (error) {
// console.log('error on onlineEmitter: ', error)
// }
// finally {
// _fifo = setInterval(onlineEmitter, 3000);
// }
// }
// _fifo = setInterval(onlineEmitter, 3000);
const NotificationsPopOver = () => { const NotificationsPopOver = () => {
const classes = useStyles() const classes = useStyles()

View File

@ -60,7 +60,7 @@ const SessionSchema = Yup.object().shape({
.required('Required'), .required('Required'),
}) })
const WhatsAppModal = ({ open, onClose, whatsAppId }) => { const WhatsAppModal = ({ open, onClose, whatsAppId, whatsAppOfficial }) => {
const classes = useStyles() const classes = useStyles()
const initialState = { const initialState = {
name: '', name: '',
@ -69,12 +69,17 @@ const WhatsAppModal = ({ open, onClose, whatsAppId }) => {
greetingMessage: '', greetingMessage: '',
farewellMessage: '', farewellMessage: '',
isDefault: false, isDefault: false,
isOfficial: false,
phoneNumberId: '',
wabaId: ''
} }
const { user } = useContext(AuthContext) const { user } = useContext(AuthContext)
const [whatsApp, setWhatsApp] = useState(initialState) const [whatsApp, setWhatsApp] = useState(initialState)
const [selectedQueueIds, setSelectedQueueIds] = useState([]) const [selectedQueueIds, setSelectedQueueIds] = useState([])
const [isOfficial, setIsOfficial] = useState(false)
useEffect(() => { useEffect(() => {
const fetchSession = async () => { const fetchSession = async () => {
@ -82,7 +87,9 @@ const WhatsAppModal = ({ open, onClose, whatsAppId }) => {
try { try {
const { data } = await api.get(`whatsapp/${whatsAppId}`) const { data } = await api.get(`whatsapp/${whatsAppId}`)
setWhatsApp(data) setWhatsApp(data)
setIsOfficial(data?.isOfficial)
const whatsQueueIds = data.queues?.map((queue) => queue.id) const whatsQueueIds = data.queues?.map((queue) => queue.id)
setSelectedQueueIds(whatsQueueIds) setSelectedQueueIds(whatsQueueIds)
@ -94,6 +101,17 @@ const WhatsAppModal = ({ open, onClose, whatsAppId }) => {
}, [whatsAppId]) }, [whatsAppId])
const handleSaveWhatsApp = async (values) => { const handleSaveWhatsApp = async (values) => {
console.log('values1: ', values)
const { isOfficial } = values
if (!isOfficial) {
values.phoneNumberId = ''
values.wabaId = ''
}
const whatsappData = { ...values, queueIds: selectedQueueIds } const whatsappData = { ...values, queueIds: selectedQueueIds }
let response = null let response = null
@ -131,6 +149,7 @@ const WhatsAppModal = ({ open, onClose, whatsAppId }) => {
const handleClose = () => { const handleClose = () => {
onClose() onClose()
setWhatsApp(initialState) setWhatsApp(initialState)
setIsOfficial(false)
} }
return ( return (
@ -189,8 +208,26 @@ const WhatsAppModal = ({ open, onClose, whatsAppId }) => {
} }
label={i18n.t('whatsappModal.form.default')} label={i18n.t('whatsappModal.form.default')}
/> />
{whatsAppOfficial &&
<FormControlLabel
control={
<Field
as={Switch}
color="primary"
name="isOfficial"
onClick={() => setIsOfficial(!isOfficial)}
checked={values.isOfficial}
/>
}
label={'Whatsapp Oficial'}
/>
}
</div> </div>
<div className={classes.multFieldLine}>
{!isOfficial ? <div className={classes.multFieldLine}>
<Field <Field
as={TextField} as={TextField}
label="url API" label="url API"
@ -213,7 +250,39 @@ const WhatsAppModal = ({ open, onClose, whatsAppId }) => {
margin="dense" margin="dense"
className={classes.textField} className={classes.textField}
/> />
</div> :
<div className={classes.multFieldLine}>
<Field
as={TextField}
label="Phone number id"
autoFocus
name="phoneNumberId"
error={touched.name && Boolean(errors.name)}
helperText={touched.name && errors.name}
variant="outlined"
margin="dense"
className={classes.textField}
/>
<Field
as={TextField}
label="WABA ID"
autoFocus
name="wabaId"
error={touched.name && Boolean(errors.name)}
helperText={touched.name && errors.name}
variant="outlined"
margin="dense"
className={classes.textField}
/>
</div> </div>
}
</> </>
)} )}
/> />

View File

@ -5,9 +5,9 @@ import { format, parseISO } from 'date-fns'
import openSocket from 'socket.io-client' import openSocket from 'socket.io-client'
import { makeStyles } from '@material-ui/core/styles' import { makeStyles } from '@material-ui/core/styles'
import { green } from '@material-ui/core/colors' import { green, red, yellow, grey } from '@material-ui/core/colors'
import Settings from "@material-ui/icons/Settings"; import Settings from "@material-ui/icons/Settings"
import { import {
Button, Button,
@ -27,6 +27,7 @@ import {
CheckCircle, CheckCircle,
SignalCellularConnectedNoInternet2Bar, SignalCellularConnectedNoInternet2Bar,
SignalCellularConnectedNoInternet0Bar, SignalCellularConnectedNoInternet0Bar,
FiberManualRecord,
SignalCellular4Bar, SignalCellular4Bar,
CropFree, CropFree,
DeleteOutline, DeleteOutline,
@ -103,6 +104,33 @@ const CustomToolTip = ({ title, content, children }) => {
) )
} }
const whatsAppClasssification = ({ isOfficial, classification }) => {
if (isOfficial && classification) {
if (classification === 'GREEN')
return <CustomToolTip title={'Qualidade alta'}>
<FiberManualRecord style={{ color: green[500] }} />
</CustomToolTip>
if (classification === 'YELLOW')
return <CustomToolTip title={'Qualidade média'}>
<FiberManualRecord style={{ color: yellow[500] }} />
</CustomToolTip>
if (classification === 'RED')
return <CustomToolTip title={'Qualidade baixa'}>
<FiberManualRecord style={{ color: red[500] }} />
</CustomToolTip>
}
else {
return <CustomToolTip title={i18n.t('connections.toolTips.connected.title')}>
<SignalCellular4Bar style={{ color: green[500] }} />
</CustomToolTip>
}
}
const Connections = () => { const Connections = () => {
//-------- //--------
const { user } = useContext(AuthContext) const { user } = useContext(AuthContext)
@ -118,8 +146,6 @@ const Connections = () => {
const [diskSpaceInfo, setDiskSpaceInfo] = useState({}) const [diskSpaceInfo, setDiskSpaceInfo] = useState({})
const [disabled, setDisabled] = useState(true)
const [settings, setSettings] = useState([]) const [settings, setSettings] = useState([])
const [buttons, setClicks] = useState([]) const [buttons, setClicks] = useState([])
@ -139,6 +165,7 @@ const Connections = () => {
const fetchSession = async () => { const fetchSession = async () => {
try { try {
const { data } = await api.get('/settings') const { data } = await api.get('/settings')
setSettings(data.settings) setSettings(data.settings)
} catch (err) { } catch (err) {
toastError(err) toastError(err)
@ -149,7 +176,6 @@ const Connections = () => {
const getSettingValue = (key) => { const getSettingValue = (key) => {
const { value } = settings.find((s) => s.key === key) const { value } = settings.find((s) => s.key === key)
return value return value
} }
@ -162,6 +188,7 @@ const Connections = () => {
} }
const handleRestartWhatsAppSession = async (whatsapp) => { const handleRestartWhatsAppSession = async (whatsapp) => {
try { try {
whatsapp.disabled = true whatsapp.disabled = true
@ -280,6 +307,9 @@ const Connections = () => {
} }
const renderActionButtons = (whatsApp) => { const renderActionButtons = (whatsApp) => {
if (whatsApp.isOfficial) return
return ( return (
<Can <Can
role={user.profile} role={user.profile}
@ -352,7 +382,15 @@ const Connections = () => {
<SignalCellularConnectedNoInternet0Bar color="secondary" /> <SignalCellularConnectedNoInternet0Bar color="secondary" />
</CustomToolTip> </CustomToolTip>
)} )}
{whatsApp.status === 'OPENING' && ( {whatsApp.status === 'OPENING' && whatsApp.isOfficial && (settings &&
settings.length > 0 &&
getSettingValue('whatsaAppCloudApi') &&
getSettingValue('whatsaAppCloudApi') === 'disabled') && (
<CustomToolTip title={'Whatsapp Cloud API está desativado'}>
<FiberManualRecord style={{ color: grey[500] }} />
</CustomToolTip>
)}
{whatsApp.status === 'OPENING' && !whatsApp.isOfficial && (
<CircularProgress size={24} className={classes.buttonProgress} /> <CircularProgress size={24} className={classes.buttonProgress} />
)} )}
{whatsApp.status === 'qrcode' && ( {whatsApp.status === 'qrcode' && (
@ -363,11 +401,11 @@ const Connections = () => {
<CropFree /> <CropFree />
</CustomToolTip> </CustomToolTip>
)} )}
{whatsApp.status === 'CONNECTED' && ( {whatsApp.status === 'CONNECTED' && (
<CustomToolTip title={i18n.t('connections.toolTips.connected.title')}> whatsAppClasssification({ ...whatsApp, })
<SignalCellular4Bar style={{ color: green[500] }} />
</CustomToolTip>
)} )}
{(whatsApp.status === 'TIMEOUT' || whatsApp.status === 'PAIRING') && ( {(whatsApp.status === 'TIMEOUT' || whatsApp.status === 'PAIRING') && (
<CustomToolTip <CustomToolTip
title={i18n.t('connections.toolTips.timeout.title')} title={i18n.t('connections.toolTips.timeout.title')}
@ -397,8 +435,6 @@ const Connections = () => {
params: { status: 'status' }, params: { status: 'status' },
}) })
setDisabled(false)
setClicks((buttons) => setClicks((buttons) =>
buttons.map((e) => { buttons.map((e) => {
return { id: e.id, disabled: false } return { id: e.id, disabled: false }
@ -464,6 +500,10 @@ const Connections = () => {
open={whatsAppModalOpen} open={whatsAppModalOpen}
onClose={handleCloseWhatsAppModal} onClose={handleCloseWhatsAppModal}
whatsAppId={!qrModalOpen && selectedWhatsApp?.id} whatsAppId={!qrModalOpen && selectedWhatsApp?.id}
whatsAppOfficial={(settings &&
settings.length > 0 &&
getSettingValue('whatsaAppCloudApi') &&
getSettingValue('whatsaAppCloudApi') === 'enabled') ? true : false}
/> />
<ConfigModal <ConfigModal
@ -567,13 +607,13 @@ const Connections = () => {
yes={() => <TableCell align="center">Restore</TableCell>} yes={() => <TableCell align="center">Restore</TableCell>}
/> />
<Can {/* <Can
role={user.profile} role={user.profile}
perform="connection-button:show" perform="connection-button:show"
yes={() => ( yes={() => (
<TableCell align="center">Session MB</TableCell> <TableCell align="center">Session MB</TableCell>
)} )}
/> /> */}
<TableCell align="center"> <TableCell align="center">
{i18n.t('connections.table.lastUpdate')} {i18n.t('connections.table.lastUpdate')}
@ -592,8 +632,24 @@ const Connections = () => {
) : ( ) : (
<> <>
{whatsApps?.length > 0 && {whatsApps?.length > 0 &&
whatsApps.map((whatsApp) => ( whatsApps.map((whatsApp) => {
<TableRow key={whatsApp.id}>
let disabledRow = {}
let disabled = false
if (whatsApp?.isOfficial && ((settings &&
settings.length > 0 &&
getSettingValue('whatsaAppCloudApi') &&
getSettingValue('whatsaAppCloudApi') === 'disabled'))) {
disabledRow = {
'opacity': '0.5',
// 'pointer-events': 'none'
}
disabled = true
}
return (
<TableRow key={whatsApp.id} style={disabledRow}>
<TableCell align="center"> <TableCell align="center">
{whatsApp.name} {whatsApp.name}
</TableCell> </TableCell>
@ -617,6 +673,8 @@ const Connections = () => {
perform="connection-button:show" perform="connection-button:show"
yes={() => ( yes={() => (
<TableCell align="center"> <TableCell align="center">
{!whatsApp?.isOfficial &&
<Button <Button
disabled={ disabled={
whatsApp.disabled || disabled whatsApp.disabled || disabled
@ -631,12 +689,14 @@ const Connections = () => {
} }
> >
Restore Restore
</Button> </Button>}
</TableCell> </TableCell>
)} )}
/> />
<Can {/* <Can
role={user.profile} role={user.profile}
perform="connection-button:show" perform="connection-button:show"
yes={() => ( yes={() => (
@ -651,7 +711,7 @@ const Connections = () => {
</CustomToolTip> </CustomToolTip>
</TableCell> </TableCell>
)} )}
/> /> */}
<TableCell align="center"> <TableCell align="center">
{format( {format(
@ -726,7 +786,8 @@ const Connections = () => {
/> />
</TableCell> </TableCell>
</TableRow> </TableRow>
))} )
})}
</> </>
)} )}
</TableBody> </TableBody>

View File

@ -310,21 +310,6 @@ const Contacts = () => {
setIsCreateTicketModalOpen(false) setIsCreateTicketModalOpen(false)
} }
// const handleSaveTicket = async (contactId) => {
// if (!contactId) return;
// setLoading(true);
// try {
// const { data: ticket } = await api.post("/tickets", {
// contactId: contactId,
// userId: user?.id,
// status: "open",
// });
// history.push(`/tickets/${ticket.id}`);
// } catch (err) {
// toastError(err);
// }
// setLoading(false);
// };
const hadleEditContact = (contactId) => { const hadleEditContact = (contactId) => {
setSelectedContactId(contactId) setSelectedContactId(contactId)