diff --git a/backend/src/database/seeds/20241008203900-create-quickAnswer-settings.ts b/backend/src/database/seeds/20241008203900-create-quickAnswer-settings.ts new file mode 100644 index 00000000..113412b7 --- /dev/null +++ b/backend/src/database/seeds/20241008203900-create-quickAnswer-settings.ts @@ -0,0 +1,22 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.bulkInsert( + "Settings", + [ + { + key: "quickAnswer", + value: "disabled", + createdAt: new Date(), + updatedAt: new Date() + } + ], + {} + ); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("Settings", {}); + } +}; diff --git a/frontend/src/pages/QuickAnswers/index.js b/frontend/src/pages/QuickAnswers/index.js index 82261230..f4b6e5e4 100644 --- a/frontend/src/pages/QuickAnswers/index.js +++ b/frontend/src/pages/QuickAnswers/index.js @@ -1,10 +1,7 @@ -import React, { useState, useEffect, useReducer } from "react"; -import openSocket from "../../services/socket-io"; -import { useHistory } from "react-router-dom"; - import { Button, IconButton, + InputAdornment, makeStyles, Paper, Table, @@ -12,7 +9,6 @@ import { TableCell, TableHead, TableRow, - InputAdornment, TextField, Tooltip } from "@material-ui/core"; @@ -24,16 +20,20 @@ import { Search } from "@material-ui/icons"; -import api from "../../services/api"; -import { i18n } from "../../translate/i18n"; +import React, { useContext, useEffect, useReducer, useState } from "react"; +import { useHistory } from "react-router-dom"; +import openSocket from "../../services/socket-io"; +import ConfirmationModal from "../../components/ConfirmationModal"; import MainContainer from "../../components/MainContainer"; import MainHeader from "../../components/MainHeader"; import MainHeaderButtonsWrapper from "../../components/MainHeaderButtonsWrapper"; -import Title from "../../components/Title"; -import TableRowSkeleton from "../../components/TableRowSkeleton"; import QuickAnswersModal from "../../components/QuickAnswersModal"; -import ConfirmationModal from "../../components/ConfirmationModal"; +import TableRowSkeleton from "../../components/TableRowSkeleton"; +import Title from "../../components/Title"; +import { AuthContext } from "../../context/Auth/AuthContext"; +import api from "../../services/api"; +import { i18n } from "../../translate/i18n"; import { toast } from "react-toastify"; import toastError from "../../errors/toastError"; @@ -95,7 +95,6 @@ const useStyles = makeStyles((theme) => ({ const QuickAnswers = () => { const classes = useStyles(); const history = useHistory(); - const [loading, setLoading] = useState(false); const [pageNumber, setPageNumber] = useState(1); const [searchParam, setSearchParam] = useState(""); @@ -106,6 +105,9 @@ const QuickAnswers = () => { const [deletingAllQuickAnswers, setDeletingAllQuickAnswers] = useState(null); const [confirmModalOpen, setConfirmModalOpen] = useState(false); const [hasMore, setHasMore] = useState(false); + const [settings, setSettings] = useState([]); + const { user } = useContext(AuthContext); + const isAdmin = user.profile; useEffect(() => { dispatch({ type: "RESET" }); @@ -153,6 +155,23 @@ const QuickAnswers = () => { }; }, []); + useEffect(() => { + const fetchSettings = async () => { + try { + const { data } = await api.get("/settings"); + setSettings(data); + } catch (err) { + toastError(err); + } + }; + fetchSettings(); + }, []); + + const getSettingValue = key => { + const { value } = settings.find(s => s.key === key); + return value; + }; + const handleSearch = (event) => { setSearchParam(event.target.value.toLowerCase()); }; @@ -214,13 +233,13 @@ const QuickAnswers = () => { + onConfirm={() => deletingQuickAnswers ? handleDeleteQuickAnswers(deletingQuickAnswers.id) - : handleDeleteAllQuickAnswers(deletingAllQuickAnswers) + : handleDeleteAllQuickAnswers(deletingAllQuickAnswers) } > { @@ -250,27 +269,31 @@ const QuickAnswers = () => { ), }} /> - - - - - - + {((settings && settings.length > 0 && getSettingValue("quickAnswer") === "enabled") || (isAdmin === "admin")) && ( + + + + )} + {((settings && settings.length > 0 && getSettingValue("quickAnswer") === "enabled") || (isAdmin === "admin")) && ( + + + + )} { {i18n.t("quickAnswers.table.message")} - - {i18n.t("quickAnswers.table.actions")} - + {((settings && settings.length > 0 && getSettingValue("quickAnswer") === "enabled") || (isAdmin === "admin")) && ( + + {i18n.t("quickAnswers.table.actions")} + + )} @@ -298,24 +323,26 @@ const QuickAnswers = () => { {quickAnswer.shortcut} {quickAnswer.message} - - handleEditQuickAnswers(quickAnswer)} - > - - - - { - setConfirmModalOpen(true); - setDeletingQuickAnswers(quickAnswer); - }} - > - - - + {((settings && settings.length > 0 && getSettingValue("quickAnswer") === "enabled") || (isAdmin === "admin")) && ( + + handleEditQuickAnswers(quickAnswer)} + > + + + + { + setConfirmModalOpen(true); + setDeletingQuickAnswers(quickAnswer); + }} + > + + + + )} ))} {loading && } diff --git a/frontend/src/pages/Settings/index.js b/frontend/src/pages/Settings/index.js index f76bc23f..523435c1 100644 --- a/frontend/src/pages/Settings/index.js +++ b/frontend/src/pages/Settings/index.js @@ -1,21 +1,21 @@ -import React, { useState, useEffect } from "react"; -import openSocket from "socket.io-client"; +import React, { useEffect, useState } from "react"; import { useHistory } from "react-router-dom"; +import openSocket from "socket.io-client"; -import { makeStyles, withStyles } from "@material-ui/core/styles"; -import Paper from "@material-ui/core/Paper"; -import Typography from "@material-ui/core/Typography"; import Container from "@material-ui/core/Container"; +import Paper from "@material-ui/core/Paper"; import Select from "@material-ui/core/Select"; +import { makeStyles, withStyles } from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; import { toast } from "react-toastify"; import Tooltip from "@material-ui/core/Tooltip"; -import api from "../../services/api"; -import { i18n } from "../../translate/i18n.js"; -import toastError from "../../errors/toastError"; import FormControlLabel from '@material-ui/core/FormControlLabel'; import Switch from '@material-ui/core/Switch'; +import toastError from "../../errors/toastError"; +import api from "../../services/api"; +import { i18n } from "../../translate/i18n.js"; const useStyles = makeStyles(theme => ({ root: { @@ -243,10 +243,23 @@ const Settings = () => { - + + + + 0 && getSettingValue("quickAnswer") === "enabled"} + onChange={handleChangeBooleanSetting} name="quickAnswer" + />} + label={i18n.t("settings.settings.quickAnswer.name")} + /> + + + diff --git a/frontend/src/translate/languages/en.js b/frontend/src/translate/languages/en.js index 9ba0d854..5d363dad 100644 --- a/frontend/src/translate/languages/en.js +++ b/frontend/src/translate/languages/en.js @@ -489,7 +489,7 @@ const messages = { deleteMessage: "All agent data will be lost. Open tickets for this agent will be moved to hold.", }, }, - company:{ + company: { success: "Company data successfully saved.", title: "Company Data", info: "Information", @@ -555,6 +555,14 @@ const messages = { disabled: "Closed", }, }, + quickAnswer: { + name: "Quick Answers", + note: "If enabled, you can edit quick answers", + options: { + enabled: "Enabled", + disabled: "Disabled", + }, + }, closeTicketApi: { name: "Close Ticket sent API", note: "Automatically closes ticket when submitted via API", @@ -700,3 +708,4 @@ const messages = { }; export { messages }; + diff --git a/frontend/src/translate/languages/es.js b/frontend/src/translate/languages/es.js index da8dd1d1..7a516e34 100644 --- a/frontend/src/translate/languages/es.js +++ b/frontend/src/translate/languages/es.js @@ -489,7 +489,7 @@ const messages = { deleteMessage: "Se perderán todos los datos del asistente. Los tickets abiertos para este asistente se moverán a espera.", }, }, - company:{ + company: { success: "Los datos de la empresa se guardaron con éxito.", title: "Datos de la empresa", info: "Información", @@ -555,6 +555,14 @@ const messages = { disabled: "Cerrado", }, }, + quickAnswer: { + name: "Respuestas rápidas", + note: "Si está habilitado, puedes editar respuestas rápidas", + options: { + enabled: "Habilitado", + disabled: "Deshabilitado", + }, + }, closeTicketApi: { name: "Cerrar ticket enviado API", note: "Cierra automáticamente el ticket cuando se envía a través de API", @@ -698,4 +706,4 @@ const messages = { }, }; -export { messages }; \ No newline at end of file +export { messages }; diff --git a/frontend/src/translate/languages/pt.js b/frontend/src/translate/languages/pt.js index 3cb130ce..36649630 100644 --- a/frontend/src/translate/languages/pt.js +++ b/frontend/src/translate/languages/pt.js @@ -554,6 +554,14 @@ const messages = { disabled: "Fechado", }, }, + quickAnswer: { + name: "Respostas Rápidas", + note: "Se habilitado, poderá editar as respostas rápidas", + options: { + enabled: "Ativado", + disabled: "Desativado", + }, + }, closeTicketApi: { name: "Encerrar Ticket enviado API", note: "Fecha automaticamente o ticket quando enviado por API",