diff --git a/backend/.eslintrc.json b/backend/.eslintrc.json index aa015faa0..efa6e5028 100644 --- a/backend/.eslintrc.json +++ b/backend/.eslintrc.json @@ -45,5 +45,11 @@ "import/resolver": { "typescript": {} } - } + }, + "prettier/prettier": [ + "error", + { + "endOfLine": "auto" + } + ] } diff --git a/backend/.wwebjs_cache/2.3000.1019186557.html b/backend/.wwebjs_cache/2.3000.1019186557.html new file mode 100644 index 000000000..308981779 --- /dev/null +++ b/backend/.wwebjs_cache/2.3000.1019186557.html @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + +WhatsApp Web + +
WhatsApp
 Protegida com a criptografia de ponta a ponta
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/.wwebjs_cache/2.3000.1019187602.html b/backend/.wwebjs_cache/2.3000.1019187602.html new file mode 100644 index 000000000..2c2e3a54e --- /dev/null +++ b/backend/.wwebjs_cache/2.3000.1019187602.html @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + +WhatsApp Web + +
WhatsApp
 Protegida com a criptografia de ponta a ponta
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/package.json b/backend/package.json index 345610de2..fec37a63a 100644 --- a/backend/package.json +++ b/backend/package.json @@ -16,7 +16,6 @@ "license": "MIT", "dependencies": { "@sentry/node": "^5.29.2", - "@types/lodash": "^4.17.5", "@types/pino": "^6.3.4", "bcryptjs": "^2.4.3", "cookie-parser": "^1.4.5", @@ -27,6 +26,7 @@ "express-async-errors": "^3.1.1", "http-graceful-shutdown": "^2.3.2", "jsonwebtoken": "^8.5.1", + "mariadb": "^3.4.0", "multer": "^1.4.2", "mustache": "^4.2.0", "mysql2": "^2.2.5", @@ -53,6 +53,7 @@ "@types/faker": "^5.1.3", "@types/jest": "^26.0.15", "@types/jsonwebtoken": "^8.5.0", + "@types/lodash": "4.14", "@types/multer": "^1.4.4", "@types/mustache": "^4.1.2", "@types/node": "^14.11.8", @@ -61,7 +62,6 @@ "@types/uuid": "^8.3.3", "@types/validator": "^13.1.0", "@types/yup": "^0.29.8", - "@types/lodash": "4.14", "@typescript-eslint/eslint-plugin": "^4.4.0", "@typescript-eslint/parser": "^4.4.0", "eslint": "^7.10.0", diff --git a/backend/src/controllers/MessageController.ts b/backend/src/controllers/MessageController.ts index 21f90aa1f..6425d80ed 100644 --- a/backend/src/controllers/MessageController.ts +++ b/backend/src/controllers/MessageController.ts @@ -9,6 +9,9 @@ import ShowTicketService from "../services/TicketServices/ShowTicketService"; import DeleteWhatsAppMessage from "../services/WbotServices/DeleteWhatsAppMessage"; import SendWhatsAppMedia from "../services/WbotServices/SendWhatsAppMedia"; import SendWhatsAppMessage from "../services/WbotServices/SendWhatsAppMessage"; +import { Op, Sequelize } from "sequelize"; + +import { performance } from "perf_hooks"; type IndexQuery = { pageNumber: string; @@ -73,3 +76,26 @@ export const remove = async ( return res.send(); }; + +export const search = async ( + req: Request, + res: Response +): Promise => { + const start = performance.now(); + + const { ticketId, search } = req.params; + + const messages = await Message.findAll({ + where: { + ticketId, + body: Sequelize.where(Sequelize.fn("LOWER", Sequelize.col("body")), { + [Op.like]: `%${search.toLowerCase()}%` + }) + } + }); + + const end = performance.now(); + console.log(`Execution time: ${(end - start).toFixed(2)}ms`); + + return res.json(messages); +}; diff --git a/backend/src/routes/messageRoutes.ts b/backend/src/routes/messageRoutes.ts index a97303bd7..9d3ab7727 100644 --- a/backend/src/routes/messageRoutes.ts +++ b/backend/src/routes/messageRoutes.ts @@ -18,6 +18,12 @@ messageRoutes.post( MessageController.store ); +messageRoutes.get( + "/messages/:ticketId/:search", + isAuth, + MessageController.search +); + messageRoutes.delete("/messages/:messageId", isAuth, MessageController.remove); export default messageRoutes; diff --git a/backend/test-config.yml b/backend/test-config.yml new file mode 100644 index 000000000..0389252ad --- /dev/null +++ b/backend/test-config.yml @@ -0,0 +1,13 @@ +config: + target: "http://localhost:8080" # Definindo o URL de destino + phases: + - duration: 60 # Duração do teste + arrivalRate: 10 # Taxa de chegada de requisições por segundo + +scenarios: + - flow: + - get: + url: "/messages/2/teste" # Endpoint para a requisição + headers: + Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2FybmFtZSI6IkJpZyBKb3NlcGgiLCJwcm9maWxlIjoiYWRtaW4iLCJpZCI6MywiaWF0IjoxNzM2MzQ4Njg1LCJleHAiOjE3MzYzNDk1ODV9.KrpTrzKXsQmGXekSdx1JJqnNRAVoZvgLh3ipUAHgClc +" diff --git a/frontend/package.json b/frontend/package.json index acc009a84..7f9499e6d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -31,7 +31,7 @@ "yup": "^0.32.8" }, "scripts": { - "start": "react-scripts start", + "start": "set NODE_OPTIONS=--openssl-legacy-provider && react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" diff --git a/frontend/src/components/TicketHeader/index.js b/frontend/src/components/TicketHeader/index.js index 453d52b61..eda5c942f 100644 --- a/frontend/src/components/TicketHeader/index.js +++ b/frontend/src/components/TicketHeader/index.js @@ -1,29 +1,44 @@ -import React from "react"; - -import { Card, Button } from "@material-ui/core"; +import React, { useEffect, useState } from "react"; +import { Card, Button, TextField, IconButton } from "@material-ui/core"; import { makeStyles } from "@material-ui/core/styles"; import TicketHeaderSkeleton from "../TicketHeaderSkeleton"; import ArrowBackIos from "@material-ui/icons/ArrowBackIos"; +import SearchIcon from "@material-ui/icons/Search"; import { useHistory } from "react-router-dom"; +import api from "../../services/api"; const useStyles = makeStyles((theme) => ({ ticketHeader: { display: "flex", + alignItems: "center", backgroundColor: "#eee", flex: "none", borderBottom: "1px solid rgba(0, 0, 0, 0.12)", + padding: theme.spacing(1), [theme.breakpoints.down("sm")]: { flexWrap: "wrap", }, }, + searchField: { + marginLeft: theme.spacing(2), + flexGrow: 1, + }, })); -const TicketHeader = ({ loading, children }) => { +const TicketHeader = ({ loading, children, onSearch }) => { const classes = useStyles(); const history = useHistory(); const handleBack = () => { history.push("/tickets"); }; + const [searchTerm, setsearchTerm] = useState(""); + const ticketId = history.location.pathname.split("/")[2]; + + const searchMessage = () => { + api.get(`/messages/${ticketId}/${searchTerm}`).then((response) => { + console.log(response.data); + }); + }; return ( <> @@ -34,6 +49,17 @@ const TicketHeader = ({ loading, children }) => { + setsearchTerm(e.target.value)} + /> + + + {children} )}