diff --git a/backend/src/controllers/SettingController.ts b/backend/src/controllers/SettingController.ts index 10b7f8e..7144a89 100644 --- a/backend/src/controllers/SettingController.ts +++ b/backend/src/controllers/SettingController.ts @@ -7,9 +7,9 @@ import UpdateSettingService from "../services/SettingServices/UpdateSettingServi import ListSettingsService from "../services/SettingServices/ListSettingsService"; export const index = async (req: Request, res: Response): Promise => { - if (req.user.profile !== "master") { - throw new AppError("ERR_NO_PERMISSION", 403); - } + // if (req.user.profile !== "master") { + // throw new AppError("ERR_NO_PERMISSION", 403); + // } const settings = await ListSettingsService(); diff --git a/backend/src/database/seeds/20230719121844-add-edit-ura-settings.ts b/backend/src/database/seeds/20230719121844-add-edit-ura-settings.ts new file mode 100644 index 0000000..98c27f5 --- /dev/null +++ b/backend/src/database/seeds/20230719121844-add-edit-ura-settings.ts @@ -0,0 +1,22 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.bulkInsert( + "Settings", + [ + { + key: "editURA", + value: "enabled", + createdAt: new Date(), + updatedAt: new Date() + } + ], + {} + ); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("Settings", {}); + } +}; diff --git a/backend/src/database/seeds/20230719184620-add-edit-queue-settings.ts b/backend/src/database/seeds/20230719184620-add-edit-queue-settings.ts new file mode 100644 index 0000000..71d598a --- /dev/null +++ b/backend/src/database/seeds/20230719184620-add-edit-queue-settings.ts @@ -0,0 +1,22 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.bulkInsert( + "Settings", + [ + { + key: "editQueue", + value: "enabled", + createdAt: new Date(), + updatedAt: new Date() + } + ], + {} + ); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("Settings", {}); + } +}; diff --git a/backend/src/routes/settingRoutes.ts b/backend/src/routes/settingRoutes.ts index 5a1ffa0..7047a63 100644 --- a/backend/src/routes/settingRoutes.ts +++ b/backend/src/routes/settingRoutes.ts @@ -5,9 +5,7 @@ import * as SettingController from "../controllers/SettingController"; const settingRoutes = Router(); - - -settingRoutes.get("/settings", isAuth, SettingController.index); +settingRoutes.get("/settings", SettingController.index); // routes.get("/settings/:settingKey", isAuth, SettingsController.show); diff --git a/backend/src/services/StatusChatEndService/ShowStatusChatEndService.ts b/backend/src/services/StatusChatEndService/ShowStatusChatEndService.ts index 12c6aaf..085e591 100644 --- a/backend/src/services/StatusChatEndService/ShowStatusChatEndService.ts +++ b/backend/src/services/StatusChatEndService/ShowStatusChatEndService.ts @@ -1,8 +1,14 @@ import StatusChatEnd from "../../models/StatusChatEnd"; import AppError from "../../errors/AppError"; -const ShowStatusChatEndService = async (id: string | number): Promise => { - const status = await StatusChatEnd.findByPk(id, { attributes: ['id', 'name'], }); +const ShowStatusChatEndService = async ( + id: string | number +): Promise => { + const status = await StatusChatEnd.findByPk(id, { + attributes: ["id", "name"] + }); + + console.log(`---------------> statusChatEnd id: ${id}`); if (!status) { throw new AppError("ERR_NO_STATUS_FOUND", 404); @@ -11,4 +17,4 @@ const ShowStatusChatEndService = async (id: string | number): Promise { - const [locale, setLocale] = useState(); + const [locale, setLocale] = useState() const theme = createTheme( { scrollbarStyles: { - "&::-webkit-scrollbar": { - width: "8px", - height: "8px", + '&::-webkit-scrollbar': { + width: '8px', + height: '8px', }, - "&::-webkit-scrollbar-thumb": { - boxShadow: "inset 0 0 6px rgba(0, 0, 0, 0.3)", + '&::-webkit-scrollbar-thumb': { + boxShadow: 'inset 0 0 6px rgba(0, 0, 0, 0.3)', - backgroundColor: "#e8e8e8", + backgroundColor: '#e8e8e8', }, }, palette: { //primary: { main: "#2576d2" }, - primary: { main: "#ec5114" }, + primary: { main: '#ec5114' }, }, }, locale - ); + ) useEffect(() => { - const i18nlocale = localStorage.getItem("i18nextLng"); + const i18nlocale = localStorage.getItem('i18nextLng') const browserLocale = - i18nlocale.substring(0, 2) + i18nlocale.substring(3, 5); + i18nlocale.substring(0, 2) + i18nlocale.substring(3, 5) - if (browserLocale === "ptBR") { - setLocale(ptBR); + if (browserLocale === 'ptBR') { + setLocale(ptBR) } - }, []); + }, []) return ( - {/*TabTicketProvider Context to manipulate the entire state of selected option from user click on tickets options header */} - - - ); -}; + ) +} -export default App; +export default App diff --git a/frontend/src/components/WhatsAppModal/index.js b/frontend/src/components/WhatsAppModal/index.js index 57d0cd0..b2b8e40 100644 --- a/frontend/src/components/WhatsAppModal/index.js +++ b/frontend/src/components/WhatsAppModal/index.js @@ -1,290 +1,300 @@ -import React, { useState, useEffect } from "react"; -import * as Yup from "yup"; -import { Formik, Form, Field } from "formik"; -import { toast } from "react-toastify"; +import React, { useState, useEffect, useContext } from 'react' +import * as Yup from 'yup' +import { Formik, Form, Field } from 'formik' +import { toast } from 'react-toastify' -import { makeStyles } from "@material-ui/core/styles"; -import { green } from "@material-ui/core/colors"; +import { makeStyles } from '@material-ui/core/styles' +import { green } from '@material-ui/core/colors' + +import { AuthContext } from '../../context/Auth/AuthContext' +import { Can } from '../../components/Can' import { - Dialog, - DialogContent, - DialogTitle, - Button, - DialogActions, - CircularProgress, - TextField, - Switch, - FormControlLabel, -} from "@material-ui/core"; + Dialog, + DialogContent, + DialogTitle, + Button, + DialogActions, + CircularProgress, + TextField, + Switch, + FormControlLabel, +} from '@material-ui/core' -import api from "../../services/api"; -import { i18n } from "../../translate/i18n"; -import toastError from "../../errors/toastError"; -import QueueSelect from "../QueueSelect"; +import api from '../../services/api' +import { i18n } from '../../translate/i18n' +import toastError from '../../errors/toastError' +import QueueSelect from '../QueueSelect' -const useStyles = makeStyles(theme => ({ - root: { - display: "flex", - flexWrap: "wrap", - }, +const useStyles = makeStyles((theme) => ({ + root: { + display: 'flex', + flexWrap: 'wrap', + }, - multFieldLine: { - display: "flex", - "& > *:not(:last-child)": { - marginRight: theme.spacing(1), - }, - }, + multFieldLine: { + display: 'flex', + '& > *:not(:last-child)': { + marginRight: theme.spacing(1), + }, + }, - btnWrapper: { - position: "relative", - }, + btnWrapper: { + position: 'relative', + }, - buttonProgress: { - color: green[500], - position: "absolute", - top: "50%", - left: "50%", - marginTop: -12, - marginLeft: -12, - }, -})); + buttonProgress: { + color: green[500], + position: 'absolute', + top: '50%', + left: '50%', + marginTop: -12, + marginLeft: -12, + }, +})) const SessionSchema = Yup.object().shape({ - name: Yup.string() - .min(2, "Too Short!") - .max(100, "Too Long!") - .required("Required"), -}); + name: Yup.string() + .min(2, 'Too Short!') + .max(100, 'Too Long!') + .required('Required'), +}) const WhatsAppModal = ({ open, onClose, whatsAppId }) => { - const classes = useStyles(); - const initialState = { - name: "", - urlApi: "", - url: "", - greetingMessage: "", - farewellMessage: "", - isDefault: false, - }; - const [whatsApp, setWhatsApp] = useState(initialState); - const [selectedQueueIds, setSelectedQueueIds] = useState([]); + const classes = useStyles() + const initialState = { + name: '', + urlApi: '', + url: '', + greetingMessage: '', + farewellMessage: '', + isDefault: false, + } - useEffect(() => { - const fetchSession = async () => { - if (!whatsAppId) return; + const { user } = useContext(AuthContext) - try { - const { data } = await api.get(`whatsapp/${whatsAppId}`); - setWhatsApp(data); + const [whatsApp, setWhatsApp] = useState(initialState) + const [selectedQueueIds, setSelectedQueueIds] = useState([]) - const whatsQueueIds = data.queues?.map(queue => queue.id); - setSelectedQueueIds(whatsQueueIds); - } catch (err) { - toastError(err); - } - }; - fetchSession(); - }, [whatsAppId]); + useEffect(() => { + const fetchSession = async () => { + if (!whatsAppId) return - const handleSaveWhatsApp = async values => { - const whatsappData = { ...values, queueIds: selectedQueueIds }; + try { + const { data } = await api.get(`whatsapp/${whatsAppId}`) + setWhatsApp(data) - let response = null + const whatsQueueIds = data.queues?.map((queue) => queue.id) + setSelectedQueueIds(whatsQueueIds) + } catch (err) { + toastError(err) + } + } + fetchSession() + }, [whatsAppId]) - try { - if (whatsAppId) { - response = await api.put(`/whatsapp/${whatsAppId}`, whatsappData); - } else { - response = await api.post("/whatsapp", whatsappData); - } + const handleSaveWhatsApp = async (values) => { + const whatsappData = { ...values, queueIds: selectedQueueIds } - console.log('response: ', response.data.message) + let response = null - if(response && response.data.message === 'wrong_number_start'){ - alert('O numero contido no nome da conexão deve iniciar com o código do país!') - } - else if(response && response.data.message === 'invalid_phone_number'){ - alert('A quantidade de numeros digitados no nome do contato é invalida! Certifique-se de que você digitou o numero correto acompanhado pelo código do país!') - } - else if( response && response.data.message === 'no_phone_number'){ - alert('Para criar/editar uma sessão de Whatsapp é necessário que o numero do Whatsapp acompanhado pelo código do país esteja presente no nome da sessão!') - } - else{ - toast.success(i18n.t("whatsappModal.success")); - handleClose(); - } - - } catch (err) { - toastError(err); - } - }; + try { + if (whatsAppId) { + response = await api.put(`/whatsapp/${whatsAppId}`, whatsappData) + } else { + response = await api.post('/whatsapp', whatsappData) + } - const handleClose = () => { - onClose(); - setWhatsApp(initialState); - }; + console.log('response: ', response.data.message) - return ( -
- - - {whatsAppId - ? i18n.t("whatsappModal.title.edit") - : i18n.t("whatsappModal.title.add")} - - { - setTimeout(() => { - handleSaveWhatsApp(values); - actions.setSubmitting(false); - }, 400); - }} - > - {({ values, touched, errors, isSubmitting }) => ( -
- - -
- - - } - label={i18n.t("whatsappModal.form.default")} - /> -
+ if (response && response.data.message === 'wrong_number_start') { + alert( + 'O numero contido no nome da conexão deve iniciar com o código do país!' + ) + } else if (response && response.data.message === 'invalid_phone_number') { + alert( + 'A quantidade de numeros digitados no nome do contato é invalida! Certifique-se de que você digitou o numero correto acompanhado pelo código do país!' + ) + } else if (response && response.data.message === 'no_phone_number') { + alert( + 'Para criar/editar uma sessão de Whatsapp é necessário que o numero do Whatsapp acompanhado pelo código do país esteja presente no nome da sessão!' + ) + } else { + toast.success(i18n.t('whatsappModal.success')) + handleClose() + } + } catch (err) { + toastError(err) + } + } + const handleClose = () => { + onClose() + setWhatsApp(initialState) + } + return ( +
+ + + {whatsAppId + ? i18n.t('whatsappModal.title.edit') + : i18n.t('whatsappModal.title.add')} + + { + setTimeout(() => { + handleSaveWhatsApp(values) + actions.setSubmitting(false) + }, 400) + }} + > + {({ values, touched, errors, isSubmitting }) => ( + + + ( + <> +
+ + + } + label={i18n.t('whatsappModal.form.default')} + /> +
+
+ + +
+ + )} + /> -
- - -
+
+ +
+
+ +
+ setSelectedQueueIds(selectedIds)} + /> +
+ + + + + + )} +
+
+
+ ) +} -
- -
- - -
- -
- setSelectedQueueIds(selectedIds)} - /> -
- - - - - - )} -
-
-
- ); -}; - -export default React.memo(WhatsAppModal); +export default React.memo(WhatsAppModal) diff --git a/frontend/src/context/Auth/AuthContext.js b/frontend/src/context/Auth/AuthContext.js index d13b342..5368f33 100644 --- a/frontend/src/context/Auth/AuthContext.js +++ b/frontend/src/context/Auth/AuthContext.js @@ -1,21 +1,22 @@ -import React, { createContext } from "react"; +import React, { createContext } from 'react' -import useAuth from "../../hooks/useAuth.js"; +import useAuth from '../../hooks/useAuth.js' -const AuthContext = createContext(); +const AuthContext = createContext() const AuthProvider = ({ children }) => { - const { loading, user, isAuth, handleLogin, handleLogout } = useAuth(); + const { loading, user, isAuth, handleLogin, handleLogout, setSetting } = + useAuth() - //{ + //{ - return ( - - {children} - - ); -}; + return ( + + {children} + + ) +} -export { AuthContext, AuthProvider }; +export { AuthContext, AuthProvider } diff --git a/frontend/src/hooks/useAuth.js/index.js b/frontend/src/hooks/useAuth.js/index.js index dc5d3d3..70ffe21 100644 --- a/frontend/src/hooks/useAuth.js/index.js +++ b/frontend/src/hooks/useAuth.js/index.js @@ -1,125 +1,158 @@ -import { useState, useEffect } from "react"; -import { useHistory } from "react-router-dom"; -import openSocket from "socket.io-client"; +import { useState, useEffect } from 'react' +import { useHistory } from 'react-router-dom' +import openSocket from 'socket.io-client' -import { toast } from "react-toastify"; +import { toast } from 'react-toastify' -import { i18n } from "../../translate/i18n"; -import api from "../../services/api"; -import toastError from "../../errors/toastError"; +import { i18n } from '../../translate/i18n' +import api from '../../services/api' +import toastError from '../../errors/toastError' const useAuth = () => { - const history = useHistory(); - const [isAuth, setIsAuth] = useState(false); - const [loading, setLoading] = useState(true); - const [user, setUser] = useState({}); + const history = useHistory() + const [isAuth, setIsAuth] = useState(false) + const [loading, setLoading] = useState(true) + const [user, setUser] = useState({}) - api.interceptors.request.use( - config => { - const token = localStorage.getItem("token"); - if (token) { - config.headers["Authorization"] = `Bearer ${JSON.parse(token)}`; - setIsAuth(true); - } - return config; - }, - error => { - Promise.reject(error); - } - ); + const [setting, setSetting] = useState({}) - api.interceptors.response.use( - response => { - return response; - }, - async error => { - const originalRequest = error.config; - if (error?.response?.status === 403 && !originalRequest._retry) { - originalRequest._retry = true; + api.interceptors.request.use( + (config) => { + const token = localStorage.getItem('token') + if (token) { + config.headers['Authorization'] = `Bearer ${JSON.parse(token)}` + setIsAuth(true) + } + return config + }, + (error) => { + Promise.reject(error) + } + ) - const { data } = await api.post("/auth/refresh_token"); - if (data) { - localStorage.setItem("token", JSON.stringify(data.token)); - api.defaults.headers.Authorization = `Bearer ${data.token}`; - } - return api(originalRequest); - } - if (error?.response?.status === 401) { - localStorage.removeItem("token"); - api.defaults.headers.Authorization = undefined; - setIsAuth(false); - } - return Promise.reject(error); - } - ); + api.interceptors.response.use( + (response) => { + return response + }, + async (error) => { + const originalRequest = error.config + if (error?.response?.status === 403 && !originalRequest._retry) { + originalRequest._retry = true - useEffect(() => { - const token = localStorage.getItem("token"); - (async () => { - if (token) { - try { - const { data } = await api.post("/auth/refresh_token"); - api.defaults.headers.Authorization = `Bearer ${data.token}`; - setIsAuth(true); - setUser(data.user); - } catch (err) { - toastError(err); - } - } - setLoading(false); - })(); - }, []); + const { data } = await api.post('/auth/refresh_token') + if (data) { + localStorage.setItem('token', JSON.stringify(data.token)) + api.defaults.headers.Authorization = `Bearer ${data.token}` + } + return api(originalRequest) + } + if (error?.response?.status === 401) { + localStorage.removeItem('token') + api.defaults.headers.Authorization = undefined + setIsAuth(false) + } + return Promise.reject(error) + } + ) - useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL); + useEffect(() => { + const token = localStorage.getItem('token') + ;(async () => { + if (token) { + try { + const { data } = await api.post('/auth/refresh_token') + api.defaults.headers.Authorization = `Bearer ${data.token}` + setIsAuth(true) + setUser(data.user) + } catch (err) { + toastError(err) + } + } + setLoading(false) + })() + }, []) - socket.on("user", data => { - if (data.action === "update" && data.user.id === user.id) { - setUser(data.user); - } - }); + useEffect(() => { + const fetchSession = async () => { + try { + const { data } = await api.get('/settings') + setSetting(data) + } catch (err) { + toastError(err) + } + } + fetchSession() + }, []) - return () => { - socket.disconnect(); - }; - }, [user]); + useEffect(() => { + const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - const handleLogin = async userData => { - setLoading(true); + socket.on('user', (data) => { + if (data.action === 'update' && data.user.id === user.id) { + setUser(data.user) + } + }) - try { - const { data } = await api.post("/auth/login", userData); - localStorage.setItem("token", JSON.stringify(data.token)); - api.defaults.headers.Authorization = `Bearer ${data.token}`; - setUser(data.user); - setIsAuth(true); - toast.success(i18n.t("auth.toasts.success")); - history.push("/tickets"); - setLoading(false); - } catch (err) { - toastError(err); - setLoading(false); - } - }; + socket.on('settings', (data) => { + if (data.action === 'update') { + setSetting((prevState) => { + const aux = [...prevState] + const settingIndex = aux.findIndex((s) => s.key === data.setting.key) + aux[settingIndex].value = data.setting.value + return aux + }) + } + }) - const handleLogout = async () => { - setLoading(true); + return () => { + socket.disconnect() + } + }, [user]) - try { - await api.delete("/auth/logout"); - setIsAuth(false); - setUser({}); - localStorage.removeItem("token"); - api.defaults.headers.Authorization = undefined; - setLoading(false); - history.push("/login"); - } catch (err) { - toastError(err); - setLoading(false); - } - }; + const handleLogin = async (userData) => { + setLoading(true) - return { isAuth, user, loading, handleLogin, handleLogout }; -}; + try { + const { data } = await api.post('/auth/login', userData) + localStorage.setItem('token', JSON.stringify(data.token)) + api.defaults.headers.Authorization = `Bearer ${data.token}` + setUser(data.user) + setIsAuth(true) + toast.success(i18n.t('auth.toasts.success')) + history.push('/tickets') + setLoading(false) + } catch (err) { + toastError(err) + setLoading(false) + } + } -export default useAuth; + const handleLogout = async () => { + setLoading(true) + + try { + await api.delete('/auth/logout') + setIsAuth(false) + setUser({}) + localStorage.removeItem('token') + api.defaults.headers.Authorization = undefined + setLoading(false) + history.push('/login') + } catch (err) { + toastError(err) + setLoading(false) + } + } + + return { + isAuth, + user, + loading, + handleLogin, + handleLogout, + setting, + setSetting, + } +} + +export default useAuth diff --git a/frontend/src/pages/Connections/index.js b/frontend/src/pages/Connections/index.js index aa04cc9..a8c5fe4 100644 --- a/frontend/src/pages/Connections/index.js +++ b/frontend/src/pages/Connections/index.js @@ -1,368 +1,371 @@ -import React, { useState, useCallback, useEffect, useContext } from "react"; -import { toast } from "react-toastify"; -import { format, parseISO } from "date-fns"; +import React, { useState, useCallback, useEffect, useContext } from 'react' +import { toast } from 'react-toastify' +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 { green } from "@material-ui/core/colors"; +import { makeStyles } from '@material-ui/core/styles' +import { green } from '@material-ui/core/colors' import { - Button, - TableBody, - TableRow, - TableCell, - IconButton, - Table, - TableHead, - Paper, - Tooltip, - Typography, - CircularProgress, -} from "@material-ui/core"; + Button, + TableBody, + TableRow, + TableCell, + IconButton, + Table, + TableHead, + Paper, + Tooltip, + Typography, + CircularProgress, +} from '@material-ui/core' import { - Edit, - CheckCircle, - SignalCellularConnectedNoInternet2Bar, - SignalCellularConnectedNoInternet0Bar, - SignalCellular4Bar, - CropFree, - DeleteOutline, - // Restore -} from "@material-ui/icons"; + Edit, + CheckCircle, + SignalCellularConnectedNoInternet2Bar, + SignalCellularConnectedNoInternet0Bar, + SignalCellular4Bar, + CropFree, + DeleteOutline, + // Restore +} from '@material-ui/icons' -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 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 api from "../../services/api"; -import WhatsAppModal from "../../components/WhatsAppModal"; -import ConfirmationModal from "../../components/ConfirmationModal"; -import QrcodeModal from "../../components/QrcodeModal"; -import { i18n } from "../../translate/i18n"; -import { WhatsAppsContext } from "../../context/WhatsApp/WhatsAppsContext"; -import toastError from "../../errors/toastError"; +import api from '../../services/api' +import WhatsAppModal from '../../components/WhatsAppModal' +import ConfirmationModal from '../../components/ConfirmationModal' +import QrcodeModal from '../../components/QrcodeModal' +import { i18n } from '../../translate/i18n' +import { WhatsAppsContext } from '../../context/WhatsApp/WhatsAppsContext' +import toastError from '../../errors/toastError' //-------- -import { AuthContext } from "../../context/Auth/AuthContext"; -import { Can } from "../../components/Can"; +import { AuthContext } from '../../context/Auth/AuthContext' +import { Can } from '../../components/Can' - -const useStyles = makeStyles(theme => ({ - mainPaper: { - flex: 1, - padding: theme.spacing(1), - overflowY: "scroll", - ...theme.scrollbarStyles, - }, - customTableCell: { - display: "flex", - alignItems: "center", - justifyContent: "center", - }, - tooltip: { - backgroundColor: "#f5f5f9", - color: "rgba(0, 0, 0, 0.87)", - fontSize: theme.typography.pxToRem(14), - border: "1px solid #dadde9", - maxWidth: 450, - }, - tooltipPopper: { - textAlign: "center", - }, - buttonProgress: { - color: green[500], - }, -})); +const useStyles = makeStyles((theme) => ({ + mainPaper: { + flex: 1, + padding: theme.spacing(1), + overflowY: 'scroll', + ...theme.scrollbarStyles, + }, + customTableCell: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }, + tooltip: { + backgroundColor: '#f5f5f9', + color: 'rgba(0, 0, 0, 0.87)', + fontSize: theme.typography.pxToRem(14), + border: '1px solid #dadde9', + maxWidth: 450, + }, + tooltipPopper: { + textAlign: 'center', + }, + buttonProgress: { + color: green[500], + }, +})) const CustomToolTip = ({ title, content, children }) => { - const classes = useStyles(); + const classes = useStyles() - return ( - - - {title} - - {content && {content}} - - } - > - {children} - - ); -}; + return ( + + + {title} + + {content && {content}} + + } + > + {children} + + ) +} const Connections = () => { + //-------- + const { user } = useContext(AuthContext) - //-------- - const { user } = useContext(AuthContext); + const classes = useStyles() + const { whatsApps, loading } = useContext(WhatsAppsContext) + const [whatsAppModalOpen, setWhatsAppModalOpen] = useState(false) + const [qrModalOpen, setQrModalOpen] = useState(false) + const [selectedWhatsApp, setSelectedWhatsApp] = useState(null) + const [confirmModalOpen, setConfirmModalOpen] = useState(false) - const classes = useStyles(); + const [diskSpaceInfo, setDiskSpaceInfo] = useState({}) - const { whatsApps, loading } = useContext(WhatsAppsContext); - const [whatsAppModalOpen, setWhatsAppModalOpen] = useState(false); - const [qrModalOpen, setQrModalOpen] = useState(false); - const [selectedWhatsApp, setSelectedWhatsApp] = useState(null); - const [confirmModalOpen, setConfirmModalOpen] = useState(false); + const [disabled, setDisabled] = useState(true) - const [diskSpaceInfo, setDiskSpaceInfo] = useState({}); + const [settings, setSettings] = useState([]) - const [disabled, setDisabled] = useState(true); + const [buttons, setClicks] = useState([]) - const [buttons, setClicks] = useState([]) + const confirmationModalInitialState = { + action: '', + title: '', + message: '', + whatsAppId: '', + open: false, + } + const [confirmModalInfo, setConfirmModalInfo] = useState( + confirmationModalInitialState + ) + useEffect(() => { + const fetchSession = async () => { + try { + const { data } = await api.get('/settings') + setSettings(data) + } catch (err) { + toastError(err) + } + } + fetchSession() + }, []) - const confirmationModalInitialState = { - action: "", - title: "", - message: "", - whatsAppId: "", - open: false, - }; - const [confirmModalInfo, setConfirmModalInfo] = useState( - confirmationModalInitialState - ); + const getSettingValue = (key) => { + const { value } = settings.find((s) => s.key === key) - const handleStartWhatsAppSession = async whatsAppId => { - try { - await api.post(`/whatsappsession/${whatsAppId}`); - } catch (err) { - toastError(err); - } - }; + return value + } + const handleStartWhatsAppSession = async (whatsAppId) => { + try { + await api.post(`/whatsappsession/${whatsAppId}`) + } catch (err) { + toastError(err) + } + } + const handleRestartWhatsAppSession = async (whatsapp) => { + try { + whatsapp.disabled = true + setClicks([...buttons, whatsapp.id]) - const handleRestartWhatsAppSession = async whatsapp => { - try { + function enable_button(whatsappId) { + setClicks((buttons) => + buttons.filter((id) => { + return +id !== +whatsappId + }) + ) + } - whatsapp.disabled = true + setTimeout(enable_button, 25000, whatsapp.id) - setClicks([...buttons, whatsapp.id]) + await api.post(`/restartwhatsappsession/${whatsapp.id}`) + } catch (err) { + toastError(err) + } + } - function enable_button(whatsappId) { + useEffect(() => { + // whatsApps.map((e) => { + // if (buttons.includes(e.id)) { + // e.disabled = true + // } + // }) - setClicks(buttons => buttons.filter(id => { return +id !== +whatsappId }),); + for (let i = 0; i < whatsApps.length; i++) { + if (buttons.includes(whatsApps[i].id)) { + whatsApps[i].disabled = true + } + } + }, [whatsApps, buttons]) - } + const handleRequestNewQrCode = async (whatsAppId) => { + try { + await api.put(`/whatsappsession/${whatsAppId}`) + } catch (err) { + toastError(err) + } + } - setTimeout(enable_button, 25000, whatsapp.id) + const handleOpenWhatsAppModal = () => { + setSelectedWhatsApp(null) + setWhatsAppModalOpen(true) + } - await api.post(`/restartwhatsappsession/${whatsapp.id}`); + const handleCloseWhatsAppModal = useCallback(() => { + setWhatsAppModalOpen(false) + setSelectedWhatsApp(null) + }, [setSelectedWhatsApp, setWhatsAppModalOpen]) - } catch (err) { - toastError(err); - } - }; + const handleOpenQrModal = (whatsApp) => { + setSelectedWhatsApp(whatsApp) + setQrModalOpen(true) + } + const handleCloseQrModal = useCallback(() => { + setSelectedWhatsApp(null) + setQrModalOpen(false) + }, [setQrModalOpen, setSelectedWhatsApp]) - useEffect(() => { + const handleEditWhatsApp = (whatsApp) => { + setSelectedWhatsApp(whatsApp) + setWhatsAppModalOpen(true) + } - // whatsApps.map((e) => { - // if (buttons.includes(e.id)) { - // e.disabled = true - // } - // }) + const handleOpenConfirmationModal = (action, whatsAppId) => { + if (action === 'disconnect') { + setConfirmModalInfo({ + action: action, + title: i18n.t('connections.confirmationModal.disconnectTitle'), + message: i18n.t('connections.confirmationModal.disconnectMessage'), + whatsAppId: whatsAppId, + }) + } + if (action === 'delete') { + setConfirmModalInfo({ + action: action, + title: i18n.t('connections.confirmationModal.deleteTitle'), + message: i18n.t('connections.confirmationModal.deleteMessage'), + whatsAppId: whatsAppId, + }) + } + setConfirmModalOpen(true) + } - for (let i = 0; i < whatsApps.length; i++) { - if (buttons.includes(whatsApps[i].id)) { - whatsApps[i].disabled = true - } - } + const handleSubmitConfirmationModal = async () => { + if (confirmModalInfo.action === 'disconnect') { + try { + await api.delete(`/whatsappsession/${confirmModalInfo.whatsAppId}`) + } catch (err) { + toastError(err) + } + } - }, [whatsApps, buttons]) + if (confirmModalInfo.action === 'delete') { + try { + await api.delete(`/whatsapp/${confirmModalInfo.whatsAppId}`) + toast.success(i18n.t('connections.toasts.deleted')) + } catch (err) { + toastError(err) + } + } + setConfirmModalInfo(confirmationModalInitialState) + } - const handleRequestNewQrCode = async whatsAppId => { - try { - await api.put(`/whatsappsession/${whatsAppId}`); - } catch (err) { - toastError(err); - } - }; + const renderActionButtons = (whatsApp) => { + return ( + ( + <> + {whatsApp.status === 'qrcode' && ( + + )} + {whatsApp.status === 'DISCONNECTED' && ( + <> + {' '} + + + )} + {(whatsApp.status === 'CONNECTED' || + whatsApp.status === 'PAIRING' || + whatsApp.status === 'TIMEOUT') && ( + + )} + {whatsApp.status === 'OPENING' && ( + + )} + + )} + /> + ) + } - const handleOpenWhatsAppModal = () => { - setSelectedWhatsApp(null); - setWhatsAppModalOpen(true); - }; + const renderStatusToolTips = (whatsApp) => { + return ( +
+ {whatsApp.status === 'DISCONNECTED' && ( + + + + )} + {whatsApp.status === 'OPENING' && ( + + )} + {whatsApp.status === 'qrcode' && ( + + + + )} + {whatsApp.status === 'CONNECTED' && ( + + + + )} + {(whatsApp.status === 'TIMEOUT' || whatsApp.status === 'PAIRING') && ( + + + + )} - const handleCloseWhatsAppModal = useCallback(() => { - setWhatsAppModalOpen(false); - setSelectedWhatsApp(null); - }, [setSelectedWhatsApp, setWhatsAppModalOpen]); - - const handleOpenQrModal = whatsApp => { - setSelectedWhatsApp(whatsApp); - setQrModalOpen(true); - }; - - const handleCloseQrModal = useCallback(() => { - setSelectedWhatsApp(null); - setQrModalOpen(false); - }, [setQrModalOpen, setSelectedWhatsApp]); - - const handleEditWhatsApp = whatsApp => { - setSelectedWhatsApp(whatsApp); - setWhatsAppModalOpen(true); - }; - - const handleOpenConfirmationModal = (action, whatsAppId) => { - if (action === "disconnect") { - setConfirmModalInfo({ - action: action, - title: i18n.t("connections.confirmationModal.disconnectTitle"), - message: i18n.t("connections.confirmationModal.disconnectMessage"), - whatsAppId: whatsAppId, - }); - } - - if (action === "delete") { - setConfirmModalInfo({ - action: action, - title: i18n.t("connections.confirmationModal.deleteTitle"), - message: i18n.t("connections.confirmationModal.deleteMessage"), - whatsAppId: whatsAppId, - }); - } - setConfirmModalOpen(true); - }; - - const handleSubmitConfirmationModal = async () => { - if (confirmModalInfo.action === "disconnect") { - try { - await api.delete(`/whatsappsession/${confirmModalInfo.whatsAppId}`); - } catch (err) { - toastError(err); - } - } - - if (confirmModalInfo.action === "delete") { - try { - await api.delete(`/whatsapp/${confirmModalInfo.whatsAppId}`); - toast.success(i18n.t("connections.toasts.deleted")); - } catch (err) { - toastError(err); - } - } - - setConfirmModalInfo(confirmationModalInitialState); - }; - - const renderActionButtons = whatsApp => { - return ( - - ( - - <> - {whatsApp.status === "qrcode" && ( - - )} - {whatsApp.status === "DISCONNECTED" && ( - - <> - {" "} - - - )} - {(whatsApp.status === "CONNECTED" || - whatsApp.status === "PAIRING" || - whatsApp.status === "TIMEOUT") && ( - - )} - {whatsApp.status === "OPENING" && ( - - )} - - - )} - /> - - ); - }; - - const renderStatusToolTips = whatsApp => { - return ( -
- {whatsApp.status === "DISCONNECTED" && ( - - - - )} - {whatsApp.status === "OPENING" && ( - - )} - {whatsApp.status === "qrcode" && ( - - - - )} - {whatsApp.status === "CONNECTED" && ( - - - - )} - {(whatsApp.status === "TIMEOUT" || whatsApp.status === "PAIRING") && ( - - - - )} - - {/* {whatsApp.status === "RESTORING" && ( + {/* {whatsApp.status === "RESTORING" && ( { )} */} -
- ); - }; - - - - - useEffect(() => { - - const delayDebounceFn = setTimeout(() => { - - const fetchQueries = async () => { - try { - - await api.post(`/restartwhatsappsession/0`, { params: { status: 'status' }, }); - - setDisabled(false) - - setClicks(buttons => buttons.map((e) => { return { id: e.id, disabled: false } })) - - } catch (err) { - console.log(err); - } - }; - - fetchQueries(); - - }, 500); - return () => clearTimeout(delayDebounceFn); - - }, []); - - - useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL); - - socket.on("diskSpaceMonit", data => { - if (data.action === "update") { - - setDiskSpaceInfo(data.diskSpace) - - } - }); - - return () => { - socket.disconnect(); - }; - }, []); - - return ( - - ( - - - - {confirmModalInfo.message} - - - - - - - - - - - {i18n.t("connections.title")} - - - ( - - )} - /> - - - - - - - - <> - - ( - <> - - - - - Size - - - Used - - - Available - - - Use% - - - - - - - {diskSpaceInfo.size} - {diskSpaceInfo.used} - {diskSpaceInfo.available} - {diskSpaceInfo.use} - - -
-
- - )} - /> - - - - - - - {i18n.t("connections.table.name")} - - - - {i18n.t("connections.table.status")} - - - ( - - {i18n.t("connections.table.session")} - - )} - /> - - - - - ( - - Restore - - )} - /> - - - - ( - - Session MB - - )} - /> - - - - - - {i18n.t("connections.table.lastUpdate")} - - - {i18n.t("connections.table.default")} - - - {i18n.t("connections.table.actions")} - - - - - {loading ? ( - - ) : ( - <> - {whatsApps?.length > 0 && - whatsApps.map(whatsApp => ( - - {whatsApp.name} - - - {renderStatusToolTips(whatsApp)} - - - ( - - {renderActionButtons(whatsApp)} - - )} - /> - - - - - - - ( - - - - - - - )} - /> - - - - ( - - -
{whatsApp.sessionSize}
-
-
- )} - /> - - - - - - - {format(parseISO(whatsApp.updatedAt), "dd/MM/yy HH:mm")} - - - - - {whatsApp.isDefault && ( -
- -
- )} -
- - - - - ( - handleEditWhatsApp(whatsApp)} - > - - - )} - /> - - - ( - { - handleOpenConfirmationModal("delete", whatsApp.id); - }} - > - - - )} - /> - - -
- ))} - - )} -
-
- - -
-
- )} - /> - - ); -}; - -export default Connections; +
+ ) + } + + useEffect(() => { + const delayDebounceFn = setTimeout(() => { + const fetchQueries = async () => { + try { + await api.post(`/restartwhatsappsession/0`, { + params: { status: 'status' }, + }) + + setDisabled(false) + + setClicks((buttons) => + buttons.map((e) => { + return { id: e.id, disabled: false } + }) + ) + } catch (err) { + console.log(err) + } + } + + fetchQueries() + }, 500) + return () => clearTimeout(delayDebounceFn) + }, []) + + useEffect(() => { + const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + + socket.on('diskSpaceMonit', (data) => { + if (data.action === 'update') { + setDiskSpaceInfo(data.diskSpace) + } + }) + + socket.on('settings', (data) => { + if (data.action === 'update') { + setSettings((prevState) => { + const aux = [...prevState] + const settingIndex = aux.findIndex((s) => s.key === data.setting.key) + aux[settingIndex].value = data.setting.value + return aux + }) + } + }) + + return () => { + socket.disconnect() + } + }, []) + + return ( + ( + + + {confirmModalInfo.message} + + + + + + + + {i18n.t('connections.title')} + + + ( + + )} + /> + + + + + <> + ( + <> + + + + Size + Used + Available + Use% + + + + + + + {diskSpaceInfo.size} + + + {diskSpaceInfo.used} + + + {diskSpaceInfo.available} + + + {diskSpaceInfo.use} + + + +
+
+ + )} + /> + + + + + + {i18n.t('connections.table.name')} + + + + {i18n.t('connections.table.status')} + + + ( + + {i18n.t('connections.table.session')} + + )} + /> + + Restore} + /> + + ( + Session MB + )} + /> + + + {i18n.t('connections.table.lastUpdate')} + + + {i18n.t('connections.table.default')} + + + {i18n.t('connections.table.actions')} + + + + + {loading ? ( + + ) : ( + <> + {whatsApps?.length > 0 && + whatsApps.map((whatsApp) => ( + + + {whatsApp.name} + + + + {renderStatusToolTips(whatsApp)} + + + ( + + {renderActionButtons(whatsApp)} + + )} + /> + + ( + + + + )} + /> + + ( + + +
{whatsApp.sessionSize}
+
+
+ )} + /> + + + {format( + parseISO(whatsApp.updatedAt), + 'dd/MM/yy HH:mm' + )} + + + + {whatsApp.isDefault && ( +
+ +
+ )} +
+ + + ( + // disabled={ + // whatsApp.disabled || disabled + // ? true + // : false + // } +
+ {(settings && + settings.length > 0 && + getSettingValue('editURA') && + getSettingValue('editURA') === + 'enabled') | + (user.profile === 'master') ? ( + + handleEditWhatsApp(whatsApp) + } + > + + + ) : ( +
+ )} +
+ )} + /> + + ( + { + handleOpenConfirmationModal( + 'delete', + whatsApp.id + ) + }} + > + + + )} + /> +
+
+ ))} + + )} +
+
+ +
+
+ )} + /> + ) +} + +export default Connections diff --git a/frontend/src/pages/Queues/index.js b/frontend/src/pages/Queues/index.js index 4df3e78..99b6eab 100644 --- a/frontend/src/pages/Queues/index.js +++ b/frontend/src/pages/Queues/index.js @@ -1,6 +1,6 @@ -import React, { useEffect, useReducer, useState, useContext } from "react"; +import React, { useEffect, useReducer, useState, useContext } from 'react' -import openSocket from "socket.io-client"; +import openSocket from 'socket.io-client' import { Button, @@ -13,155 +13,186 @@ import { TableHead, TableRow, Typography, -} from "@material-ui/core"; +} from '@material-ui/core' -import MainContainer from "../../components/MainContainer"; -import MainHeader from "../../components/MainHeader"; -import MainHeaderButtonsWrapper from "../../components/MainHeaderButtonsWrapper"; -import TableRowSkeleton from "../../components/TableRowSkeleton"; -import Title from "../../components/Title"; -import { i18n } from "../../translate/i18n"; -import toastError from "../../errors/toastError"; -import api from "../../services/api"; -import { DeleteOutline, Edit } from "@material-ui/icons"; -import QueueModal from "../../components/QueueModal"; -import { toast } from "react-toastify"; -import ConfirmationModal from "../../components/ConfirmationModal"; +import MainContainer from '../../components/MainContainer' +import MainHeader from '../../components/MainHeader' +import MainHeaderButtonsWrapper from '../../components/MainHeaderButtonsWrapper' +import TableRowSkeleton from '../../components/TableRowSkeleton' +import Title from '../../components/Title' +import { i18n } from '../../translate/i18n' +import toastError from '../../errors/toastError' +import api from '../../services/api' +import { DeleteOutline, Edit } from '@material-ui/icons' +import QueueModal from '../../components/QueueModal' +import { toast } from 'react-toastify' +import ConfirmationModal from '../../components/ConfirmationModal' -import { AuthContext } from "../../context/Auth/AuthContext"; -import { Can } from "../../components/Can"; +import { AuthContext } from '../../context/Auth/AuthContext' +import { Can } from '../../components/Can' const useStyles = makeStyles((theme) => ({ mainPaper: { flex: 1, padding: theme.spacing(1), - overflowY: "scroll", + overflowY: 'scroll', ...theme.scrollbarStyles, }, customTableCell: { - display: "flex", - alignItems: "center", - justifyContent: "center", + display: 'flex', + alignItems: 'center', + justifyContent: 'center', }, -})); +})) const reducer = (state, action) => { - if (action.type === "LOAD_QUEUES") { - const queues = action.payload; - const newQueues = []; + if (action.type === 'LOAD_QUEUES') { + const queues = action.payload + const newQueues = [] queues.forEach((queue) => { - const queueIndex = state.findIndex((q) => q.id === queue.id); + const queueIndex = state.findIndex((q) => q.id === queue.id) if (queueIndex !== -1) { - state[queueIndex] = queue; + state[queueIndex] = queue } else { - newQueues.push(queue); + newQueues.push(queue) } - }); + }) - return [...state, ...newQueues]; + return [...state, ...newQueues] } - if (action.type === "UPDATE_QUEUES") { - const queue = action.payload; - const queueIndex = state.findIndex((u) => u.id === queue.id); + if (action.type === 'UPDATE_QUEUES') { + const queue = action.payload + const queueIndex = state.findIndex((u) => u.id === queue.id) if (queueIndex !== -1) { - state[queueIndex] = queue; - return [...state]; + state[queueIndex] = queue + return [...state] } else { - return [queue, ...state]; + return [queue, ...state] } } - if (action.type === "DELETE_QUEUE") { - const queueId = action.payload; - const queueIndex = state.findIndex((q) => q.id === queueId); + if (action.type === 'DELETE_QUEUE') { + const queueId = action.payload + const queueIndex = state.findIndex((q) => q.id === queueId) if (queueIndex !== -1) { - state.splice(queueIndex, 1); + state.splice(queueIndex, 1) } - return [...state]; + return [...state] } - if (action.type === "RESET") { - return []; + if (action.type === 'RESET') { + return [] } -}; +} const Queues = () => { - const classes = useStyles(); + const classes = useStyles() - const { user } = useContext(AuthContext); + const { user } = useContext(AuthContext) - const [queues, dispatch] = useReducer(reducer, []); - const [loading, setLoading] = useState(false); + const [queues, dispatch] = useReducer(reducer, []) + const [loading, setLoading] = useState(false) - const [queueModalOpen, setQueueModalOpen] = useState(false); - const [selectedQueue, setSelectedQueue] = useState(null); - const [confirmModalOpen, setConfirmModalOpen] = useState(false); + const [queueModalOpen, setQueueModalOpen] = useState(false) + const [selectedQueue, setSelectedQueue] = useState(null) + const [confirmModalOpen, setConfirmModalOpen] = useState(false) + + const [settings, setSettings] = useState([]) useEffect(() => { - (async () => { - setLoading(true); + ;(async () => { + setLoading(true) try { - const { data } = await api.get("/queue"); - dispatch({ type: "LOAD_QUEUES", payload: data }); + const { data } = await api.get('/queue') + dispatch({ type: 'LOAD_QUEUES', payload: data }) - setLoading(false); + setLoading(false) } catch (err) { - toastError(err); - setLoading(false); + toastError(err) + setLoading(false) } - })(); - }, []); + })() + }, []) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL); + const fetchSession = async () => { + try { + const { data } = await api.get('/settings') + setSettings(data) + } catch (err) { + toastError(err) + } + } + fetchSession() + }, []) - socket.on("queue", (data) => { - if (data.action === "update" || data.action === "create") { - dispatch({ type: "UPDATE_QUEUES", payload: data.queue }); + const getSettingValue = (key) => { + const { value } = settings.find((s) => s.key === key) + + return value + } + + useEffect(() => { + const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + + socket.on('queue', (data) => { + if (data.action === 'update' || data.action === 'create') { + dispatch({ type: 'UPDATE_QUEUES', payload: data.queue }) } - if (data.action === "delete") { - dispatch({ type: "DELETE_QUEUE", payload: data.queueId }); + if (data.action === 'delete') { + dispatch({ type: 'DELETE_QUEUE', payload: data.queueId }) } - }); + }) + + socket.on('settings', (data) => { + if (data.action === 'update') { + setSettings((prevState) => { + const aux = [...prevState] + const settingIndex = aux.findIndex((s) => s.key === data.setting.key) + aux[settingIndex].value = data.setting.value + return aux + }) + } + }) return () => { - socket.disconnect(); - }; - }, []); + socket.disconnect() + } + }, []) const handleOpenQueueModal = () => { - setQueueModalOpen(true); - setSelectedQueue(null); - }; + setQueueModalOpen(true) + setSelectedQueue(null) + } const handleCloseQueueModal = () => { - setQueueModalOpen(false); - setSelectedQueue(null); - }; + setQueueModalOpen(false) + setSelectedQueue(null) + } const handleEditQueue = (queue) => { - setSelectedQueue(queue); - setQueueModalOpen(true); - }; + setSelectedQueue(queue) + setQueueModalOpen(true) + } const handleCloseConfirmationModal = () => { - setConfirmModalOpen(false); - setSelectedQueue(null); - }; + setConfirmModalOpen(false) + setSelectedQueue(null) + } const handleDeleteQueue = async (queueId) => { try { - await api.delete(`/queue/${queueId}`); - toast.success(i18n.t("Queue deleted successfully!")); + await api.delete(`/queue/${queueId}`) + toast.success(i18n.t('Queue deleted successfully!')) } catch (err) { - toastError(err); + toastError(err) } - setSelectedQueue(null); - }; + setSelectedQueue(null) + } return ( { handleDeleteQueue(selectedQueue.id)} > - {i18n.t("queues.confirmationModal.deleteMessage")} + {i18n.t('queues.confirmationModal.deleteMessage')} { queueId={selectedQueue?.id} /> - {i18n.t("queues.title")} - + {i18n.t('queues.title')} { color="primary" onClick={handleOpenQueueModal} > - {i18n.t("queues.buttons.add")} + {i18n.t('queues.buttons.add')} )} /> - - - {i18n.t("queues.table.name")} + {i18n.t('queues.table.name')} - {i18n.t("queues.table.color")} + {i18n.t('queues.table.color')} - {i18n.t("queues.table.greeting")} + {i18n.t('queues.table.greeting')} - {i18n.t("queues.table.actions")} + {i18n.t('queues.table.actions')} @@ -238,7 +267,7 @@ const Queues = () => { backgroundColor: queue.color, width: 60, height: 20, - alignSelf: "center", + alignSelf: 'center', }} /> @@ -246,7 +275,7 @@ const Queues = () => {
@@ -255,25 +284,44 @@ const Queues = () => {
- - - - ( - handleEditQueue(queue)} +
- - + {(settings && + settings.length > 0 && + getSettingValue('editQueue') && + getSettingValue('editQueue') === 'enabled') | + (user.profile === 'master') ? ( + handleEditQueue(queue)} + > + + + ) : ( +
+ )} +
+ + // handleEditQueue(queue)} + // > + // + // )} /> - { { - setSelectedQueue(queue); - setConfirmModalOpen(true); + setSelectedQueue(queue) + setConfirmModalOpen(true) }} > )} /> -
))} @@ -301,7 +348,7 @@ const Queues = () => { )} /> - ); -}; + ) +} -export default Queues; +export default Queues diff --git a/frontend/src/pages/Settings/index.js b/frontend/src/pages/Settings/index.js index 2912d6d..ab79873 100644 --- a/frontend/src/pages/Settings/index.js +++ b/frontend/src/pages/Settings/index.js @@ -1,190 +1,207 @@ -import React, { useState, useEffect, useContext} from "react"; -import openSocket from "socket.io-client"; +import React, { useState, useEffect, useContext } from 'react' +import openSocket from 'socket.io-client' -import { makeStyles } 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 Select from "@material-ui/core/Select"; -import { toast } from "react-toastify"; +import { makeStyles } 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 Select from '@material-ui/core/Select' +import { toast } from 'react-toastify' -import api from "../../services/api"; -import { i18n } from "../../translate/i18n.js"; -import toastError from "../../errors/toastError"; +import api from '../../services/api' +import { i18n } from '../../translate/i18n.js' +import toastError from '../../errors/toastError' //-------- -import { AuthContext } from "../../context/Auth/AuthContext"; -import { Can } from "../../components/Can"; +import { AuthContext } from '../../context/Auth/AuthContext' + +import { Can } from '../../components/Can' // import Button from "@material-ui/core/Button"; -const useStyles = makeStyles(theme => ({ - root: { - display: "flex", - alignItems: "center", - padding: theme.spacing(4), - }, +const useStyles = makeStyles((theme) => ({ + root: { + display: 'flex', + alignItems: 'center', + padding: theme.spacing(4), + }, - paper: { - padding: theme.spacing(2), - display: "flex", - alignItems: "center", - }, + paper: { + padding: theme.spacing(2), + display: 'flex', + alignItems: 'center', + }, - settingOption: { - marginLeft: "auto", - }, - margin: { - margin: theme.spacing(1), - }, -})); + settingOption: { + marginLeft: 'auto', + }, + margin: { + margin: theme.spacing(1), + }, +})) const Settings = () => { - const classes = useStyles(); + const classes = useStyles() - //-------- - const { user } = useContext(AuthContext); + //-------- + const { user } = useContext(AuthContext) - const [settings, setSettings] = useState([]); + const [settings, setSettings] = useState([]) - useEffect(() => { - const fetchSession = async () => { - try { - const { data } = await api.get("/settings"); - setSettings(data); - } catch (err) { - toastError(err); - } - }; - fetchSession(); - }, []); + useEffect(() => { + const fetchSession = async () => { + try { + const { data } = await api.get('/settings') + setSettings(data) + } catch (err) { + toastError(err) + } + } + fetchSession() + }, []) - useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL); + useEffect(() => { + const socket = openSocket(process.env.REACT_APP_BACKEND_URL) - socket.on("settings", data => { - if (data.action === "update") { - setSettings(prevState => { - const aux = [...prevState]; - const settingIndex = aux.findIndex(s => s.key === data.setting.key); - aux[settingIndex].value = data.setting.value; - return aux; - }); - } - }); + socket.on('settings', (data) => { + console.log('settings updated ----------------------------') - return () => { - socket.disconnect(); - }; - }, []); + if (data.action === 'update') { + setSettings((prevState) => { + const aux = [...prevState] + const settingIndex = aux.findIndex((s) => s.key === data.setting.key) + aux[settingIndex].value = data.setting.value + return aux + }) + } + }) - const handleChangeSetting = async e => { - const selectedValue = e.target.value; - const settingKey = e.target.name; + return () => { + socket.disconnect() + } + }, []) - try { - await api.put(`/settings/${settingKey}`, { - value: selectedValue, - }); - toast.success(i18n.t("settings.success")); - } catch (err) { - toastError(err); - } - }; + useEffect(() => { + console.log('------> settings: ', settings) + }, [settings]) - const getSettingValue = key => { - const { value } = settings.find(s => s.key === key); - return value; - }; + const handleChangeSetting = async (e) => { + const selectedValue = e.target.value + const settingKey = e.target.name + try { + await api.put(`/settings/${settingKey}`, { + value: selectedValue, + }) + toast.success(i18n.t('settings.success')) + } catch (err) { + toastError(err) + } + } - // const handleEdit = () => { - - // - - // } + const getSettingValue = (key) => { + const { value } = settings.find((s) => s.key === key) - return ( + return value + } + return ( + ( +
+
+ + + {i18n.t('settings.title')} + - ( + + + {i18n.t('settings.settings.userCreation.name')} + -
+ + + +
-
- - - {i18n.t("settings.title")} - - - - - {i18n.t("settings.settings.userCreation.name")} - - - - - -
- +
+ + + Editar ura - {/*
- - - Application name - - - + + + +
- - Estudio Face - +
+ + + Editar fila + + + +
+
+ )} + /> + ) +} - - -
- -
-
*/} - -
- - )} - /> - - ); -}; - -export default Settings; +export default Settings diff --git a/frontend/src/rules.js b/frontend/src/rules.js index 2ea72e4..1b7c1ad 100644 --- a/frontend/src/rules.js +++ b/frontend/src/rules.js @@ -1,59 +1,58 @@ const rules = { - user: { - static: [], - }, + user: { + static: [], + }, - admin: { - static: [ - //"show-icon-edit-whatsapp", + admin: { + static: [ + 'show-icon-edit-whatsapp', + 'show-icon-edit-queue', - "drawer-admin-items:view", - "tickets-manager:showall", - "user-modal:editProfile", - "user-modal:editQueues", - "ticket-options:deleteTicket", - "contacts-page:deleteContact", - "contacts-page:import-csv-contacts", - "connections-view:show", - "dashboard-view:show", - "queues-view:show", - "user-view:show", - "ticket-report:show", - - ], - }, + 'drawer-admin-items:view', + 'tickets-manager:showall', + 'user-modal:editProfile', + 'user-modal:editQueues', + 'ticket-options:deleteTicket', + 'contacts-page:deleteContact', + 'contacts-page:import-csv-contacts', + 'connections-view:show', + 'dashboard-view:show', + 'queues-view:show', + 'user-view:show', + 'ticket-report:show', + ], + }, - master: { - static: [ + master: { + static: [ + 'url-remote-session:show', + 'show-icon-edit-whatsapp', + 'show-icon-add-queue', + 'show-icon-edit-queue', + 'show-icon-delete-queue', + 'space-disk-info:show', - "show-icon-edit-whatsapp", - "show-icon-add-queue", - "show-icon-edit-queue", - "show-icon-delete-queue", - "space-disk-info:show", - + 'drawer-admin-items:view', + 'tickets-manager:showall', + 'user-modal:editProfile', + 'user-modal:editQueues', + 'ticket-options:deleteTicket', + 'contacts-page:deleteContact', + 'contacts-page:import-contacts', + 'contacts-page:import-csv-contacts', + 'connections-view:show', + 'dashboard-view:show', + 'queues-view:show', + 'user-view:show', + 'settings-view:show', + 'btn-add-user', + 'icon-remove-user', + 'btn-add-whatsapp', + 'btn-remove-whatsapp', + 'ticket-report:show', + 'connection-button:show', + ], + }, +} - "drawer-admin-items:view", - "tickets-manager:showall", - "user-modal:editProfile", - "user-modal:editQueues", - "ticket-options:deleteTicket", - "contacts-page:deleteContact", - "contacts-page:import-contacts", - "contacts-page:import-csv-contacts", - "connections-view:show", - "dashboard-view:show", - "queues-view:show", - "user-view:show", - "settings-view:show", - "btn-add-user", - "icon-remove-user", - "btn-add-whatsapp", - "btn-remove-whatsapp", - "ticket-report:show", - "connection-button:show" - ], - }, -}; - -export default rules; +export default rules