Merge pull request #383 from ricardoapaes/feature/multiple-tickets-for-contacts

User default whatsapp and multiple tickets per contact
This commit is contained in:
Cassio Santos
2022-03-14 11:17:38 -03:00
committed by GitHub
28 changed files with 252 additions and 49 deletions

View File

@@ -4,6 +4,7 @@ import AppError from "../errors/AppError";
import GetDefaultWhatsApp from "../helpers/GetDefaultWhatsApp";
import SetTicketMessagesAsRead from "../helpers/SetTicketMessagesAsRead";
import Message from "../models/Message";
import Whatsapp from "../models/Whatsapp";
import CreateOrUpdateContactService from "../services/ContactServices/CreateOrUpdateContactService";
import FindOrCreateTicketService from "../services/TicketServices/FindOrCreateTicketService";
import ShowTicketService from "../services/TicketServices/ShowTicketService";
@@ -13,6 +14,10 @@ import GetProfilePicUrl from "../services/WbotServices/GetProfilePicUrl";
import SendWhatsAppMedia from "../services/WbotServices/SendWhatsAppMedia";
import SendWhatsAppMessage from "../services/WbotServices/SendWhatsAppMessage";
type WhatsappData = {
whatsappId: number;
}
type MessageData = {
body: string;
fromMe: boolean;
@@ -24,7 +29,10 @@ interface ContactData {
number: string;
}
const createContact = async (newContact: string) => {
const createContact = async (
whatsappId: number | undefined,
newContact: string
) => {
await CheckIsValidContact(newContact);
const validNumber: any = await CheckContactNumber(newContact);
@@ -42,11 +50,21 @@ const createContact = async (newContact: string) => {
const contact = await CreateOrUpdateContactService(contactData);
const defaultWhatsapp = await GetDefaultWhatsApp();
let whatsapp:Whatsapp | null;
if(whatsappId === undefined) {
whatsapp = await GetDefaultWhatsApp();
} else {
whatsapp = await Whatsapp.findByPk(whatsappId);
if(whatsapp === null) {
throw new AppError(`whatsapp #${whatsappId} not found`);
}
}
const createTicket = await FindOrCreateTicketService(
contact,
defaultWhatsapp.id,
whatsapp.id,
1
);
@@ -59,6 +77,7 @@ const createContact = async (newContact: string) => {
export const index = async (req: Request, res: Response): Promise<Response> => {
const newContact: ContactData = req.body;
const { whatsappId }: WhatsappData = req.body;
const { body, quotedMsg }: MessageData = req.body;
const medias = req.files as Express.Multer.File[];
@@ -76,7 +95,7 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
throw new AppError(err.message);
}
const contactAndTicket = await createContact(newContact.number);
const contactAndTicket = await createContact(whatsappId, newContact.number);
if (medias) {
await Promise.all(

View File

@@ -2,7 +2,8 @@ import { Request, Response } from "express";
import ImportContactsService from "../services/WbotServices/ImportContactsService";
export const store = async (req: Request, res: Response): Promise<Response> => {
await ImportContactsService();
const userId:number = parseInt(req.user.id);
await ImportContactsService(userId);
return res.status(200).json({ message: "contacts imported" });
};

View File

@@ -27,7 +27,7 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
};
export const store = async (req: Request, res: Response): Promise<Response> => {
const { email, password, name, profile, queueIds } = req.body;
const { email, password, name, profile, queueIds, whatsappId } = req.body;
if (
req.url === "/signup" &&
@@ -43,7 +43,8 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
password,
name,
profile,
queueIds
queueIds,
whatsappId
});
const io = getIO();

View File

@@ -0,0 +1,17 @@
import { QueryInterface, DataTypes } from "sequelize";
module.exports = {
up: (queryInterface: QueryInterface) => {
return queryInterface.addColumn("Users", "whatsappId", {
type: DataTypes.INTEGER,
references: { model: "Whatsapps", key: "id" },
onUpdate: "CASCADE",
onDelete: "SET NULL",
allowNull: true
},);
},
down: (queryInterface: QueryInterface) => {
return queryInterface.removeColumn("Users", "whatsappId");
}
};

View File

@@ -2,9 +2,12 @@ import { Op } from "sequelize";
import AppError from "../errors/AppError";
import Ticket from "../models/Ticket";
const CheckContactOpenTickets = async (contactId: number): Promise<void> => {
const CheckContactOpenTickets = async (
contactId: number,
whatsappId: number
): Promise<void> => {
const ticket = await Ticket.findOne({
where: { contactId, status: { [Op.or]: ["open", "pending"] } }
where: { contactId, whatsappId, status: { [Op.or]: ["open", "pending"] } }
});
if (ticket) {

View File

@@ -1,7 +1,17 @@
import AppError from "../errors/AppError";
import Whatsapp from "../models/Whatsapp";
import GetDefaultWhatsAppByUser from "./GetDefaultWhatsAppByUser";
const GetDefaultWhatsApp = async (
userId?: number
): Promise<Whatsapp> => {
if(userId) {
const whatsappByUser = await GetDefaultWhatsAppByUser(userId);
if(whatsappByUser !== null) {
return whatsappByUser;
}
}
const GetDefaultWhatsApp = async (): Promise<Whatsapp> => {
const defaultWhatsapp = await Whatsapp.findOne({
where: { isDefault: true }
});

View File

@@ -0,0 +1,20 @@
import User from "../models/User";
import Whatsapp from "../models/Whatsapp";
import { logger } from "../utils/logger";
const GetDefaultWhatsAppByUser = async (
userId: number
): Promise<Whatsapp | null> => {
const user = await User.findByPk(userId, {include: ["whatsapp"]});
if( user === null ) {
return null;
}
if(user.whatsapp !== null) {
logger.info(`Found whatsapp linked to user '${user.name}' is '${user.whatsapp.name}'.`);
}
return user.whatsapp;
};
export default GetDefaultWhatsAppByUser;

View File

@@ -5,7 +5,7 @@ import Ticket from "../models/Ticket";
const GetTicketWbot = async (ticket: Ticket): Promise<Session> => {
if (!ticket.whatsappId) {
const defaultWhatsapp = await GetDefaultWhatsApp();
const defaultWhatsapp = await GetDefaultWhatsApp(ticket.user.id);
await ticket.$set("whatsapp", defaultWhatsapp);
}

View File

@@ -1,5 +1,6 @@
import Queue from "../models/Queue";
import User from "../models/User";
import Whatsapp from "../models/Whatsapp";
interface SerializedUser {
id: number;
@@ -7,6 +8,7 @@ interface SerializedUser {
email: string;
profile: string;
queues: Queue[];
whatsapp: Whatsapp;
}
export const SerializeUser = (user: User): SerializedUser => {
@@ -15,6 +17,7 @@ export const SerializeUser = (user: User): SerializedUser => {
name: user.name,
email: user.email,
profile: user.profile,
queues: user.queues
queues: user.queues,
whatsapp: user.whatsapp
};
};

View File

@@ -11,12 +11,15 @@ import {
AutoIncrement,
Default,
HasMany,
BelongsToMany
BelongsToMany,
ForeignKey,
BelongsTo
} from "sequelize-typescript";
import { hash, compare } from "bcryptjs";
import Ticket from "./Ticket";
import Queue from "./Queue";
import UserQueue from "./UserQueue";
import Whatsapp from "./Whatsapp";
@Table
class User extends Model<User> {
@@ -45,6 +48,13 @@ class User extends Model<User> {
@Column
profile: string;
@ForeignKey(() => Whatsapp)
@Column
whatsappId: number;
@BelongsTo(() => Whatsapp)
whatsapp: Whatsapp;
@CreatedAt
createdAt: Date;

View File

@@ -2,30 +2,39 @@ import AppError from "../../errors/AppError";
import CheckContactOpenTickets from "../../helpers/CheckContactOpenTickets";
import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp";
import Ticket from "../../models/Ticket";
import User from "../../models/User";
import ShowContactService from "../ContactServices/ShowContactService";
interface Request {
contactId: number;
status: string;
userId: number;
queueId ?: number;
}
const CreateTicketService = async ({
contactId,
status,
userId
userId,
queueId
}: Request): Promise<Ticket> => {
const defaultWhatsapp = await GetDefaultWhatsApp();
const defaultWhatsapp = await GetDefaultWhatsApp(userId);
await CheckContactOpenTickets(contactId);
await CheckContactOpenTickets(contactId, defaultWhatsapp.id);
const { isGroup } = await ShowContactService(contactId);
if(queueId === undefined) {
const user = await User.findByPk(userId, { include: ["queues"]});
queueId = user?.queues.length === 1 ? user.queues[0].id : undefined;
}
const { id }: Ticket = await defaultWhatsapp.$create("ticket", {
contactId,
status,
isGroup,
userId
userId,
queueId
});
const ticket = await Ticket.findByPk(id, { include: ["contact"] });

View File

@@ -15,7 +15,8 @@ const FindOrCreateTicketService = async (
status: {
[Op.or]: ["open", "pending"]
},
contactId: groupContact ? groupContact.id : contact.id
contactId: groupContact ? groupContact.id : contact.id,
whatsappId: whatsappId
}
});
@@ -26,7 +27,8 @@ const FindOrCreateTicketService = async (
if (!ticket && groupContact) {
ticket = await Ticket.findOne({
where: {
contactId: groupContact.id
contactId: groupContact.id,
whatsappId: whatsappId
},
order: [["updatedAt", "DESC"]]
});
@@ -46,7 +48,8 @@ const FindOrCreateTicketService = async (
updatedAt: {
[Op.between]: [+subHours(new Date(), 2), +new Date()]
},
contactId: contact.id
contactId: contact.id,
whatsappId: whatsappId
},
order: [["updatedAt", "DESC"]]
});

View File

@@ -6,6 +6,7 @@ import Contact from "../../models/Contact";
import Message from "../../models/Message";
import Queue from "../../models/Queue";
import ShowUserService from "../UserServices/ShowUserService";
import Whatsapp from "../../models/Whatsapp";
interface Request {
searchParam?: string;
@@ -50,6 +51,11 @@ const ListTicketsService = async ({
model: Queue,
as: "queue",
attributes: ["id", "name", "color"]
},
{
model: Whatsapp,
as: "whatsapp",
attributes: ["name"]
}
];

View File

@@ -10,6 +10,7 @@ interface TicketData {
status?: string;
userId?: number;
queueId?: number;
whatsappId?: number;
}
interface Request {
@@ -27,16 +28,20 @@ const UpdateTicketService = async ({
ticketData,
ticketId
}: Request): Promise<Response> => {
const { status, userId, queueId } = ticketData;
const { status, userId, queueId, whatsappId } = ticketData;
const ticket = await ShowTicketService(ticketId);
await SetTicketMessagesAsRead(ticket);
if(whatsappId && ticket.whatsappId !== whatsappId) {
await CheckContactOpenTickets(ticket.contactId, whatsappId);
}
const oldStatus = ticket.status;
const oldUserId = ticket.user?.id;
if (oldStatus === "closed") {
await CheckContactOpenTickets(ticket.contact.id);
await CheckContactOpenTickets(ticket.contact.id, ticket.whatsappId);
}
await ticket.update({
@@ -46,6 +51,11 @@ const UpdateTicketService = async ({
});
if(whatsappId) {
await ticket.update({
whatsappId
});
}
await ticket.reload();

View File

@@ -10,6 +10,7 @@ interface Request {
name: string;
queueIds?: number[];
profile?: string;
whatsappId?: number;
}
interface Response {
@@ -24,7 +25,8 @@ const CreateUserService = async ({
password,
name,
queueIds = [],
profile = "admin"
profile = "admin",
whatsappId
}: Request): Promise<Response> => {
const schema = Yup.object().shape({
name: Yup.string().required().min(2),
@@ -56,18 +58,17 @@ const CreateUserService = async ({
email,
password,
name,
profile
profile,
whatsappId: whatsappId ? whatsappId : null
},
{ include: ["queues"] }
{ include: ["queues", "whatsapp"] }
);
await user.$set("queues", queueIds);
await user.reload();
const serializedUser = SerializeUser(user);
return serializedUser;
return SerializeUser(user);
};
export default CreateUserService;

View File

@@ -1,6 +1,7 @@
import { Sequelize, Op } from "sequelize";
import Queue from "../../models/Queue";
import User from "../../models/User";
import Whatsapp from "../../models/Whatsapp";
interface Request {
searchParam?: string;
@@ -39,7 +40,8 @@ const ListUsersService = async ({
offset,
order: [["createdAt", "DESC"]],
include: [
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] }
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] },
{ model: Whatsapp, as: "whatsapp", attributes: ["id", "name"] },
]
});

View File

@@ -1,12 +1,14 @@
import User from "../../models/User";
import AppError from "../../errors/AppError";
import Queue from "../../models/Queue";
import Whatsapp from "../../models/Whatsapp";
const ShowUserService = async (id: string | number): Promise<User> => {
const user = await User.findByPk(id, {
attributes: ["name", "id", "email", "profile", "tokenVersion"],
attributes: ["name", "id", "email", "profile", "tokenVersion", "whatsappId"],
include: [
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] }
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] },
{ model: Whatsapp, as: "whatsapp", attributes: ["id", "name"] },
],
order: [ [ { model: Queue, as: "queues"}, 'name', 'asc' ] ]
});

View File

@@ -1,6 +1,7 @@
import * as Yup from "yup";
import AppError from "../../errors/AppError";
import { SerializeUser } from "../../helpers/SerializeUser";
import ShowUserService from "./ShowUserService";
interface UserData {
@@ -9,6 +10,7 @@ interface UserData {
name?: string;
profile?: string;
queueIds?: number[];
whatsappId?: number;
}
interface Request {
@@ -36,7 +38,7 @@ const UpdateUserService = async ({
password: Yup.string()
});
const { email, password, profile, name, queueIds = [] } = userData;
const { email, password, profile, name, queueIds = [], whatsappId } = userData;
try {
await schema.validate({ email, password, profile, name });
@@ -48,22 +50,15 @@ const UpdateUserService = async ({
email,
password,
profile,
name
name,
whatsappId: whatsappId ? whatsappId : null
});
await user.$set("queues", queueIds);
await user.reload();
const serializedUser = {
id: user.id,
name: user.name,
email: user.email,
profile: user.profile,
queues: user.queues
};
return serializedUser;
return SerializeUser(user);
};
export default UpdateUserService;

View File

@@ -3,8 +3,8 @@ import { getWbot } from "../../libs/wbot";
import Contact from "../../models/Contact";
import { logger } from "../../utils/logger";
const ImportContactsService = async (): Promise<void> => {
const defaultWhatsapp = await GetDefaultWhatsApp();
const ImportContactsService = async (userId:number): Promise<void> => {
const defaultWhatsapp = await GetDefaultWhatsApp(userId);
const wbot = getWbot(defaultWhatsapp.id);

View File

@@ -99,6 +99,21 @@ const useStyles = makeStyles(theme => ({
top: "0%",
left: "0%",
},
userTag: {
position: "absolute",
marginRight: 5,
right: 5,
bottom: 5,
background:"#2576D2",
color: "#ffffff",
border:"1px solid #CCC",
padding: 1,
paddingLeft: 5,
paddingRight: 5,
borderRadius: 10,
fontSize: "1em"
},
}));
const TicketListItem = ({ ticket }) => {
@@ -196,6 +211,9 @@ const TicketListItem = ({ ticket }) => {
)}
</Typography>
)}
{ticket.whatsappId && (
<div className={classes.userTag} title={i18n.t("ticketsList.connectionTitle")}>{ticket.whatsapp.name}</div>
)}
</span>
}
secondary={

View File

@@ -94,6 +94,7 @@ const TicketOptionsMenu = ({ ticket, menuOpen, handleClose, anchorEl }) => {
modalOpen={transferTicketModalOpen}
onClose={handleCloseTransferTicketModal}
ticketid={ticket.id}
ticketWhatsappId={ticket.whatsappId}
/>
</>
);

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useContext } from "react";
import { useHistory } from "react-router-dom";
import Button from "@material-ui/core/Button";
@@ -23,6 +23,9 @@ import api from "../../services/api";
import ButtonWithSpinner from "../ButtonWithSpinner";
import toastError from "../../errors/toastError";
import useQueues from "../../hooks/useQueues";
import useWhatsApps from "../../hooks/useWhatsApps";
import { AuthContext } from "../../context/Auth/AuthContext";
import { Can } from "../Can";
const useStyles = makeStyles((theme) => ({
maxWidth: {
@@ -34,7 +37,7 @@ const filterOptions = createFilterOptions({
trim: true,
});
const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
const TransferTicketModal = ({ modalOpen, onClose, ticketid, ticketWhatsappId }) => {
const history = useHistory();
const [options, setOptions] = useState([]);
const [queues, setQueues] = useState([]);
@@ -43,8 +46,12 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
const [searchParam, setSearchParam] = useState("");
const [selectedUser, setSelectedUser] = useState(null);
const [selectedQueue, setSelectedQueue] = useState('');
const [selectedWhatsapp, setSelectedWhatsapp] = useState(ticketWhatsappId);
const classes = useStyles();
const { findAll: findAllQueues } = useQueues();
const { loadingWhatsapps, whatsApps } = useWhatsApps();
const { user: loggedInUser } = useContext(AuthContext);
useEffect(() => {
const loadQueues = async () => {
@@ -107,6 +114,10 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
}
}
if(selectedWhatsapp) {
data.whatsappId = selectedWhatsapp;
}
await api.put(`/tickets/${ticketid}`, data);
setLoading(false);
@@ -177,6 +188,24 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
))}
</Select>
</FormControl>
<Can
role={loggedInUser.profile}
perform="ticket-options:transferWhatsapp"
yes={() => (!loadingWhatsapps &&
<FormControl variant="outlined" className={classes.maxWidth} style={{ marginTop: 20 }}>
<InputLabel>{i18n.t("transferTicketModal.fieldConnectionLabel")}</InputLabel>
<Select
value={selectedWhatsapp}
onChange={(e) => setSelectedWhatsapp(e.target.value)}
label={i18n.t("transferTicketModal.fieldConnectionPlaceholder")}
>
{whatsApps.map((whasapp) => (
<MenuItem key={whasapp.id} value={whasapp.id}>{whasapp.name}</MenuItem>
))}
</Select>
</FormControl>
)}
/>
</DialogContent>
<DialogActions>
<Button

View File

@@ -32,6 +32,7 @@ import toastError from "../../errors/toastError";
import QueueSelect from "../QueueSelect";
import { AuthContext } from "../../context/Auth/AuthContext";
import { Can } from "../Can";
import useWhatsApps from "../../hooks/useWhatsApps";
const useStyles = makeStyles(theme => ({
root: {
@@ -79,7 +80,7 @@ const UserModal = ({ open, onClose, userId }) => {
name: "",
email: "",
password: "",
profile: "user",
profile: "user"
};
const { user: loggedInUser } = useContext(AuthContext);
@@ -87,7 +88,8 @@ const UserModal = ({ open, onClose, userId }) => {
const [user, setUser] = useState(initialState);
const [selectedQueueIds, setSelectedQueueIds] = useState([]);
const [showPassword, setShowPassword] = useState(false);
const [whatsappId, setWhatsappId] = useState(false);
const {loading, whatsApps} = useWhatsApps();
useEffect(() => {
const fetchUser = async () => {
@@ -99,6 +101,7 @@ const UserModal = ({ open, onClose, userId }) => {
});
const userQueueIds = data.queues?.map(queue => queue.id);
setSelectedQueueIds(userQueueIds);
setWhatsappId(data.whatsappId ? data.whatsappId : '');
} catch (err) {
toastError(err);
}
@@ -113,7 +116,7 @@ const UserModal = ({ open, onClose, userId }) => {
};
const handleSaveUser = async values => {
const userData = { ...values, queueIds: selectedQueueIds };
const userData = { ...values, whatsappId, queueIds: selectedQueueIds };
try {
if (userId) {
await api.put(`/users/${userId}`, userData);
@@ -242,6 +245,26 @@ const UserModal = ({ open, onClose, userId }) => {
/>
)}
/>
<Can
role={loggedInUser.profile}
perform="user-modal:editQueues"
yes={() => (!loading &&
<FormControl variant="outlined" margin="dense" className={classes.maxWidth} fullWidth>
<InputLabel>{i18n.t("userModal.form.whatsapp")}</InputLabel>
<Field
as={Select}
value={whatsappId}
onChange={(e) => setWhatsappId(e.target.value)}
label={i18n.t("userModal.form.whatsapp")}
>
<MenuItem value={''}>&nbsp;</MenuItem>
{whatsApps.map((whatsapp) => (
<MenuItem key={whatsapp.id} value={whatsapp.id}>{whatsapp.name}</MenuItem>
))}
</Field>
</FormControl>
)}
/>
</DialogContent>
<DialogActions>
<Button

View File

@@ -243,6 +243,9 @@ const Users = () => {
<TableCell align="center">
{i18n.t("users.table.profile")}
</TableCell>
<TableCell align="center">
{i18n.t("users.table.whatsapp")}
</TableCell>
<TableCell align="center">
{i18n.t("users.table.actions")}
</TableCell>
@@ -255,6 +258,7 @@ const Users = () => {
<TableCell align="center">{user.name}</TableCell>
<TableCell align="center">{user.email}</TableCell>
<TableCell align="center">{user.profile}</TableCell>
<TableCell align="center">{user.whatsapp?.name}</TableCell>
<TableCell align="center">
<IconButton
size="small"

View File

@@ -10,6 +10,7 @@ const rules = {
"user-modal:editProfile",
"user-modal:editQueues",
"ticket-options:deleteTicket",
"ticket-options:transferWhatsapp",
"contacts-page:deleteContact",
],
},

View File

@@ -206,6 +206,7 @@ const messages = {
email: "Email",
password: "Password",
profile: "Profile",
whatsapp: "Default Connection",
},
buttons: {
okAdd: "Add",
@@ -248,7 +249,9 @@ const messages = {
title: "Transfer Ticket",
fieldLabel: "Type to search for users",
fieldQueueLabel: "Transfer to queue",
fieldConnectionLabel: "Transfer to connection",
fieldQueuePlaceholder: "Please select a queue",
fieldConnectionPlaceholder: "Please select a connection",
noOptions: "No user found with this name",
buttons: {
ok: "Transfer",
@@ -260,6 +263,7 @@ const messages = {
assignedHeader: "Working on",
noTicketsTitle: "Nothing here!",
noTicketsMessage: "No tickets found with this status or search term.",
connectionTitle: "Connection that is currently being used.",
buttons: {
accept: "Accept",
},
@@ -340,6 +344,7 @@ const messages = {
name: "Name",
email: "Email",
profile: "Profile",
whatsapp: "Default Connection",
actions: "Actions",
},
buttons: {

View File

@@ -209,6 +209,7 @@ const messages = {
email: "Correo Electrónico",
password: "Contraseña",
profile: "Perfil",
whatsapp: "Conexión estándar",
},
buttons: {
okAdd: "Agregar",
@@ -251,7 +252,9 @@ const messages = {
title: "Transferir Ticket",
fieldLabel: "Escriba para buscar usuarios",
fieldQueueLabel: "Transferir a la cola",
fieldConnectionLabel: "Transferir to conexión",
fieldQueuePlaceholder: "Seleccione una cola",
fieldConnectionPlaceholder: "Seleccione una conexión",
noOptions: "No se encontraron usuarios con ese nombre",
buttons: {
ok: "Transferir",
@@ -262,6 +265,7 @@ const messages = {
pendingHeader: "Cola",
assignedHeader: "Trabajando en",
noTicketsTitle: "¡Nada acá!",
connectionTitle: "Conexión que se está utilizando actualmente.",
noTicketsMessage:
"No se encontraron tickets con este estado o término de búsqueda",
buttons: {
@@ -345,6 +349,7 @@ const messages = {
name: "Nombre",
email: "Correo Electrónico",
profile: "Perfil",
whatsapp: "Conexión estándar",
actions: "Acciones",
},
buttons: {

View File

@@ -208,6 +208,7 @@ const messages = {
email: "Email",
password: "Senha",
profile: "Perfil",
whatsapp: "Conexão Padrão",
},
buttons: {
okAdd: "Adicionar",
@@ -250,7 +251,9 @@ const messages = {
title: "Transferir Ticket",
fieldLabel: "Digite para buscar usuários",
fieldQueueLabel: "Transferir para fila",
fieldConnectionLabel: "Transferir para conexão",
fieldQueuePlaceholder: "Selecione uma fila",
fieldConnectionPlaceholder: "Selecione uma conexão",
noOptions: "Nenhum usuário encontrado com esse nome",
buttons: {
ok: "Transferir",
@@ -263,6 +266,7 @@ const messages = {
noTicketsTitle: "Nada aqui!",
noTicketsMessage:
"Nenhum ticket encontrado com esse status ou termo pesquisado",
connectionTitle: "Conexão que está sendo utilizada atualmente.",
buttons: {
accept: "Aceitar",
},
@@ -344,6 +348,7 @@ const messages = {
name: "Nome",
email: "Email",
profile: "Perfil",
whatsapp: "Conexão Padrão",
actions: "Ações",
},
buttons: {