From 3c42f1b2aac0a14c53ba325197b958d606f1611b Mon Sep 17 00:00:00 2001 From: Luis Felipe Risch <lfr20@inf.ufpr.br> Date: Mon, 9 Nov 2020 11:57:43 -0300 Subject: [PATCH] Start to build the file of community questions --- .../Pages/SubPages/CommunityQuestions.js | 551 ++++++++++++++++++ 1 file changed, 551 insertions(+) create mode 100644 src/Admin/Pages/Pages/SubPages/CommunityQuestions.js diff --git a/src/Admin/Pages/Pages/SubPages/CommunityQuestions.js b/src/Admin/Pages/Pages/SubPages/CommunityQuestions.js new file mode 100644 index 00000000..8bdef6e3 --- /dev/null +++ b/src/Admin/Pages/Pages/SubPages/CommunityQuestions.js @@ -0,0 +1,551 @@ +/*Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana + +This file is part of Plataforma Integrada MEC. + +Plataforma Integrada MEC is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Plataforma Integrada MEC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with Plataforma Integrada MEC. If not, see <http://www.gnu.org/licenses/>.*/ + +import React, { useEffect, useState } from "react"; +//imports from local files +import TableData from "../../../Components/Components/Table"; +import SnackBar from "../../../../Components/SnackbarComponent"; +import { Url } from "../../../Filters"; +import { GetFullList } from "../../../Services"; +//imports from material ui +import { withStyles } from "@material-ui/core/styles"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import TextField from "@material-ui/core/TextField"; +import Popover from "@material-ui/core/Popover"; +import IconButton from "@material-ui/core/IconButton"; +import { Button, Typography, Paper, Grid } from "@material-ui/core"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import AddRoundedIcon from "@material-ui/icons/AddRounded"; +import UpdateRoundedIcon from "@material-ui/icons/UpdateRounded"; +import CancelRoundedIcon from '@material-ui/icons/CancelRounded'; +import FilterListRoundedIcon from "@material-ui/icons/FilterListRounded"; +import VisibilityIcon from "@material-ui/icons/Visibility"; +import EmailRoundedIcon from '@material-ui/icons/EmailRounded'; +//routers +import { Link } from 'react-router-dom'; + +let currPage = 0; +let viewItem = {}; + +const StyledTableCell = withStyles((theme) => ({ + head: { + backgroundColor: theme.palette.common.black, + color: theme.palette.common.white, + }, + body: { + fontSize: 14, + }, +}))(TableCell); + +const StyledTableRow = withStyles((theme) => ({ + root: { + "&:nth-of-type(odd)": { + backgroundColor: theme.palette.action.hover, + }, + }, +}))(TableRow); + +const Activity = () => { + const ADD_ONE_LENGHT = [""]; + const TOP_LABELS = [ + "ID", + "DATA DE CONTATO", + "NOME", + "EMAIL", + "MENSAGEM", + "VISUALIZAR" + ]; //Labels from Table + + const [anchorEl, setAnchorEl] = React.useState(null); + + const [error, setError] = useState(null); //Necessary to consult the API, catch errors + const [isLoaded, setIsLoaded] = useState(false); //Necessary to consult the API, wait until complete + const [items, setItems] = useState([]); //Necessary to consult the API, data + + const [isLoadingMoreItems, setIsLoadingMoreItems] = useState(false); //controlls the state of loadind more data + const [isUpdating, setIsUpdating] = useState(false); //controlls the state of updating data + + //Works with the filter + const [showMessageFilter, setShowMessageFilter] = useState(false); + const [showEmailFilter, setShowEmailFilter] = useState(false); + const [showNameFilter, setShowNameFilter] = useState(false); + const [message, setMessage] = useState(''); + const [email, setEmail] = useState(''); + const [name, setName] = useState(''); + + const [snackInfo, setSnackInfo] = useState({ + message: "", + icon: "", + open: false, + color: "", + }); + + //handle with the message filter + const MessageFilterHandler = async (e) => { + setMessage(e.target.value) + const headers = { + Accept: "application/json", + "Content-Type": "application/json; charset=utf-8", + "access-token": sessionStorage.getItem("@portalmec/accessToken"), + client: sessionStorage.getItem("@portalmec/clientToken"), + uid: sessionStorage.getItem("@portalmec/uid"), + 'If-None-Match': null + }; + + GetFullList(Url("contacts", `"message" : "${message}"`, currPage, 'DESC'), headers).then((res) => { + console.log(res); + if (res.state) { + const arrData = [...res.data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + } else { + HandleSnack("Não achamos nada na nossa base de dados!", true, "warning", "#FA8072"); + } + }); + } + + //handle with the email filter + const EmailFilterHandler = (e) => { + setEmail(e.target.value) + const headers = { + Accept: "application/json", + "Content-Type": "application/json; charset=utf-8", + "access-token": sessionStorage.getItem("@portalmec/accessToken"), + client: sessionStorage.getItem("@portalmec/clientToken"), + uid: sessionStorage.getItem("@portalmec/uid"), + 'If-None-Match': null + }; + + GetFullList(Url("contacts", `"email" : "${email}"`, currPage, 'DESC'), headers).then((res) => { + console.log(res); + if (res.state) { + const arrData = [...res.data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + } else { + HandleSnack("Não achamos nada na nossa base de dados!", true, "warning", "#FA8072"); + } + }); + } + + //handle with the name filter + const NameFilterHandler = (e) => { + setName(e.target.value) + const headers = { + Accept: "application/json", + "Content-Type": "application/json; charset=utf-8", + "access-token": sessionStorage.getItem("@portalmec/accessToken"), + client: sessionStorage.getItem("@portalmec/clientToken"), + uid: sessionStorage.getItem("@portalmec/uid"), + 'If-None-Match': null + }; + + GetFullList(Url("contacts", `"name" : "${name}"`, currPage, 'DESC'), headers).then((res) => { + console.log(res); + if (res.state) { + const arrData = [...res.data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + } else { + HandleSnack("Não achamos nada na nossa base de dados!", true, "warning", "#FA8072"); + } + }); + } + + //handle snack info + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color, + }); + }; + + const handleClick = (event) => { + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const open = Boolean(anchorEl); + const id = open ? 'simple-popover' : undefined; + + //handle load more items + const LoadMoreItens = async (api) => { + setIsLoadingMoreItems(true); + const headers = { + Accept: "application/json", + "Content-Type": "application/json; charset=utf-8", + "access-token": sessionStorage.getItem("@portalmec/accessToken"), + client: sessionStorage.getItem("@portalmec/clientToken"), + uid: sessionStorage.getItem("@portalmec/uid"), + 'If-None-Match': null + }; + + GetFullList(api, headers).then((res) => { + if (res.state) { + const arrData = [...res.data]; + if (arrData.length === 0) { + HandleSnack( + "Não há mais dados para serem carregados", + true, + "warning", + "#FFC125" + ); + } else { + const arrItems = [...items]; + arrItems.pop(); //Deleting the last position, that was used to display the button of load more items + const arrResult = arrItems.concat(arrData); + setItems(arrResult.concat(ADD_ONE_LENGHT)); + } + } else { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + } + setIsLoadingMoreItems(false); + }); + }; + + // handle update list data + const UpdateHandler = async (api) => { + setIsUpdating(true); + const headers = { + Accept: "application/json", + "Content-Type": "application/json; charset=utf-8", + "access-token": sessionStorage.getItem("@portalmec/accessToken"), + client: sessionStorage.getItem("@portalmec/clientToken"), + uid: sessionStorage.getItem("@portalmec/uid"), + 'If-None-Match': null + }; + + GetFullList(api, headers).then((res) => { + console.log(res); + if (res.state) { + HandleSnack( + "A lista de dados foi atualizada", + true, + "success", + "#228B22" + ); + const arrData = [...res.data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + } else { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + } + setIsUpdating(false); + }); + }; + + //getting data from server + useEffect(() => { + const headers = { + Accept: "application/json", + "Content-Type": "application/json; charset=utf-8", + "access-token": sessionStorage.getItem("@portalmec/accessToken"), + client: sessionStorage.getItem("@portalmec/clientToken"), + uid: sessionStorage.getItem("@portalmec/uid"), + }; + + GetFullList(Url("contacts", "", `${currPage}`, "DESC"), headers).then( + (res) => { + if (res.state) { + const arrData = [...res.data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + setIsLoaded(true); + setError(false); + } else { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + setIsLoaded(true); + setError(true); + } + } + ); + }, []); + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <div>Loading...</div>; + } else { + + return <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) + } + /> + + <Paper style={{ padding: "1em" }}> + <Grid container spacing={3} direction="row" alignItems="center"> + <Grid item xs={6}> + <Typography variant="h4">Dúvidas da comunidade</Typography> + </Grid> + <Grid + item + xs={6} + alignItems="center" + justify="center" + direction="row" + > + <Grid container justify="flex-end" spacing={3}> + <Grid item> + <Button + variant="contained" + color="secondary" + disabled={isUpdating} + onClick={() => { + currPage = 0; + UpdateHandler( + Url("contacts", "", `${currPage}`, "DESC") + ); + }} + startIcon={<UpdateRoundedIcon />} + > + {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} + </Button> + </Grid> + <Grid item> + <Button + variant="contained" + color="secondary" + onClick={(e) => { + currPage = 0; + UpdateHandler( + Url("contacts", "", `${currPage}`, "DESC") + ); + handleClick(e); + }} + startIcon={<FilterListRoundedIcon />} + > + Filtrar + </Button> + <Popover + id={id} + open={open} + anchorEl={anchorEl} + onClose={handleClose} + anchorOrigin={{ + vertical: 'bottom', + horizontal: 'center', + }} + transformOrigin={{ + vertical: 'top', + horizontal: 'center', + }} + > + <Button + onClick={() => setShowEmailFilter(!showEmailFilter)} + color={showEmailFilter ? 'primary' : 'default'} + variant='text' + > + EMAIL + </Button> + + <Button + onClick={() => setShowMessageFilter(!showMessageFilter)} + color={showMessageFilter ? 'primary' : 'default'} + variant='text' + > + MENSAGEM + </Button> + + <Button + onClick={() => setShowNameFilter(!showNameFilter)} + color={showNameFilter ? 'primary' : 'default'} + variant='text' + > + NOME + </Button> + </Popover> + </Grid> + </Grid> + </Grid> + </Grid> + + <div style={{ height: '1.5em' }}></div> + + <Grid item xs={12}> + <Grid container justify="space-between" spacing={3}> + { + showMessageFilter ? + <Grid item> + <TextField + label='Mensagem' + type="search" + onChange={(e) => MessageFilterHandler(e)} + /> + <IconButton + size="small" + color="primary" + onClick={() => { + currPage = 0; + UpdateHandler( + Url("contacts", "", `${currPage}`, "DESC") + ); + setShowMessageFilter(false) + }} + > + <CancelRoundedIcon /> + </IconButton> + </Grid> : null + } + { + showEmailFilter ? + <Grid item> + <TextField + label='Email' + type="search" + onChange={(e) => EmailFilterHandler(e)} + /> + <IconButton + size="small" + color="primary" + onClick={() => { + currPage = 0; + UpdateHandler( + Url("contacts", "", `${currPage}`, "DESC") + ); + setShowEmailFilter(false) + }} + > + <CancelRoundedIcon /> + </IconButton> + </Grid> : null + } + { + showNameFilter ? + <Grid item> + <TextField + label='Nome' + type="search" + onChange={(e) => NameFilterHandler(e)} + /> + <IconButton + size="small" + color="primary" + onClick={() => { + currPage = 0; + UpdateHandler( + Url("contacts", "", `${currPage}`, "DESC") + ); + setShowNameFilter(false) + }} + > + <CancelRoundedIcon /> + </IconButton> + </Grid> : null + } + </Grid> + </Grid> + </Paper> + + <div style={{ height: "2em" }}></div> + + <TableData top={TOP_LABELS}> + <TableBody> + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledTableRow style={{ padding: "1em" }}> + {/* Button to load more data */} + <Button + color="primary" + variant="text" + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + currPage++; + if (showMessageFilter) { + LoadMoreItens( + Url("contacts", `"message" : "${message}"`, `${currPage}`, "DESC") + ); + } else if (showEmailFilter) { + LoadMoreItens( + Url("contacts", `"email" : "${email}"`, `${currPage}`, "DESC") + ); + } else if (showNameFilter) { + LoadMoreItens( + Url("contacts", `"name" : "${name}"`, `${currPage}`, "DESC") + ); + } else { + LoadMoreItens( + Url("contacts", "", `${currPage}`, "DESC") + ); + } + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledTableRow> + ) : ( + <StyledTableRow key={index}> + <StyledTableCell component="th" scope="row"> + {row.id} + </StyledTableCell> + <StyledTableCell align="right"> + {row.created_at} + </StyledTableCell> + <StyledTableCell align="right"> + {row.name} + </StyledTableCell> + <StyledTableCell align="right"> + { + row.email ? + <Link to={`/admin/sendEmail/${row.email}`} style={{textDecoration : 'none'}}> + <Button + variant='text' + color='primary' + startIcon={<EmailRoundedIcon />} + > + {row.email} + </Button> + </Link> : null + } + </StyledTableCell> + <StyledTableCell align="right"> + {row.message} + </StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/activity/${row.id}`}> + <IconButton> + <VisibilityIcon style={{ fill: "#00bcd4" }} /> + </IconButton> + </Link> + </StyledTableCell> + </StyledTableRow> + ) + )} + </TableBody> + </TableData> + </> + }; +} +export default Activity; -- GitLab