diff --git a/src/Admin/Components/Components/AppBar.js b/src/Admin/Components/Components/AppBar.js new file mode 100644 index 0000000000000000000000000000000000000000..b596c35f59484e8754b79c68d787feced4011913 --- /dev/null +++ b/src/Admin/Components/Components/AppBar.js @@ -0,0 +1,73 @@ +import React from 'react'; +import PropTypes from "prop-types"; +import Typography from "@material-ui/core/Typography"; +import Box from "@material-ui/core/Box"; +import AppBar from "@material-ui/core/AppBar"; +import { Tab, Tabs } from "@material-ui/core"; +import { Link } from 'react-router-dom' +import { TabsItens } from '../../Pages/AdminLabelTabs/LabelTabs' + +function TabPanel(props) { + const { children, value, index, ...other } = props; + + return ( + <div + role="tabpanel" + hidden={value !== index} + id={`nav-tabpanel-${index}`} + aria-labelledby={`nav-tab-${index}`} + {...other} + > + {value === index && ( + <Box p={3}> + <Typography>{children}</Typography> + </Box> + )} + </div> + ); +} + +TabPanel.propTypes = { + children: PropTypes.node, + index: PropTypes.any.isRequired, + value: PropTypes.any.isRequired, +}; + +function a11yProps(index) { + return { + id: `nav-tab-${index}`, + "aria-controls": `nav-tabpanel-${index}`, + }; +} +export default function AppBarAdmin() { + const [value, setValue] = React.useState(0); + + const handleChange = (event, newValue) => { + setValue(newValue); + }; + + return ( + <AppBar position="sticky" color="default"> + <Tabs + variant="scrollable" + scrollButtons="on" + value={value} + onChange={handleChange} + aria-label="nav tabs example" + > + { + TabsItens.map((label, index) => ( + <Tab + key={label.href} + label={label.label} + to={label.href} + icon={label.icon} + component={Link} + {...a11yProps(index)} + /> + )) + } + </Tabs> + </AppBar> + ) +} \ No newline at end of file diff --git a/src/Admin/Components/Components/DataCards/ActivityCard.js b/src/Admin/Components/Components/DataCards/ActivityCard.js index d3bdcbe1d1f8d11122a150950099243f1a9cf510..915df2f99fdb31c17741d362555721f14a3753f9 100644 --- a/src/Admin/Components/Components/DataCards/ActivityCard.js +++ b/src/Admin/Components/Components/DataCards/ActivityCard.js @@ -32,7 +32,7 @@ import { getRequest } from '../../../../Components/HelperFunctions/getAxiosConfi import { Link } from 'react-router-dom' import LoadingSpinner from '../../../../Components/LoadingSpinner'; -const ActivityCard = ({ match }) => { +const ActivityCard = () => { const classes = useStyles(); const [error, setError] = useState(null); //Necessary to consult the API, catch errors @@ -48,7 +48,9 @@ const ActivityCard = ({ match }) => { //getting data from server useEffect(() => { - getRequest(GetAData("activities", match.params.id), + const urlParams = new URLSearchParams(window.location.search); + const query = urlParams.get("activity"); + getRequest(GetAData("activities", query), (data, header) => { setItem(data); setIsLoaded(true); @@ -120,7 +122,7 @@ const ActivityCard = ({ match }) => { </Link> </Grid> </Grid> - <div style={{height: "1em"}}/> + <div style={{ height: "1em" }} /> {DATA.map((info, index) => ( <div className={classes.displayColumn} key={index}> <Typography color="initial" className={classes.subTitle}> diff --git a/src/Admin/Components/Components/DataCards/CollectionCard.js b/src/Admin/Components/Components/DataCards/CollectionCard.js index fa06198a87093ad05ca72addaed66fd26e566b0f..a4ef28da2b30bdff799545b79d7936b5415e19ca 100644 --- a/src/Admin/Components/Components/DataCards/CollectionCard.js +++ b/src/Admin/Components/Components/DataCards/CollectionCard.js @@ -36,9 +36,11 @@ import LoadingSpinner from '../../../../Components/LoadingSpinner'; import SnackBar from '../../../../Components/SnackbarComponent'; import { getRequest, deleteRequest } from '../../../../Components/HelperFunctions/getAxiosConfig'; -const CollectionCard = ({ match }) => { +const CollectionCard = () => { let history = useHistory() const classes = useStyles(); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("collection"); 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 @@ -69,7 +71,6 @@ const CollectionCard = ({ match }) => { //Called when user want to delete one institution async function DeleteHandler() { - const id = match.params.id deleteRequest( DeleteFilter("collections", id), (data) => { @@ -93,7 +94,7 @@ const CollectionCard = ({ match }) => { useEffect(() => { getRequest( - GetAData("collections", match.params.id), + GetAData("collections", id), (data, header) => { setItem(data); setIsLoaded(true); @@ -178,14 +179,14 @@ const CollectionCard = ({ match }) => { </Button> </Link> - <Link style={{ textDecoration: 'none' }} to={`/admin/EditCollection/${item.id}`}> + <Link style={{ textDecoration: 'none' }} to={`/admin/EditCollection?collection=${item.id}`}> <Button startIcon={<EditRoundedIcon />} color="primary" variant="outlined" > Editar - </Button> + </Button> </Link> <Button @@ -198,7 +199,7 @@ const CollectionCard = ({ match }) => { </Button> </Grid> </Grid> - <div style={{height: "1em"}}/> + <div style={{ height: "1em" }} /> {DATA.map((info, index) => ( <div className={classes.displayColumn} key={index}> <Typography color="initial" className={classes.subTitle}> diff --git a/src/Admin/Components/Components/DataCards/CommunityQuestionCard.js b/src/Admin/Components/Components/DataCards/CommunityQuestionCard.js index 4ee4a1448f3a4f1efb90df90e9bcd63bd4164ffc..b8ae952c3dabc4ff4c7fd73ceb45a6d3123972b1 100644 --- a/src/Admin/Components/Components/DataCards/CommunityQuestionCard.js +++ b/src/Admin/Components/Components/DataCards/CommunityQuestionCard.js @@ -36,7 +36,7 @@ import Unauthorized from "../Unauthorized"; import { getRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' import LoadingSpinner from '../../../../Components/LoadingSpinner'; -const CommunityQuestions = ({ match }) => { +const CommunityQuestions = () => { const { state } = useContext(Store); const classes = useStyles(); @@ -68,8 +68,10 @@ const CommunityQuestions = ({ match }) => { } useEffect(() => { + const urlParams = new URLSearchParams(window.location.search); + const query = urlParams.get("question"); getRequest( - GetAData("contacts", match.params.id), + GetAData("contacts", query), (data, header) => { setItem(data); setIsLoaded(true); @@ -100,7 +102,7 @@ const CommunityQuestions = ({ match }) => { subTitle: "Email", prop: item.email ? - <Link to={`/admin/sendEmail/${item.email}`} style={{ textDecoration: 'none' }}> + <Link to={`/admin/sendEmail/?email=${item.email}`} style={{ textDecoration: 'none' }}> <Button variant='text' color='primary' diff --git a/src/Admin/Components/Components/DataCards/ComplaintsCard.js b/src/Admin/Components/Components/DataCards/ComplaintsCard.js index 17f7623e403413685bd15f2e2a56474f736b1dcd..4c3fc1337f6c2a18d26e20b9191f46bfe003ed1a 100644 --- a/src/Admin/Components/Components/DataCards/ComplaintsCard.js +++ b/src/Admin/Components/Components/DataCards/ComplaintsCard.js @@ -51,8 +51,10 @@ import { getRequest, postRequest } from '../../../../Components/HelperFunctions/ const PORTAL_MEC = "https://plataformaintegrada.mec.gov.br/"; -const CollectionCard = ({ match }) => { +const CollectionCard = () => { const classes = useStyles(); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("id"); const [error, setError] = useState(null); //Necessary to consult the API, catch errors @@ -179,7 +181,7 @@ const CollectionCard = ({ match }) => { const reloadData = () => { setIsLoaded(false) getRequest( - GetAData("complaints", match.params.id), + GetAData("complaints", id), (data, header) => { setItem(data) setIsLoaded(true); @@ -212,7 +214,7 @@ const CollectionCard = ({ match }) => { HandleSnack('Alteração feito com sucesso!', true, 'success', '#228B22') reloadData() } - }, + }, (error) => { HandleSnack('Ocorreu algum erro', true, 'warning', '#FA8072') } @@ -357,7 +359,7 @@ const CollectionCard = ({ match }) => { case "User": return ( <CardActions> - <Link to={`/admin/user/${item.complainable_id}`}> + <Link to={`/admin/user?id=${item.complainable_id}`}> <Button variant="contained" color="primary" @@ -566,13 +568,12 @@ const CollectionCard = ({ match }) => { const HandleComplainObj = async (method) => { postRequest( - MethodsToComplain("complaints", match.params.id, method), + MethodsToComplain("complaints", id, method), {}, (data) => { if (data.errors) HandleSnack('Ocorreu algum erro', true, 'warning', '#FA8072') - else - { + else { HandleSnack('Alteração feito com sucesso', true, 'success', '#228B22') reloadData() } @@ -595,7 +596,7 @@ const CollectionCard = ({ match }) => { useEffect(() => { getRequest( - GetAData("complaints", match.params.id), + GetAData("complaints", id), (data, header) => { setItem(data) setIsLoaded(true); @@ -685,7 +686,7 @@ const CollectionCard = ({ match }) => { > { - item.complainable_type === "User" ? `Usuário #${item.complainable_id}` : `Recurso #${item.complainable_id}` + item.complainable_type === "User" ? `Usuário #${item.complainable_id}` : `Recurso #${item.complainable_id}` } </Typography> </Grid> @@ -704,7 +705,7 @@ const CollectionCard = ({ match }) => { </Link> </Grid> </Grid> - <div style={{height: "1em"}}/> + <div style={{ height: "1em" }} /> {DATA.map((info, index) => ( <div className={classes.displayColumn} key={index}> <Typography color="initial" className={classes.subTitle}> diff --git a/src/Admin/Components/Components/DataCards/EducationalObjectsCard.js b/src/Admin/Components/Components/DataCards/EducationalObjectsCard.js index 493f577fa3f1b2a31a0724312e1c24923af61e98..08a8f3255e1015758e98373e8c2d7e25c70cd05e 100644 --- a/src/Admin/Components/Components/DataCards/EducationalObjectsCard.js +++ b/src/Admin/Components/Components/DataCards/EducationalObjectsCard.js @@ -41,9 +41,11 @@ import { } from "../../../../Components/HelperFunctions/getAxiosConfig"; import SnackBar from "../../../../Components/SnackbarComponent"; -const CommunityQuestions = ({ match }) => { +const CommunityQuestions = () => { const classes = useStyles(); let history = useHistory(); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("learnObj"); 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 @@ -73,7 +75,6 @@ const CommunityQuestions = ({ match }) => { }); async function DeleteHandler() { - const id = match.params.id; deleteRequest( DeleteFilter("learning_objects", id), (data) => { @@ -97,7 +98,7 @@ const CommunityQuestions = ({ match }) => { useEffect(() => { getRequest( - GetAData("learning_objects", match.params.id), + GetAData("learning_objects", id), (data, header) => { setItem(data); setIsLoaded(true); @@ -264,7 +265,7 @@ const CommunityQuestions = ({ match }) => { href={ apiUrl + "/learning_objects/" + - match.params.id + + id + "/download" } > @@ -273,7 +274,7 @@ const CommunityQuestions = ({ match }) => { </Button> <Link style={{ textDecoration: "none" }} - to={`/admin/learningObjectEdit/${item.id}`} + to={`/admin/learningObjectEdit?learnObj=${item.id}`} > <Button startIcon={<EditRoundedIcon />} @@ -293,7 +294,7 @@ const CommunityQuestions = ({ match }) => { </Button> </Grid> </Grid> - <div style={{height: "1em"}}/> + <div style={{ height: "1em" }} /> {item.thumbnail ? ( <div style={{ marginTop: "1em", marginBottom: "1em" }}> <a target="_blank" rel="noreferrer" href={apiDomain + item.thumbnail}> diff --git a/src/Admin/Components/Components/DataCards/InstitutionsCard.js b/src/Admin/Components/Components/DataCards/InstitutionsCard.js index 817fcfad40a7b73678cb2b9dfd6637df166980c7..b4981b7bb93715a8bbfa0bc94f8d85e628df3416 100644 --- a/src/Admin/Components/Components/DataCards/InstitutionsCard.js +++ b/src/Admin/Components/Components/DataCards/InstitutionsCard.js @@ -36,9 +36,12 @@ import { Link, useHistory } from 'react-router-dom'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; import SnackBar from '../../../../Components/SnackbarComponent'; -const InstitutionCard = ({ match }) => { +const InstitutionCard = () => { const classes = useStyles(); - let history = useHistory() + let history = useHistory(); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("institution"); + 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 @@ -68,7 +71,6 @@ const InstitutionCard = ({ match }) => { }); async function DeleteHandler() { - const id = match.params.id deleteRequest( DeleteFilter("institutions", id), (data) => { @@ -92,7 +94,7 @@ const InstitutionCard = ({ match }) => { useEffect(() => { getRequest( - GetAData('institutions', match.params.id), + GetAData('institutions', id), (data, header) => { setIsLoaded(true); setItem(data); @@ -176,7 +178,7 @@ const InstitutionCard = ({ match }) => { </Button> </Link> - <Link style={{ textDecoration: 'none' }} to={`/admin/institutionEdit/${item.id}`}> + <Link style={{ textDecoration: 'none' }} to={`/admin/institutionEdit?institution=${item.id}`}> <Button startIcon={<EditRoundedIcon />} color="primary" @@ -196,7 +198,7 @@ const InstitutionCard = ({ match }) => { </Button> </Grid> </Grid> - <div style={{height: "1em"}}/> + <div style={{ height: "1em" }} /> {DATA.map((info, index) => ( <div className={classes.displayColumn} key={index}> <Typography color="initial" className={classes.subTitle}> diff --git a/src/Admin/Components/Components/DataCards/NoteVarCard.js b/src/Admin/Components/Components/DataCards/NoteVarCard.js index 6b72bddfa0ebd118b13bba0dfc0866b135b14ae4..7c7b4356f9f174607e330987ee15081724b080e8 100644 --- a/src/Admin/Components/Components/DataCards/NoteVarCard.js +++ b/src/Admin/Components/Components/DataCards/NoteVarCard.js @@ -34,9 +34,10 @@ import { getRequest } from '../../../../Components/HelperFunctions/getAxiosConfi import { Link } from 'react-router-dom'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; -const NoteCard = ({ match }) => { - console.log(match); +const NoteCard = () => { const classes = useStyles(); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("id"); 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 @@ -52,7 +53,7 @@ const NoteCard = ({ match }) => { useEffect(() => { getRequest( - GetAData('scores', match.params.id), + GetAData('scores', id), (data, header) => { setIsLoaded(true); setItem(data); @@ -116,7 +117,7 @@ const NoteCard = ({ match }) => { </Button> </Link> - <Link style={{ textDecoration: 'none' }} to={`/admin/noteVarEdit/${item.id}`}> + <Link style={{ textDecoration: 'none' }} to={`/admin/noteVarEdit?id=${item.id}`}> <Button startIcon={<EditRoundedIcon />} color="primary" diff --git a/src/Admin/Components/Components/DataCards/RatingCard.js b/src/Admin/Components/Components/DataCards/RatingCard.js index c333b56c6c5946e87370693780eb622288338b7c..b5f69a53c800dce0324ec0afb274a97ce315fc8e 100644 --- a/src/Admin/Components/Components/DataCards/RatingCard.js +++ b/src/Admin/Components/Components/DataCards/RatingCard.js @@ -36,9 +36,11 @@ import { Link, useHistory } from 'react-router-dom'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; import SnackBar from '../../../../Components/SnackbarComponent'; -const RatingCard = ({ match }) => { +const RatingCard = () => { const classes = useStyles(); - let history = useHistory() + let history = useHistory(); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("rating"); 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 @@ -68,7 +70,6 @@ const RatingCard = ({ match }) => { }; async function DeleteHandler() { - const id = match.params.id deleteRequest( DeleteFilter("ratings", id), (data) => { @@ -93,7 +94,7 @@ const RatingCard = ({ match }) => { useEffect(() => { getRequest( - GetAData('ratings', match.params.id), + GetAData('ratings', id), (data, header) => { setIsLoaded(true); setItem(data); @@ -165,7 +166,7 @@ const RatingCard = ({ match }) => { </Button> </Link> - <Link style={{ textDecoration: 'none' }} to={`/admin/EditRating/${item.id}`}> + <Link style={{ textDecoration: 'none' }} to={`/admin/EditRating?rating=${item.id}`}> <Button startIcon={<EditRoundedIcon />} color="primary" @@ -185,7 +186,7 @@ const RatingCard = ({ match }) => { </Button> </Grid> </Grid> - <div style={{height: "1em"}}/> + <div style={{ height: "1em" }} /> {DATA.map((info, index) => ( <div className={classes.displayColumn} key={index}> <Typography color="initial" className={classes.subTitle}> diff --git a/src/Admin/Components/Components/DataCards/UserCard.js b/src/Admin/Components/Components/DataCards/UserCard.js index d4e82906c3470fdaac4fbbbfd0308d5bd7baf0e3..a34f96b390a075eed4c3aed1a28b3baacc968734 100644 --- a/src/Admin/Components/Components/DataCards/UserCard.js +++ b/src/Admin/Components/Components/DataCards/UserCard.js @@ -45,9 +45,12 @@ import { getRequest, postRequest, deleteRequest, putRequest } from '../../../../ //styles import styled from 'styled-components'; -const CollectionCard = ({ match }, props) => { +const CollectionCard = () => { let history = useHistory() const classes = useStyles(); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("id"); + 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 [item, setItem] = useState({}); @@ -138,7 +141,7 @@ const CollectionCard = ({ match }, props) => { const reloadData = () => { setIsLoaded(false) getRequest( - GetAData("users", match.params.id), + GetAData("users", id), (data, header) => { setItem(data) setIsLoaded(true); @@ -159,13 +162,12 @@ const CollectionCard = ({ match }, props) => { url, body, (data) => { - if(data.errors) + if (data.errors) HandleSnack("Erro!", true, "warning", "#FA8072"); - else - { + else { HandleSnack(`${userName} aceito como professor!`, true, "success", "#228B22"); reloadData() - } + } }, (error) => { HandleSnack("Erro!", true, "warning", "#FA8072"); @@ -182,13 +184,12 @@ const CollectionCard = ({ match }, props) => { url, body, (data) => { - if(data.errors) + if (data.errors) HandleSnack("Erro!", true, "warning", "#FA8072"); - else - { - HandleSnack(`${userName} rejeitado como professor!`, true, "success", "#228B22"); - reloadData() - } + else { + HandleSnack(`${userName} rejeitado como professor!`, true, "success", "#228B22"); + reloadData() + } }, (error) => { HandleSnack("Erro!", true, "warning", "#FA8072"); @@ -200,10 +201,9 @@ const CollectionCard = ({ match }, props) => { deleteRequest( `/users/${userId}`, (data) => { - if(data.errors) + if (data.errors) HandleSnack("Erro!", true, "warning", "#FA8072") - else - { + else { HandleSnack(`${item.name} deletado com sucesso!`, true, "success", "#228B22"); history.goBack() } @@ -243,8 +243,8 @@ const CollectionCard = ({ match }, props) => { </Button> ) } - return <Typography color="textSecondary"> - Usuário não bloqueado + return <Typography color="textSecondary"> + Usuário não bloqueado </Typography> } @@ -294,16 +294,15 @@ const CollectionCard = ({ match }, props) => { const ReactiveUser = () => { putRequest( - `/users/${match.params.id}/reactivate_user`, + `/users/${id}/reactivate_user`, {}, (data) => { - if(data.errors) + if (data.errors) HandleSnack('Erro ao tentar reativar usuário!', true, 'warning', '#FA8072') - else - { + else { HandleSnack('Usuário foi reativado com sucesso!', true, 'success', '#228B22') reloadData() - } + } }, (error) => { HandleSnack('Erro ao tentar reativar usuário!', true, 'warning', '#FA8072') @@ -313,7 +312,7 @@ const CollectionCard = ({ match }, props) => { useEffect(() => { getRequest( - GetAData("users", match.params.id), + GetAData("users", id), (data, header) => { setItem(data) setIsLoaded(true); @@ -390,7 +389,7 @@ const CollectionCard = ({ match }, props) => { </Button> </Grid> <Grid item> - <Link to={`/admin/EditUser/${item.id}`} style={{ textDecoration: "none" }}> + <Link to={`/admin/EditUser?id=${item.id}`} style={{ textDecoration: "none" }}> <Button startIcon={<EditRoundedIcon />} color="primary" @@ -425,7 +424,7 @@ const CollectionCard = ({ match }, props) => { </Typography> { item.email ? - <Link to={`/admin/sendEmail/${item.email}`} style={{ textDecoration: 'none' }}> + <Link to={`/admin/sendEmail?email=${item.email}`} style={{ textDecoration: 'none' }}> <Button variant='text' color='primary' diff --git a/src/Admin/Components/Components/DisplayIcon.js b/src/Admin/Components/Components/DisplayIcon.js deleted file mode 100644 index 5336574d7124413e47603fd0fc63122c12853f2e..0000000000000000000000000000000000000000 --- a/src/Admin/Components/Components/DisplayIcon.js +++ /dev/null @@ -1,79 +0,0 @@ -/*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 from "react"; -import ListItemIcon from "@material-ui/core/ListItemIcon"; -import HomeIcon from "@material-ui/icons/Home"; -import PeopleRoundedIcon from "@material-ui/icons/PeopleRounded"; -import ContactSupportRoundedIcon from "@material-ui/icons/ContactSupportRounded"; -import LanguageRoundedIcon from "@material-ui/icons/LanguageRounded"; -import AccountBalanceRoundedIcon from "@material-ui/icons/AccountBalanceRounded"; -import MenuBookRoundedIcon from "@material-ui/icons/MenuBookRounded"; -import StarRoundedIcon from "@material-ui/icons/StarRounded"; -import AccountCircleRoundedIcon from "@material-ui/icons/AccountCircleRounded"; -import TrendingUpRoundedIcon from "@material-ui/icons/TrendingUpRounded"; -import HelpRoundedIcon from "@material-ui/icons/HelpRounded"; -import CheckRoundedIcon from "@material-ui/icons/CheckRounded"; -import PersonRoundedIcon from "@material-ui/icons/PersonRounded"; -import BlockRoundedIcon from "@material-ui/icons/BlockRounded"; -import AnnouncementRoundedIcon from "@material-ui/icons/AnnouncementRounded"; -import EmailRoundedIcon from "@material-ui/icons/EmailRounded"; -import TimelineRoundedIcon from "@material-ui/icons/TimelineRounded"; -import SettingsRoundedIcon from "@material-ui/icons/SettingsRounded"; -import ExitToAppRoundedIcon from "@material-ui/icons/ExitToAppRounded"; -import AllOutIcon from "@material-ui/icons/AllOut"; -import SportsEsportsRoundedIcon from '@material-ui/icons/SportsEsportsRounded'; - -//This file manipulate the icon that will be displayed in the left navigation menu - -const orange = "#ff7f00"; -const pink = "#e81f4f"; -const purple = "#673ab7"; -const blue = "#00bcd4"; - -const icons = [ - <HomeIcon style={{ fill: orange }} />, - <PeopleRoundedIcon style={{ fill: pink }} />, - <AllOutIcon style={{ fill: purple }} />, - <ContactSupportRoundedIcon style={{ fill: blue }} />, - <AccountBalanceRoundedIcon style={{ fill: orange }} />, - <LanguageRoundedIcon style={{ fill: pink }} />, - <MenuBookRoundedIcon style={{ fill: purple }} />, - <StarRoundedIcon style={{ fill: blue }} />, - <AccountCircleRoundedIcon style={{ fill: orange }} />, - <TrendingUpRoundedIcon style={{ fill: pink }} />, - <HelpRoundedIcon style={{ fill: purple }} />, - <CheckRoundedIcon style={{ fill: blue }} />, - <PersonRoundedIcon style={{ fill: orange }} />, - <BlockRoundedIcon style={{ fill: pink }} />, - <AnnouncementRoundedIcon style={{ fill: purple }} />, - <EmailRoundedIcon style={{ fill: blue }} />, - <SportsEsportsRoundedIcon style={{fill: orange }}/>, - <TimelineRoundedIcon style={{ fill: orange }} />, - <SettingsRoundedIcon style={{ fill: pink }} />, - <ExitToAppRoundedIcon style={{ fill: purple }} />, -]; - -const DisplayIcon = (props) => { - return( - <ListItemIcon> - {icons[props.i]} - </ListItemIcon> - ); -}; -export default DisplayIcon; diff --git a/src/Admin/Components/Components/Inputs/CreateInstitution.js b/src/Admin/Components/Components/Inputs/CreateInstitution.js index 9520845704b1986e1cba74a687c9e84184452e91..b4f001f083f15aa192319a899cbad7dcac96421a 100644 --- a/src/Admin/Components/Components/Inputs/CreateInstitution.js +++ b/src/Admin/Components/Components/Inputs/CreateInstitution.js @@ -138,18 +138,21 @@ const CreateInstitution = (props) => { if (data.id) HandleSnack('A instituição foi criada com sucesso', true, 'success', '#228B22') else { - if(data.errors){ + if (data.errors) { HandleSnack(`${data.errors[0]}`, true, 'warning', '#FA8072') } - if (data.name) { - let nameError = ""; - data.name.map((msg) => ( - nameError = nameError + msg + " e " - )) - setErrorInName({ - error: true, - message: nameError - }) + else { + if (data.name) { + let nameError = ""; + data.name.map((msg) => ( + nameError = nameError + msg + " e " + )) + setErrorInName({ + error: true, + message: nameError + }) + } + HandleSnack('Você precisa preencher algumas informações obrigatórias', true, 'warning', '#FFC125') } } setIsLoading(false) diff --git a/src/Admin/Components/Components/Inputs/CreateLanguage.js b/src/Admin/Components/Components/Inputs/CreateLanguage.js index 4e40599bd6ab48da253d6c5b7618c71774870e73..c9a6590184ea0695d365aa6a58e3119c5dfa4051 100644 --- a/src/Admin/Components/Components/Inputs/CreateLanguage.js +++ b/src/Admin/Components/Components/Inputs/CreateLanguage.js @@ -123,28 +123,31 @@ const CreateLanguage = (props) => { if (data.id) HandleSnack('A linguagem foi criada com sucesso', true, 'success', '#228B22') else { - if(data.errors){ + if (data.errors) { HandleSnack(`${data.errors[0]}`, true, 'warning', '#FA8072') } - if (data.name) { - let nameError = ""; - data.name.map((msg) => ( - nameError = nameError + msg + " e " - )) - setErrorInName({ - error: true, - message: nameError - }) - } - if (data.code) { - let codeError = ""; - data.code.map((msg) => ( - codeError = codeError + msg + " e " - )) - setErrorInCode({ - error: true, - message: codeError - }) + else { + if (data.name) { + let nameError = ""; + data.name.map((msg) => ( + nameError = nameError + msg + " e " + )) + setErrorInName({ + error: true, + message: nameError + }) + } + if (data.code) { + let codeError = ""; + data.code.map((msg) => ( + codeError = codeError + msg + " e " + )) + setErrorInCode({ + error: true, + message: codeError + }) + } + HandleSnack('Você precisa preencher algumas informações obrigatórias', true, 'warning', '#FFC125') } } setIsLoading(false) diff --git a/src/Admin/Components/Components/Inputs/CreateRole.js b/src/Admin/Components/Components/Inputs/CreateRole.js index 042616ca42bef887952fc897dfd57483ff8d170c..94afb02479f83a1f9830f659c77d478247a62c26 100644 --- a/src/Admin/Components/Components/Inputs/CreateRole.js +++ b/src/Admin/Components/Components/Inputs/CreateRole.js @@ -124,18 +124,21 @@ const CreateRole = (props) => { if (data.id) HandleSnack('A role foi criada com sucesso!', true, 'success', '#228B22') else { - if(data.errors){ + if (data.errors) { HandleSnack(`${data.errors[0]}`, true, 'warning', '#FA8072') } - if (data.name) { - let errorName = ""; - data.name.map((err) => ( - errorName = errorName + err + " e " - )) - setErrorInName({ - error: true, - message: errorName - }) + else { + if (data.name) { + let errorName = ""; + data.name.map((err) => ( + errorName = errorName + err + " e " + )) + setErrorInName({ + error: true, + message: errorName + }) + } + HandleSnack('Você precisa preencher algumas informações obrigatórias', true, 'warning', '#FFC125') } } setIsLoading(false) diff --git a/src/Admin/Components/Components/Inputs/EditCollection.js b/src/Admin/Components/Components/Inputs/EditCollection.js index 67917eb60ac05c634de6f5b5bb0d9d317bdf2938..13aabcf16dac0ebc5f77ca965b60cfa6b5508395 100644 --- a/src/Admin/Components/Components/Inputs/EditCollection.js +++ b/src/Admin/Components/Components/Inputs/EditCollection.js @@ -38,14 +38,15 @@ import { Link } from 'react-router-dom'; import ClassicEditor from "@ckeditor/ckeditor5-build-classic" import { CKEditor } from '@ckeditor/ckeditor5-react'; -const EditCollection = ({ match }) => { +const EditCollection = () => { const { state } = useContext(Store); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("collection"); 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 [isLoading, setIsLoading] = useState(false); - const id = match.params.id const [name, setName] = useState('') const [privacy, setPrivacy] = useState('') const [description, setDescription] = useState(''); @@ -149,10 +150,10 @@ const EditCollection = ({ match }) => { api, body, (data) => { - if(data.errors){ + if (data.errors) { HandleSnack(`${data.errors[0]}`, true, 'warning', '#FA8072') } - else{ + else { HandleSnack('A Coleção foi alterada com sucesso', true, 'success', '#228B22') } setIsLoading(false) @@ -166,7 +167,7 @@ const EditCollection = ({ match }) => { useEffect(() => { getRequest( - GetAData("collections", match.params.id), + GetAData("collections", id), (data, header) => { setIsLoaded(true); setError(false); diff --git a/src/Admin/Components/Components/Inputs/EditEducationalObect.js b/src/Admin/Components/Components/Inputs/EditEducationalObect.js index f5eca6838ec49afecb190b9cff6928b7a475352c..5996383029e0fc08a2b770c8fe7aa32a6b6f2b9e 100644 --- a/src/Admin/Components/Components/Inputs/EditEducationalObect.js +++ b/src/Admin/Components/Components/Inputs/EditEducationalObect.js @@ -62,14 +62,14 @@ const useStyles = makeStyles((theme) => ({ let text; -const EditEducationalObject = ({ match }) => { +const EditEducationalObject = () => { const { state } = useContext(Store); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("learnObj"); const theme = useTheme(); const classes = useStyles(); - const id = match.params.id; - 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 [isLoading, setIsLoading] = useState(false); //is loading to submit @@ -275,7 +275,7 @@ const EditEducationalObject = ({ match }) => { "#228B22" ); } else { - if(data.errors){ + if (data.errors) { HandleSnack(`${data.errors[0]}`, true, 'warning', '#FA8072') } if (data.author) { @@ -399,7 +399,7 @@ const EditEducationalObject = ({ match }) => { useEffect(() => { const urls = [ - `/learning_objects/${match.params.id}`, + `/learning_objects/${id}`, "/languages", "/object_types", ]; diff --git a/src/Admin/Components/Components/Inputs/EditLanguage.js b/src/Admin/Components/Components/Inputs/EditLanguage.js index 8215429e0c0a0f0cbcedbccf9122295dd5b3e970..44df71ceed76a2846983700ced3f66f60143e7e4 100644 --- a/src/Admin/Components/Components/Inputs/EditLanguage.js +++ b/src/Admin/Components/Components/Inputs/EditLanguage.js @@ -37,15 +37,16 @@ import DeleteRoundedIcon from "@material-ui/icons/DeleteRounded"; import { Link, useHistory } from 'react-router-dom'; import Unauthorized from '../Unauthorized'; -const EditLanguage = ({ match }) => { +const EditLanguage = () => { const { state } = useContext(Store); let history = useHistory() + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("language"); 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 [isLoading, setIsLoading] = useState(false); - const id = match.params.id const [name, setName] = useState() const [code, setCode] = useState() @@ -67,7 +68,6 @@ const EditLanguage = ({ match }) => { }) async function DeleteHandler() { - const id = match.params.id deleteRequest( DeleteFilter("languages", id), (data) => { @@ -180,7 +180,7 @@ const EditLanguage = ({ match }) => { if (data.id) HandleSnack('A linguagem foi alterada com sucesso!', true, 'success', '#228B22') else { - if(data.errors){ + if (data.errors) { HandleSnack(`${data.errors[0]}`, true, 'warning', '#FA8072') } if (data.name) { @@ -215,7 +215,7 @@ const EditLanguage = ({ match }) => { useEffect(() => { getRequest( - GetAData("languages", match.params.id), + GetAData("languages", id), (data, header) => { setIsLoaded(true); setName(data.name) diff --git a/src/Admin/Components/Components/Inputs/EditRating.js b/src/Admin/Components/Components/Inputs/EditRating.js index a42363d639aacd2ea9051c60eb07f02e0ef23075..1b8e0e6fd7c2c054f389dd7f62316778c4aebfa1 100644 --- a/src/Admin/Components/Components/Inputs/EditRating.js +++ b/src/Admin/Components/Components/Inputs/EditRating.js @@ -33,17 +33,18 @@ import LoadingSpinner from '../../../../Components/LoadingSpinner'; import { getRequest, putRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' import { EditFilter, GetAData } from '../../../Filters'; //routers -import {Link} from 'react-router-dom'; +import { Link } from 'react-router-dom'; import Unauthorized from '../Unauthorized'; -const EditRating = ({ match }) => { +const EditRating = () => { const { state } = useContext(Store); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("rating"); 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 [isLoading, setIsLoading] = useState(false); - const id = match.params.id const [name, setName] = useState() const [description, setDescription] = useState() @@ -161,7 +162,7 @@ const EditRating = ({ match }) => { api, body, (data, header) => { - if(data.errors) + if (data.errors) HandleSnack('Ocorreu algum erro', true, 'warning', '#FA8072') else HandleSnack('O rating foi alterada com sucesso', true, 'success', '#228B22') @@ -193,7 +194,7 @@ const EditRating = ({ match }) => { useEffect(() => { getRequest( - GetAData("ratings", match.params.id), + GetAData("ratings", id), (data, header) => { setIsLoaded(true); setName(data.name) @@ -209,8 +210,8 @@ const EditRating = ({ match }) => { if (error) { return <div> Houve um erro... </div> } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..."/> - } else if(CheckUserPermission()){ + return <LoadingSpinner text="Carregando..." /> + } else if (CheckUserPermission()) { return ( <Card> <SnackBar @@ -233,7 +234,7 @@ const EditRating = ({ match }) => { </Typography> </Grid> <Grid item> - <Link style={{textDecoration: 'none'}} to={'/admin/Ratings'}> + <Link style={{ textDecoration: 'none' }} to={'/admin/Ratings'}> <Button startIcon={<ListRoundedIcon />} variant='outlined' @@ -282,7 +283,7 @@ const EditRating = ({ match }) => { </CardAction> </Card> ) - } else return <Unauthorized/> + } else return <Unauthorized /> } export default EditRating; \ No newline at end of file diff --git a/src/Admin/Components/Components/Inputs/EditRoles.js b/src/Admin/Components/Components/Inputs/EditRoles.js index 9b2ecaa148bbc29ba1c0a7aefa5da22111767042..4b3aa488a8d6f8d2334d29a55680b49ed8020787 100644 --- a/src/Admin/Components/Components/Inputs/EditRoles.js +++ b/src/Admin/Components/Components/Inputs/EditRoles.js @@ -38,15 +38,16 @@ import { EditFilter, GetAData, DeleteFilter } from '../../../Filters'; import { Link, useHistory } from 'react-router-dom'; import Unauthorized from '../Unauthorized'; -const EditLanguage = ({ match }) => { +const EditLanguage = () => { const { state } = useContext(Store); let history = useHistory() + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("role"); 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 [isLoading, setIsLoading] = useState(false); - const id = match.params.id const [name, setName] = useState() const [desc, setDesc] = useState() const [snackInfo, setSnackInfo] = useState({ @@ -157,18 +158,21 @@ const EditLanguage = ({ match }) => { if (data.id) HandleSnack('A role foi alterada com sucesso', true, 'success', '#228B22') else { - if(data.errors){ + if (data.errors) { HandleSnack(`${data.errors[0]}`, true, 'warning', '#FA8072') } - if (data.name) { - let errorName = ""; - data.name.map((err) => ( - errorName = errorName + err + " e " - )) - setErrorInName({ - error: true, - message: errorName - }) + else { + HandleSnack('Você precisa preencher algumas informações obrigatórias', true, 'warning', '#FFC125') + if (data.name) { + let errorName = ""; + data.name.map((err) => ( + errorName = errorName + err + " e " + )) + setErrorInName({ + error: true, + message: errorName + }) + } } } setIsLoading(false) @@ -182,7 +186,6 @@ const EditLanguage = ({ match }) => { } async function DeleteHandler() { - const id = match.params.id deleteRequest( DeleteFilter("roles", id), (data) => { @@ -206,7 +209,7 @@ const EditLanguage = ({ match }) => { useEffect(() => { getRequest( - GetAData("roles", match.params.id), + GetAData("roles", id), (data, header) => { setIsLoaded(true); setName(data.name) diff --git a/src/Admin/Components/Components/Inputs/EditUser.js b/src/Admin/Components/Components/Inputs/EditUser.js index 1dadf1b4f6367c975ea280184916d353a0cc2fbd..fe9a61c8931170c9685afa20e5a1ac118d569511 100644 --- a/src/Admin/Components/Components/Inputs/EditUser.js +++ b/src/Admin/Components/Components/Inputs/EditUser.js @@ -57,11 +57,12 @@ const useStyles = makeStyles((theme) => ({ }, })); -const EditUser = ({ match }) => { +const EditUser = () => { const classes = useStyles(); let history = useHistory(); const { state } = useContext(Store) - const id = match.params.id + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("id"); const [error, setError] = useState(id !== "-1" ? null : false); //Necessary to consult the API, catch errors const [isLoaded, setIsLoaded] = useState(id === "-1" ? true : false); //Necessary to consult the API, wait until complete @@ -291,10 +292,9 @@ const EditUser = ({ match }) => { deleteRequest( `/users/${userId}`, (data) => { - if(data.errors) + if (data.errors) HandleSnack("Erro!", true, "warning", "#FA8072"); - else - { + else { HandleSnack(`${name} deletado com sucesso!`, true, "success", "#228B22"); history.push("/admin/usersList") } @@ -329,7 +329,7 @@ const EditUser = ({ match }) => { if (data.id) HandleSnack(`O usuário: ${name} foi atualizado`, true, 'success', '#228B22') else { - if(data.errors){ + if (data.errors) { HandleSnack(`${data.errors[0]}`, true, 'warning', '#FA8072') } if (data.email) { @@ -381,12 +381,14 @@ const EditUser = ({ match }) => { body, (data) => { setIsLoading(false) - if (data.id) - { + if (data.id) { HandleSnack(`O usuário: ${name} foi criado`, true, 'success', '#228B22') history.push("/admin/usersList") } else { + if (data.errors) { + HandleSnack(`${data.errors[0]}`, true, 'warning', '#FA8072') + } if (data.password) { let passError = ""; data.password.map((msg) => ( @@ -453,9 +455,9 @@ const EditUser = ({ match }) => { const currRolesList = [...rolesList]; const auxiliarRolesId = [ 1, 2, 3, 4, 5, 6, 7, 9, 10, 11 - ] - for (let i = 0; i < data.roles.length; i++) { - const rol = data.roles[i]; + ] + for (let i = 0; i < data.roles.length; i++) { + const rol = data.roles[i]; const index = auxiliarRolesId.indexOf(rol.id); currRolesList.splice(index, 1); auxiliarRolesId.splice(index, 1); diff --git a/src/Admin/Components/Components/Inputs/EmailInputs.js b/src/Admin/Components/Components/Inputs/EmailInputs.js index 0b7a55e5eb445605db721c1a44394b19e53e2172..f75e8b482316ff43cea4ddff066ef9896ef81798 100644 --- a/src/Admin/Components/Components/Inputs/EmailInputs.js +++ b/src/Admin/Components/Components/Inputs/EmailInputs.js @@ -34,8 +34,6 @@ import { postRequest } from '../../../../Components/HelperFunctions/getAxiosConf import ClassicEditor from "@ckeditor/ckeditor5-build-classic" import { CKEditor } from '@ckeditor/ckeditor5-react'; -let sendToAll = false; - const useStyles = makeStyles((theme) => ({ root: { display: 'flex', @@ -52,11 +50,13 @@ const useStyles = makeStyles((theme) => ({ const EmailInputs = (props) => { const classes = useStyles(); - const [option, setOption] = useState("Todos os usuários"); //labels of the text field 'to' - const [index, setIndex] = useState(0); //Used to display something above the text field 'to' depending on what the user clicks + const [option, setOption] = useState(props.email ? "Emails" : "All"); //labels of the text field 'to' + const [isToEmails, setIsToEmails] = useState(props.email ? true : false) + const [isToAll, setIsToAll] = useState(props.email ? false : true) + const [isToRoles, setIsToRoles] = useState(false) // Capture th text insert by the user in the fields - const [emails, setEmails] = useState(props.email === "none" ? "" : props.email); + const [emails, setEmails] = useState(props.email ? props.email : ""); const [emailsAdress, setEmailsAdress] = useState([]); const [subject, setSubject] = useState(""); const [message, setMessage] = useState(""); @@ -153,12 +153,22 @@ const EmailInputs = (props) => { const handleChange = (e) => { const value = e.target.value; - if (value === "All") { - sendToAll = true; - } else { - sendToAll = false; + if (value === 'All') { + setIsToAll(true) + setIsToEmails(false) + setIsToRoles(false) + } + if (value === 'Emails') { + setIsToEmails(true) + setIsToRoles(false) + setIsToAll(false) } - setOption(value); + if (value === 'Roles') { + setIsToRoles(true) + setIsToAll(false) + setIsToEmails(false) + } + setOption(value) }; const handleChangeCheckBox = (i) => { @@ -188,7 +198,7 @@ const EmailInputs = (props) => { const OnKeyPressHandler = (key) => { if (key === 13) { - if (!isEmpty(emails)) { + if (!itsEmpty(emails)) { if (emails.includes("@")) { const arr = [...emailsAdress]; arr.push(emails); @@ -218,10 +228,6 @@ const EmailInputs = (props) => { setEmailsAdress(copyEmail); }; - const isEmpty = (text) => { - return text.length === 0 ? true : false; - }; - // Handle snack infos const HandleSnack = (message, state, icon, color) => { setSnackInfo({ @@ -238,45 +244,100 @@ const EmailInputs = (props) => { setEmailsAdress([]); }; + const itsEmpty = (obj) => { + return obj.length === 0 + } + const submitRequest = async () => { - // setIsSending(true); + setIsSending(true); + const rolesArr = []; - for (let index = 0; index < roles.length; index++) { - const role = roles[index] - if (role.isChecked) - rolesArr.push(role.value) - } - console.log(rolesArr) - console.log(sendToAll) const api = `/email`; const body = { "email": { - "all_users": sendToAll, + "all_users": isToAll, "subject": subject, "body": message, - "emails": emailsAdress, - "roles": rolesArr, + "emails": isToEmails ? emailsAdress : [], + "roles": isToRoles ? rolesArr : [], }, }; - postRequest( - api, - body, - (data, header) => { - HandleSnack( - "O email foi enviado com sucesso", - true, - "success", - "#228B22" - ); - setIsSending(false); - CleanFields(); - }, - (error) => { - HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); - setIsSending(false); - CleanFields(); - } - ) + + for (let index = 0; index < roles.length; index++) { + const role = roles[index] + if (role.isChecked) + rolesArr.push(role.value) + } + + if (isToRoles && !itsEmpty(rolesArr) && !itsEmpty(subject) && !itsEmpty(body)) + postRequest( + api, + body, + (data, header) => { + HandleSnack( + "O email foi enviado com sucesso", + true, + "success", + "#228B22" + ); + setIsSending(false); + CleanFields(); + }, + (error) => { + HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); + setIsSending(false); + CleanFields(); + } + ) + else if (isToEmails && !itsEmpty(emailsAdress) && !itsEmpty(subject) && !itsEmpty(body)) + postRequest( + api, + body, + (data, header) => { + HandleSnack( + "O email foi enviado com sucesso", + true, + "success", + "#228B22" + ); + setIsSending(false); + CleanFields(); + }, + (error) => { + HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); + setIsSending(false); + CleanFields(); + } + ) + else if (isToAll && !itsEmpty(emailsAdress) && !itsEmpty(subject) && !itsEmpty(body)) + postRequest( + api, + body, + (data, header) => { + HandleSnack( + "O email foi enviado com sucesso", + true, + "success", + "#228B22" + ); + setIsSending(false); + CleanFields(); + }, + (error) => { + HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); + setIsSending(false); + CleanFields(); + } + ) + else { + HandleSnack( + "Você precisa preencher todos os campos!", + true, + "warning", + "#FFC125" + ); + setIsSending(false); + } }; return ( @@ -328,7 +389,6 @@ const EmailInputs = (props) => { > {options.map((option, index) => ( <MenuItem - onClick={() => setIndex(index)} key={option.value} value={option.value} > @@ -337,8 +397,8 @@ const EmailInputs = (props) => { ))} </TextField> <div style={{ height: "1em" }} /> - - {index === 0 ? null : index === 1 ? ( + { + isToRoles && <FormGroup style={{ marginBottom: "1em" }}> {roles.map((role, index) => ( <FormControlLabel @@ -355,45 +415,45 @@ const EmailInputs = (props) => { /> ))} </FormGroup> - ) : ( - <> - <div - style={{ - display: "flex", - flexDirection: "row", - flexWrap: "wrap", - justifyContent: "Space-between", - marginBottom: "1em" - }} - > - {emailsAdress.map((email, index) => ( - <li key={index} style={{ listStyleType: "none", marginBottom: "0.5em" }}> - <Chip - label={email} - onDelete={() => HandleDelete(index)} - classes={classes.chip} - /> - </li> - ))} - </div> - - <TextField - id="outlined-input" - label="Emails" - rows={1} - error={errorInEmails.error} - helperText={errorInEmails.message} - value={emails} - onKeyPress={(key) => OnKeyPressHandler(key.which)} - onChange={EmailsHandler} - // onBlur={ShowEmails} - placeholder="Digite um email por vez e pressione Enter" - variant="outlined" - style={{ marginBottom: "1em" }} - /> - </> - )} - + } + { + isToEmails && + <> + <div + style={{ + display: "flex", + flexDirection: "row", + flexWrap: "wrap", + justifyContent: "Space-between", + marginBottom: "1em" + }} + > + {emailsAdress.map((email, index) => ( + <li key={index} style={{ listStyleType: "none", marginBottom: "0.5em" }}> + <Chip + label={email} + onDelete={() => HandleDelete(index)} + classes={classes.chip} + /> + </li> + ))} + </div> + <TextField + id="outlined-input" + label="Emails" + rows={1} + error={errorInEmails.error} + helperText={errorInEmails.message} + value={emails} + onKeyPress={(key) => OnKeyPressHandler(key.which)} + onChange={EmailsHandler} + // onBlur={ShowEmails} + placeholder="Digite um email por vez e pressione Enter" + variant="outlined" + style={{ marginBottom: "1em" }} + /> + </> + } <TextField id="outlined-input" label="Assunto" @@ -404,7 +464,7 @@ const EmailInputs = (props) => { onChange={SubjectHandler} variant="outlined" /> - </form> + </form > <div style={{ height: "1em" }} /> @@ -433,10 +493,10 @@ const EmailInputs = (props) => { color="primary" startIcon={<SendRoundedIcon />} > - {isSending ? <CircularProgress /> : "Enviar"} + {isSending ? <CircularProgress size={24} /> : "Enviar"} </Button> </div> - </div> + </div > ); }; diff --git a/src/Admin/Components/Components/Inputs/IntitutionsInputs.js b/src/Admin/Components/Components/Inputs/IntitutionsInputs.js index a4098e68855cea0deacccf7705205923e740c818..148f006fd401c3e485beb476954f6a324f7d25d3 100644 --- a/src/Admin/Components/Components/Inputs/IntitutionsInputs.js +++ b/src/Admin/Components/Components/Inputs/IntitutionsInputs.js @@ -37,10 +37,10 @@ import { EditFilter, GetAData } from '../../../Filters'; //Routers import { Link } from 'react-router-dom'; -let id; - -const EditInstitution = ({ match }) => { +const EditInstitution = () => { const { state } = useContext(Store); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("institution"); 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 @@ -98,7 +98,7 @@ const EditInstitution = ({ match }) => { } setCountry(e.target.value) } - + // Handle snack infos const HandleSnack = (message, state, icon, color) => { setSnackInfo({ @@ -145,18 +145,21 @@ const EditInstitution = ({ match }) => { if (data.id) HandleSnack('A instituição foi criada com sucesso!', true, 'success', '#228B22') else { - if(data.errors){ + if (data.errors) { HandleSnack(`${data.errors[0]}`, true, 'warning', '#FA8072') } - if (data.name) { - let errorName = ""; - data.name.map((err) => ( - errorName = errorName + err + " e " - )) - setErrorInName({ - error: true, - message: errorName - }) + else { + HandleSnack('Você precisa preencher algumas informações obrigatórias', true, 'warning', '#FFC125') + if (data.name) { + let errorName = ""; + data.name.map((err) => ( + errorName = errorName + err + " e " + )) + setErrorInName({ + error: true, + message: errorName + }) + } } } setIsLoading(false) @@ -209,8 +212,9 @@ const EditInstitution = ({ match }) => { ] useEffect(() => { + getRequest( - GetAData("institutions", match.params.id), + GetAData("institutions", id), (data, header) => { setIsLoaded(true); setName(data.name) @@ -218,7 +222,6 @@ const EditInstitution = ({ match }) => { setAdress(data.adress) setCity(data.city) setCountry(data.country) - id = data.id }, (error) => { setIsLoaded(true); diff --git a/src/Admin/Components/Components/Inputs/NoteVarInputs.js b/src/Admin/Components/Components/Inputs/NoteVarInputs.js index 8753d1a21b214342965e7bbc9f6cbc0427ab8f40..3c1542ec851b700c0b53755592659fd2a7f9cd21 100644 --- a/src/Admin/Components/Components/Inputs/NoteVarInputs.js +++ b/src/Admin/Components/Components/Inputs/NoteVarInputs.js @@ -37,14 +37,15 @@ import { EditFilter, GetAData } from '../../../Filters'; import { Link } from 'react-router-dom'; import Unauthorized from '../Unauthorized'; -const NoteVarInputs = ({ match }) => { +const NoteVarInputs = () => { const { state } = useContext(Store); + const urlParams = new URLSearchParams(window.location.search); + const id = urlParams.get("id"); 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 [isLoading, setIsLoading] = useState(false); - const id = match.params.id const [name, setName] = useState() const [code, setCode] = useState() const [weight, setWeight] = useState() @@ -165,28 +166,31 @@ const NoteVarInputs = ({ match }) => { if (data.id) HandleSnack('A variável de nota foi atualizada com sucesso!', true, 'success', '#228B22') else { - if(data.errors){ + if (data.errors) { HandleSnack(`${data.errors[0]}`, true, 'warning', '#FA8072') } - if (data.name) { - let errorName = ""; - data.name.map((err) => ( - errorName = errorName + err + " e " - )) - setErrorInName({ - error: true, - message: errorName - }) - } - if(data.weight){ - let weightError = ""; - data.weight.map((err) => ( - weightError = weightError + err + " e " - )) - setErrorInWeight({ - error: true, - message : weightError - }) + else { + HandleSnack('Você precisa preencher algumas informações obrigatórias', true, 'warning', '#FFC125') + if (data.name) { + let errorName = ""; + data.name.map((err) => ( + errorName = errorName + err + " e " + )) + setErrorInName({ + error: true, + message: errorName + }) + } + if (data.weight) { + let weightError = ""; + data.weight.map((err) => ( + weightError = weightError + err + " e " + )) + setErrorInWeight({ + error: true, + message: weightError + }) + } } } setIsLoading(false) @@ -217,7 +221,7 @@ const NoteVarInputs = ({ match }) => { useEffect(() => { getRequest( - GetAData("scores", match.params.id), + GetAData("scores", id), (data, header) => { setIsLoaded(true); setName(data.name) diff --git a/src/Admin/Components/Components/MobileComponents/MobilePageHeader.js b/src/Admin/Components/Components/MobileComponents/MobilePageHeader.js index 99405165da5b74310a7c9f4fb7c794ce4fea3106..f3520c9f12319310eba1544dd60d551aa001a29e 100644 --- a/src/Admin/Components/Components/MobileComponents/MobilePageHeader.js +++ b/src/Admin/Components/Components/MobileComponents/MobilePageHeader.js @@ -16,7 +16,7 @@ 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"; +import React from "react"; import Paper from "@material-ui/core/Paper" import Grid from "@material-ui/core/Grid" import Button from "@material-ui/core/Button" diff --git a/src/Admin/Components/Components/Table.js b/src/Admin/Components/Components/Table.js index 5e74b53f158fc26f834a67b9aa2658721ef6e448..ddb7a377b4fea041f52c881835700312b7f8e6c8 100644 --- a/src/Admin/Components/Components/Table.js +++ b/src/Admin/Components/Components/Table.js @@ -23,23 +23,7 @@ const StyledTableCell = withStyles((theme) => ({ const useStyles = makeStyles({ table: { minWidth: 700, - width : "100%" - }, - root: { - minWidth: 275, - boxShadow: '2px 2px 1px #A9A9A9' - }, - bullet: { - display: 'inline-block', - margin: '0 2px', - transform: 'scale(0.8)', - }, - title: { - fontSize: 28, - fontWeight: "500" - }, - pos: { - marginBottom: 12, + width: "100%" }, }); @@ -53,12 +37,13 @@ const TableData = (props) => { <TableRow> { props.top.map((top, index) => ( - index === 0 ? + top === "ID" ? <StyledTableCell key={index}> <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}> {top} { - props.onIconPressed === undefined ? <div></div> : <IconButton onClick={props.onIconPressed} color='primary'> + props.onIconPressed && + <IconButton onClick={props.onIconPressed} color='primary'> <FilterListRoundedIcon style={{ color: 'white' }} /> </IconButton> } diff --git a/src/Admin/Pages/AdminLabelTabs/LabelTabs.js b/src/Admin/Pages/AdminLabelTabs/LabelTabs.js index eddb77be77677a6c655745ba407cff0219c8b02a..54b2a0fdf2dfd40bbef4f5d36ee15c9d6b95f486 100644 --- a/src/Admin/Pages/AdminLabelTabs/LabelTabs.js +++ b/src/Admin/Pages/AdminLabelTabs/LabelTabs.js @@ -18,70 +18,109 @@ along with Plataforma Integrada MEC. If not, see <http://www.gnu.org/licenses/> //This file has the labels of the left menu navigation from admin page +import React from "react"; +import HomeIcon from "@material-ui/icons/Home"; +import PeopleRoundedIcon from "@material-ui/icons/PeopleRounded"; +import ContactSupportRoundedIcon from "@material-ui/icons/ContactSupportRounded"; +import LanguageRoundedIcon from "@material-ui/icons/LanguageRounded"; +import AccountBalanceRoundedIcon from "@material-ui/icons/AccountBalanceRounded"; +import MenuBookRoundedIcon from "@material-ui/icons/MenuBookRounded"; +import StarRoundedIcon from "@material-ui/icons/StarRounded"; +import AccountCircleRoundedIcon from "@material-ui/icons/AccountCircleRounded"; +import TrendingUpRoundedIcon from "@material-ui/icons/TrendingUpRounded"; +import HelpRoundedIcon from "@material-ui/icons/HelpRounded"; +import CheckRoundedIcon from "@material-ui/icons/CheckRounded"; +import PersonRoundedIcon from "@material-ui/icons/PersonRounded"; +import BlockRoundedIcon from "@material-ui/icons/BlockRounded"; +import AnnouncementRoundedIcon from "@material-ui/icons/AnnouncementRounded"; +import EmailRoundedIcon from "@material-ui/icons/EmailRounded"; +import AllOutIcon from "@material-ui/icons/AllOut"; + +const orange = "#ff7f00"; +const pink = "#e81f4f"; +const purple = "#673ab7"; +const blue = "#00bcd4"; + const TabsItens = [ { - label: "Home", - href: '/admin/home' + label: "Home", + href: '/admin/home', + icon: <HomeIcon style={{ fill: orange }} />, }, { label: 'Coleções', href: '/admin/Collections', + icon: <PeopleRoundedIcon style={{ fill: pink }} /> }, { label: "Atividades", href: '/admin/activities', + icon: <AllOutIcon style={{ fill: purple }} />, }, { label: "Dúvidas da comunidade", - href: '/admin/CommunityQuestions' + href: '/admin/CommunityQuestions', + icon: <ContactSupportRoundedIcon style={{ fill: blue }} />, }, { label: "Instituições", - href: '/admin/intitutions' + href: '/admin/intitutions', + icon: <AccountBalanceRoundedIcon style={{ fill: orange }} />, }, { label: "Linguagens", href: '/admin/languages', + icon: <LanguageRoundedIcon style={{ fill: pink }} />, }, { label: "Objetos educacionais", href: "/admin/learningObjects", + icon: <MenuBookRoundedIcon style={{ fill: purple }} />, }, { label: "Rating", - href : '/admin/Ratings' + href: '/admin/Ratings', + icon: <StarRoundedIcon style={{ fill: blue }} />, }, { label: "Permissões do usuário", href: "/admin/permissions", + icon: <AccountCircleRoundedIcon style={{ fill: orange }} />, }, { - label: "Variáveis de nota", - href:'/admin/noteVars' + label: "Variáveis de nota", + href: '/admin/noteVars', + icon: <TrendingUpRoundedIcon style={{ fill: pink }} />, }, { label: "Perguntas curadoria", - href: "/admin/Questions" + href: "/admin/Questions", + icon: <HelpRoundedIcon style={{ fill: purple }} />, }, { label: "Aprovação de professores", - href: "/admin/users/teacher_requests" + href: "/admin/users/teacher_requests", + icon: <CheckRoundedIcon style={{ fill: blue }} />, }, { label: "Usuários", - href : "/admin/usersList" + href: "/admin/usersList", + icon: <PersonRoundedIcon style={{ fill: orange }} />, }, { label: "Usuários bloqueados", - href : "/admin/BlockedUsers" + href: "/admin/BlockedUsers", + icon: <BlockRoundedIcon style={{ fill: pink }} />, }, { label: "Denúncias", href: "/admin/complaints", + icon: <AnnouncementRoundedIcon style={{ fill: purple }} />, }, { label: "Enviar email", - href:'/admin/sendEmail/none' + href: '/admin/sendEmail', + icon: <EmailRoundedIcon style={{ fill: blue }} />, }, ]; diff --git a/src/Admin/Pages/Pages/SubPages/Activity.js b/src/Admin/Pages/Pages/SubPages/Activity.js index 25d622a09195fd25f1d3a2cbe65583b15f6c0e57..c87c1b25fd2b7ce07aac8c36adf11909a794cd9a 100644 --- a/src/Admin/Pages/Pages/SubPages/Activity.js +++ b/src/Admin/Pages/Pages/SubPages/Activity.js @@ -16,491 +16,414 @@ 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"; -import moment from 'moment'; +import React, { useEffect, useState } from "react" +import moment from 'moment' //imports from local files -import TableData from "../../../Components/Components/Table"; -import SnackBar from "../../../../Components/SnackbarComponent"; -import { Url } from "../../../Filters"; -import { getRequest } from '../../../../Components/HelperFunctions/getAxiosConfig'; -import LoadingSpinner from '../../../../Components/LoadingSpinner'; +import TableData from "../../../Components/Components/Table" +import SnackBar from "../../../../Components/SnackbarComponent" +import { Url } from "../../../Filters" +import { getRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' +import LoadingSpinner from '../../../../Components/LoadingSpinner' +import MobilePageHeader from '../../../Components/Components/MobileComponents/MobilePageHeader' +import PageHeader from '../../../Components/Components/PageHeader' //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 MenuItem from "@material-ui/core/MenuItem"; -import TableRow from "@material-ui/core/TableRow"; -import TextField from "@material-ui/core/TextField"; -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 FilterListRoundedIcon from "@material-ui/icons/FilterListRounded"; -import VisibilityIcon from "@material-ui/icons/Visibility"; -import AllOutIcon from "@material-ui/icons/AllOut"; +import { withStyles } from "@material-ui/core/styles" +import TableBody from "@material-ui/core/TableBody" +import TableCell from "@material-ui/core/TableCell" +import MenuItem from "@material-ui/core/MenuItem" +import TableRow from "@material-ui/core/TableRow" +import TextField from "@material-ui/core/TextField" +import IconButton from "@material-ui/core/IconButton" +import { Button, Paper } 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 FilterListRoundedIcon from "@material-ui/icons/FilterListRounded" +import VisibilityIcon from "@material-ui/icons/Visibility" +import AllOutIcon from "@material-ui/icons/AllOut" //routers -import { Link } from 'react-router-dom'; +import { Link } from 'react-router-dom' import MobileList from "../../../Components/Components/MobileComponents/SimpleList" import styled from "styled-components" -import PageHeader from "../../../Components/Components/PageHeader" - -let currPage = 0; const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + "&:nth-of-type(odd)": { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const Activity = () => { - const ADD_ONE_LENGHT = [""]; - const TOP_LABELS = [ - "CRIADO EM", - "DONO(A)", - "ATIVIDADE", - "PRIVACIDADE", - "VISUALIZAR", - ]; //Labels from Table - const WINDOW_WIDTH = window.innerWidth - - 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 - - const [showFilter, setShowFilter] = useState(false); - - const [option, setOption] = useState("Todos os usuários"); //labels of the text field 'to' - - const [snackInfo, setSnackInfo] = useState({ - message: "", - icon: "", - open: false, - color: "", + const ADD_ONE_LENGHT = [""]; + const TOP_LABELS = [ + "CRIADO EM", + "DONO(A)", + "ATIVIDADE", + "PRIVACIDADE", + "VISUALIZAR", + ]; //Labels from Table + const WINDOW_WIDTH = window.innerWidth + + 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 [showFilter, setShowFilter] = useState(false); + const [option, setOption] = useState(); //labels of the text field 'to' + const [currPage, setCurrPage] = useState(0) + + const [snackInfo, setSnackInfo] = useState({ + message: "", + icon: "", + open: false, + color: "", + }); + + const options = [ + { + name: "private", + value: "Privado", + }, + { + name: "public", + value: "Público", + }, + ]; + + //handle snack info + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color, }); - - const options = [ - { - value: "private", - label: "Privado", - }, - { - value: "public", - label: "Público", - }, - ]; - - //handle snack info - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color, - }); - }; - - //handle load more items - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true); - getRequest(api, - (data, header) => { - const arrData = [...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)); - } - setIsLoadingMoreItems(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoadingMoreItems(false); - } - ) - }; - - // handle update list data - const UpdateHandler = async (api) => { - setIsUpdating(true); - getRequest(api, - (data, header) => { - HandleSnack( - "A lista de dados foi atualizada", - true, - "success", - "#228B22" - ); - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)) - setIsUpdating(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsUpdating(false); - } - ) - }; - - const handleChange = (e) => { - setIsLoaded(false) - const value = e.target.value; - currPage = 0; - setOption(value); - - getRequest(Url("activities", `"privacy" : "${value}"`, `${currPage}`, "DESC"), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); - setIsLoaded(true); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - } - ) - }; - - const DisplayDate = (date) => { - const convertedData = moment.utc(date); - return moment(convertedData) - .format("LLL") - .toString(); - }; - - //getting data from server - useEffect(() => { - getRequest( - Url("activities", "", `${currPage}`, "DESC"), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - setIsLoaded(true); - setError(false); + }; + + const handleChange = (e) => { + setOption(e.target.value); + }; + + const DisplayDate = (date) => { + const convertedData = moment.utc(date); + return moment(convertedData) + .format("LLL") + .toString(); + }; + + const buildUrl = (privacyOpt) => { + if (privacyOpt) + return Url("activities", `"privacy" : "${privacyOpt}"`, currPage, "DESC") + + return Url("activities", "", currPage, "DESC") + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + buildUrl(option), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') + } else { + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } + } + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, option]) + + useEffect(() => { + setOption() + setCurrPage(0) + }, [showFilter]) + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." /> + } else { + + if (WINDOW_WIDTH <= 820) { + return <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) + } + /> + + <MobilePageHeader + title="Atividades" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - setError(true); + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> } - ) - }, []); - - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." /> - } else { - - if (WINDOW_WIDTH <= 758) { - 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={12}> - <Typography variant="h4">Atividades</Typography> - </Grid> - <Grid - item - xs={12} - > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0; - UpdateHandler( - Url("activities", "", `${currPage}`, "DESC") - ); - }} - startIcon={<UpdateRoundedIcon />} - > - {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={() => { - setShowFilter(!showFilter); - }} - startIcon={<FilterListRoundedIcon />} - > - Filtrar - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - - {showFilter ? ( - <> - <div style={{ height: "1em" }}></div> - - <div style={{ alignSelf: "flex-end" }}> - <TextField - select={true} - label="Filtro" - value={option ? option : ""} - onChange={handleChange} - helperText="Por favor, selecione uma das opções" - > - {options.map((option, index) => ( - <MenuItem - key={option.value} - value={option.value} - > - {option.label} - </MenuItem> - ))} - </TextField> - </div> - </> - ) : null} - </Paper> - - <div style={{ height: "2em" }}></div> - - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++; - if (showFilter) { - LoadMoreItens( - Url("activities", `"privacy" : "${option}"`, `${currPage}`, "DESC") - ); - } else { - LoadMoreItens( - Url("activities", "", `${currPage}`, "DESC") - ); - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.id} - subtitle={row.privacy} - backColor={"#673ab7"} - avatar={<AllOutIcon />} - href={`/admin/activity/${row.id}`} - reset={() => { - currPage = 0; - }} - data={ - [ - { - title: "Dono(a)", - subtitle: row.owner ? row.owner.name : "Sem dados" - - }, - { - title: "Criado em", - subtitle: DisplayDate(row.created_at) - }, - { - title: "Atividade", - subtitle: row.activity - } - ] - } - /> - <div style={{ height: "0.5em" }} /> - </> - ) - )} + ]} + > + {showFilter ? ( + <> + <div style={{ height: "1em" }}></div> + + <div style={{ alignSelf: "flex-end" }}> + <TextField + select + label="Filtro" + value={option ? option : ""} + onChange={handleChange} + helperText="Por favor, selecione uma das opções" + > + {options.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </div> </> - } - else { - return <> - <SnackBar - severity={snackInfo.icon} - text={snackInfo.message} - snackbarOpen={snackInfo.open} - color={snackInfo.color} - handleClose={() => - setSnackInfo({ - message: "", - icon: "", - open: false, - color: "", - }) - } + ) : null} + </MobilePageHeader> + + <div style={{ height: "2em" }}></div> + + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton + key={new Date().toISOString() + row.created_at} + > + <Button + key={new Date().toISOString() + row.created_at} + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledDivButton> + ) : ( + <> + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.id} + subtitle={row.privacy} + backColor={"#673ab7"} + avatar={<AllOutIcon />} + href={`/admin/activity?activity=${row.id}`} + reset={() => { + + }} + data={ + [ + { + title: "Dono(a)", + subtitle: row.owner ? row.owner.name : "Sem dados" + + }, + { + title: "Criado em", + subtitle: DisplayDate(row.created_at) + }, + { + title: "Atividade", + subtitle: row.activity + } + ] + } /> - <PageHeader - title="Atividades" - actions={[ - { - name: "Atualizar", - isLoading: isUpdating, - func: () => { - currPage = 0; - UpdateHandler( - Url("activities", "", `${currPage}`, "DESC") - ); - }, - icon: <UpdateRoundedIcon /> - }, - { - name: "Filtrar", - isLoading: false, - func: () => { - setShowFilter(!showFilter); - }, - icon: <FilterListRoundedIcon /> - } - ]} + <div style={{ height: "0.5em" }} /> + </> + ) + )} + </> + } + else { + return <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) + } + /> + <PageHeader + title="Atividades" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + } + ]} + > + {showFilter ? ( + <> + <div style={{ height: "1em" }}></div> + + <div style={{ alignSelf: "flex-end" }}> + <TextField + select + label="Filtro" + value={option ? option : ""} + onChange={handleChange} + helperText="Por favor, selecione uma das opções" > - {showFilter ? ( - <> - <div style={{ height: "1em" }}></div> - - <div style={{ alignSelf: "flex-end" }}> - <TextField - select - label="Filtro" - value={option ? option : ""} - onChange={handleChange} - helperText="Por favor, selecione uma das opções" - > - {options.map((option, index) => ( - <MenuItem - key={option.value} - value={option.value} - > - {option.label} - </MenuItem> - ))} - </TextField> - </div> - </> - ) : null} - </PageHeader> - - <div style={{ height: "2em" }}></div> - - <TableData top={TOP_LABELS}> - <TableBody> - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledTableRow key={index} style={{ padding: "1em" }}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++; - if (showFilter) { - LoadMoreItens( - Url("activities", `"privacy" : "${option}"`, `${currPage}`, "DESC") - ); - } else { - LoadMoreItens( - Url("activities", "", `${currPage}`, "DESC") - ); - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledTableCell> - </StyledTableRow> - ) : ( - <StyledTableRow key={index}> - <StyledTableCell component="th" scope="row"> - {DisplayDate(row.created_at)} - </StyledTableCell> - <StyledTableCell align="right"> - { - row.owner ? row.owner.name : "" - } - </StyledTableCell> - <StyledTableCell align="right"> - {row.activity} - </StyledTableCell> - <StyledTableCell align="right">{row.privacy}</StyledTableCell> - <StyledTableCell align="right"> - <Link to={`/admin/activity/${row.id}`}> - <IconButton onClick={() => { currPage = 0 }}> - <VisibilityIcon style={{ fill: "#00bcd4" }} /> - </IconButton> - </Link> - </StyledTableCell> - </StyledTableRow> - ) - )} - </TableBody> - </TableData> + {options.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </div> </> - } + ) : null} + </PageHeader> + + <div style={{ height: "2em" }}></div> + + <TableData top={TOP_LABELS}> + <TableBody> + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledTableRow key={new Date().toISOString() + row.created_at} style={{ padding: "1em" }}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledTableCell> + </StyledTableRow> + ) : ( + <StyledTableRow key={new Date().toISOString() + index}> + <StyledTableCell component="th" scope="row"> + {DisplayDate(row.created_at)} + </StyledTableCell> + <StyledTableCell align="right"> + { + row.owner ? row.owner.name : "" + } + </StyledTableCell> + <StyledTableCell align="right"> + {row.activity} + </StyledTableCell> + <StyledTableCell align="right">{row.privacy}</StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/activity?activity=${row.id}`}> + <IconButton> + <VisibilityIcon style={{ fill: "#00bcd4" }} /> + </IconButton> + </Link> + </StyledTableCell> + </StyledTableRow> + ) + )} + </TableBody> + </TableData> + </> } + } }; + + export default Activity; const StyledDivButton = styled(Paper)` diff --git a/src/Admin/Pages/Pages/SubPages/AproveTeacher.js b/src/Admin/Pages/Pages/SubPages/AproveTeacher.js index df9cbfff609dadd19a830e7ac6f23fca0901a1aa..b8f7203ab10a3c0dfbb9ee471b47b77acd2ffe35 100644 --- a/src/Admin/Pages/Pages/SubPages/AproveTeacher.js +++ b/src/Admin/Pages/Pages/SubPages/AproveTeacher.js @@ -16,18 +16,23 @@ 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, useContext } from "react"; +import React, { useEffect, useState } from "react"; import moment from "moment"; +import styled from "styled-components"; //imports from local files import TableData from "../../../Components/Components/Table"; import SnackBar from "../../../../Components/SnackbarComponent"; import { Url } from "../../../Filters"; -import { Store } from "../../../../Store"; import LoadingSpinner from "../../../../Components/LoadingSpinner"; import { - getRequest, - postRequest, + getRequest, + postRequest, } from "../../../../Components/HelperFunctions/getAxiosConfig"; +import MobileList from "../../../Components/Components/MobileComponents/SimpleList"; +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader"; +import PageHeader from "../../../Components/Components/PageHeader"; +import { apiDomain } from '../../../../env'; +import noAvatar from "../../../../img/default_profile.png" //imports from material ui import { withStyles } from "@material-ui/core/styles"; import TableBody from "@material-ui/core/TableBody"; @@ -36,7 +41,7 @@ import MenuItem from "@material-ui/core/MenuItem"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; import IconButton from "@material-ui/core/IconButton"; -import { Button, Typography, Paper, Grid } from "@material-ui/core"; +import { Button, 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"; @@ -44,862 +49,716 @@ import FilterListRoundedIcon from "@material-ui/icons/FilterListRounded"; import VisibilityIcon from "@material-ui/icons/Visibility"; import CheckRoundedIcon from "@material-ui/icons/CheckRounded"; import CloseRoundedIcon from "@material-ui/icons/CloseRounded"; +import EmailRoundedIcon from '@material-ui/icons/EmailRounded'; //routers import { Link } from "react-router-dom"; -import Unauthorized from "../../../Components/Components/Unauthorized"; -import styled from "styled-components"; -import MobileList from "../../../Components/Components/MobileComponents/SimpleList"; -import { apiDomain } from '../../../../env'; -import noAvatar from "../../../../img/default_profile.png"; -import EmailRoundedIcon from '@material-ui/icons/EmailRounded'; -let currPage = 0; -let currStateFilter = "requested"; -let currNameFilter = ""; -let currEmailFilter = ""; const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + "&:nth-of-type(odd)": { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const AproveTeacher = () => { - const { state } = useContext(Store); - const WINDOW_WIDTH = window.innerWidth; - - const ADD_ONE_LENGHT = [""]; - const TOP_LABELS = [ - "ESTADO DO PEDIDO", - "ID", - "NOME", - "EMAIL", - "PEDIDO EM(MM/DD/YYYY)", - "VISUALIZAR", - "AÇÕES", - ]; //Labels from Table - - 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 - - const [showFilter, setShowFilter] = useState(false); - - const [option, setOption] = useState("requested"); - const [name, setName] = useState(""); - const [email, setEmail] = useState(""); - - const [snackInfo, setSnackInfo] = useState({ - message: "", - icon: "", - open: false, - color: "", + const WINDOW_WIDTH = window.innerWidth + const ADD_ONE_LENGHT = [""]; + const TOP_LABELS = [ + "ESTADO DO PEDIDO", + "ID", + "NOME", + "EMAIL", + "PEDIDO EM(MM/DD/YYYY)", + "VISUALIZAR", + "AÇÕES", + ]; //Labels from Table + + const [invertList, setInvertList] = useState(false) + 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 [currPage, setCurrPage] = useState(0) + const [showFilter, setShowFilter] = useState(false); + + const [option, setOption] = useState("requested"); + const [name, setName] = useState(""); + const [nameValue, setNameValue] = useState("") + const [email, setEmail] = useState(""); + const [emailValue, setEmailValue] = useState("") + + const [snackInfo, setSnackInfo] = useState({ + message: "", + icon: "", + open: false, + color: "", + }); + + const StateOptions = [ + { name: "requested", value: "Pendente" }, + { name: "accepted", value: "Aceito" }, + { name: "rejected", value: "Rejeitado" }, + ]; + + //handle snack info + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color, }); - - const StateOptions = [ - { id: "requested", name: "Pendente" }, - { id: "accepted", name: "Aceito" }, - { id: "rejected", name: "Rejeitado" }, - ]; - - //handle snack info - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color, - }); - }; - - const CheckUserPermission = () => { - let canUserEdit = false; - - if (state.userIsLoggedIn) { - const roles = [...state.currentUser.roles]; - for (let i = 0; i < roles.length; i++) - if (roles[i].name === "admin" || roles[i].name === "editor") - canUserEdit = true; - } else { - canUserEdit = false; - } - - return canUserEdit; - }; - - //handle load more items - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true); - getRequest( - api, - (data, header) => { - const arrData = [...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)); - } - setIsLoadingMoreItems(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoadingMoreItems(false); - } + }; + + const handleChange = (e, type) => { + const value = e.target.value; + setOption(value); + }; + + const NameHandler = (e) => { + setNameValue(e.target.value) + }; + + const EmailHandler = (e) => { + setEmailValue(e.target.value) + }; + + const removeItemFromList = (itemId) => { + let index = -1; + for (let i = 0; i < items.length; i++) { + const element = items[i]; + if (element.id === itemId) { + index = i + break + } + } + if (index !== -1) { + const cpyItems = [...items] + cpyItems.splice(index, 1) + setItems(cpyItems) + } + } + + const ComplaintStatus = (status) => { + switch (status) { + case "accepted": + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#228B22", + fontWeight: "500", + color: "#FFFAFA", + }} + > + ACEITO + </Paper> ); - }; - - // handle update list data - const UpdateHandler = async (api) => { - setIsUpdating(true); - getRequest( - api, - (data, header) => { - HandleSnack( - "A lista de dados foi atualizada", - true, - "success", - "#228B22" - ); - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - setIsUpdating(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsUpdating(false); - } + case "requested": + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#FF8C00", + fontWeight: "500", + color: "#FFFAFA", + }} + > + PENDENTE + </Paper> ); - }; - - const handleChange = (e, type) => { - const value = e.target.value; - setOption(value); - }; - - const ApplyFilter = (id, type) => { - currStateFilter = id; - currPage = 0; - getRequest( - Url( - "users", - `"submitter_request":"${currStateFilter}","name":"${currNameFilter}","email":"${email}"`, - `${currPage}`, - "DESC" - ), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); - setIsLoaded(true); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - } + case "rejected": + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#FA8072", + fontWeight: "500", + color: "#FFFAFA", + }} + > + Rejeitado + </Paper> ); - }; - - const NameHandler = (e) => { - currPage = 0; - currNameFilter = e.target.value; - setName(currNameFilter); - getRequest( - Url( - "users", - `"submitter_request":"${currStateFilter}","name":"${currNameFilter}","email":"${email}"`, - `${currPage}`, - "DESC" - ), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); - setIsLoaded(true); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - } + default: + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#797D7F ", + fontWeight: "500", + color: "#FFFAFA", + }} + > + Não requisitado + </Paper> ); + } + }; + + const DisplayDate = (date) => { + const convertedData = moment.utc(date); + return moment(convertedData) + .format("LLL") + .toString(); + }; + + const handleAprove = (userId, userName) => { + const url = `/users/${userId}/add_teacher`; + const body = { + approves: true, }; - - const EmailHandler = (e) => { - currPage = 0; - currEmailFilter = e.target.value; - setEmail(currEmailFilter); - getRequest( - Url( - "users", - `"submitter_request":"${currStateFilter}","name":"${currNameFilter}","email":"${currEmailFilter}"`, - `${currPage}`, - "DESC" - ), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); - setIsLoaded(true); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - } - ); - }; - - const ComplaintStatus = (status) => { - switch (status) { - case "accepted": - return ( - <Paper - style={{ - textAlign: "center", - padding: "0.5em", - backgroundColor: "#228B22", - fontWeight: "500", - color: "#FFFAFA", - }} - > - ACEITO - </Paper> - ); - case "requested": - return ( - <Paper - style={{ - textAlign: "center", - padding: "0.5em", - backgroundColor: "#FF8C00", - fontWeight: "500", - color: "#FFFAFA", - }} - > - PENDENTE - </Paper> - ); - case "rejected": - return ( - <Paper - style={{ - textAlign: "center", - padding: "0.5em", - backgroundColor: "#FA8072", - fontWeight: "500", - color: "#FFFAFA", - }} - > - Rejeitado - </Paper> - ); - default: - return ( - <Paper - style={{ - textAlign: "center", - padding: "0.5em", - backgroundColor: "#797D7F ", - fontWeight: "500", - color: "#FFFAFA", - }} - > - Não requisitado - </Paper> - ); + postRequest( + url, + body, + (data) => { + if (data.errors) HandleSnack("Erro!", true, "warning", "#FA8072"); + else { + HandleSnack( + `${userName} aceito como professor!`, + true, + "success", + "#228B22" + ); + setCurrPage(0) + removeItemFromList(userId) } + }, + (error) => { + HandleSnack("Erro!", true, "warning", "#FA8072"); + } + ); + }; + + const handleReject = (userId, userName) => { + const url = `/users/${userId}/add_teacher`; + const body = { + approves: false, }; - - const DisplayDate = (date) => { - const convertedData = moment.utc(date); - return moment(convertedData) - .format("LLL") - .toString(); - }; - - const handleAprove = (userId, userName) => { - const url = `/users/${userId}/add_teacher`; - const body = { - approves: true, - }; - postRequest( - url, - body, - (data) => { - if (data.errors) HandleSnack("Erro!", true, "warning", "#FA8072"); - else { - HandleSnack( - `${userName} aceito como professor!`, - true, - "success", - "#228B22" - ); - currPage = 0; - UpdateHandler( - Url( - "users", - `"submitter_request":"${currStateFilter}","name":"${currNameFilter}","email":"${currEmailFilter}"`, - `${currPage}`, - "DESC" - ) - ); - } - }, - (error) => { - HandleSnack("Erro!", true, "warning", "#FA8072"); - } - ); - }; - - const handleReject = (userId, userName) => { - const url = `/users/${userId}/add_teacher`; - const body = { - approves: false, - }; - postRequest( - url, - body, - (data) => { - if (data.errors) HandleSnack("Erro!", true, "warning", "#FA8072"); - else { - HandleSnack( - `${userName} rejeitado como professor!`, - true, - "success", - "#228B22" - ); - currPage = 0; - UpdateHandler( - Url( - "users", - `"submitter_request":"${currStateFilter}","name":"${currNameFilter}","email":"${currEmailFilter}"`, - `${currPage}`, - "DESC" - ) - ); - } - }, - (error) => { - HandleSnack("Erro!", true, "warning", "#FA8072"); - } - ); - }; - - //getting data from server - useEffect(() => { - getRequest( - Url( - "users", - `"submitter_request":"${currStateFilter}","name":"${currNameFilter}","email":"${currEmailFilter}"`, - `${currPage}`, - "DESC" - ), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - setIsLoaded(true); - setError(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - setError(true); + postRequest( + url, + body, + (data) => { + if (data.errors) HandleSnack("Erro!", true, "warning", "#FA8072"); + else { + HandleSnack( + `${userName} rejeitado como professor!`, + true, + "success", + "#228B22" + ); + setCurrPage(0) + removeItemFromList(userId) + } + }, + (error) => { + HandleSnack("Erro!", true, "warning", "#FA8072"); + } + ); + }; + + const cleanArrayAndInvert = () => { + setInvertList(!invertList) + setCurrPage(0) + setItems([]) + } + + const buildUrl = (email, submitter_request, name, direction) => { + if (email && submitter_request && name) + return Url("users", `"submitter_request" : "${submitter_request}", "email" : "${email}", "name" : "${name}"`, currPage, direction) + + else if (email && name) + return Url("users", `"email" : "${email}", "name" : "${name}"`, currPage, direction) + else if (email && submitter_request) + return Url("users", `"email" : "${email}", "submitter_request" : "${submitter_request}"`, currPage, direction) + else if (name && submitter_request) + return Url("users", `"name" : "${name}", "submitter_request" : "${submitter_request}"`, currPage, direction) + + else if (email) + return Url("users", `"email" : "${email}"`, currPage, direction) + else if (submitter_request) + return Url("users", `"submitter_request" : "${submitter_request}"`, currPage, direction) + else if (name) + return Url("users", `"name" : ${name}`, currPage, direction) + else + return Url("users", "", currPage, direction) + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + buildUrl(email, option, name, invertList ? "ASC" : "DESC"), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') + } else { + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } + } + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, option, email, name, invertList]) + + useEffect(() => { + setOption("requested") + setName("") + setNameValue("") + setEmail("") + setEmailValue("") + }, [showFilter]) + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." />; + } else { + if (WINDOW_WIDTH <= 1130) { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) } - ); - }, []); - - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." />; - } else if (CheckUserPermission()) { - if (WINDOW_WIDTH <= 1075) { - return ( + /> + <MobilePageHeader + title="Aprovação de professores" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + }, + { + name: "Inverter lista", + isLoading: false, + func: () => { + cleanArrayAndInvert() + }, + } + ]} + > + {showFilter ? ( + <> + <div style={{ height: "1em" }}></div> + {showFilter ? ( + <Grid + container + direction="row" + justify="space-between" + alignItems="center" + alignContent="flex-end" + spacing={3} + xs={12} + > + <Grid item> + <TextField + select + label="Estado" + value={option ? option : ""} + onChange={handleChange} + helperText="Por favor, selecione uma das opções" + > + {StateOptions.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </Grid> + <Grid item> + <TextField + label="Nome" + onChange={NameHandler} + value={nameValue} + onBlur={(event) => { setName(event.target.value) }} + helperText="Retire o foco do campo de texto ao terminar de digitar" + /> + </Grid> + <Grid item> + <TextField + label="Email" + onChange={EmailHandler} + value={emailValue} + onBlur={(event) => { setEmail(event.target.value) }} + helperText="Retire o foco do campo de texto ao terminar de digitar" + /> + </Grid> + </Grid> + ) : null} + </> + ) : null} + </MobilePageHeader> + + <div style={{ height: "2em" }}></div> + + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton> + <Button + key={new Date().toISOString() + row.created_at} + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledDivButton> + ) : ( <> - <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={12}> - <Typography variant="h4"> - Lista de pedidos para professores - </Typography> - </Grid> - - <Grid item xs={12}> - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0; - UpdateHandler( - Url( - "users", - `"submitter_request":"${currStateFilter}","name":"${currNameFilter}","email":"${currEmailFilter}"`, - `${currPage}`, - "DESC" - ) - ); - }} - startIcon={<UpdateRoundedIcon />} - > - {isUpdating ? ( - <CircularProgress size={24} /> - ) : ( - "Atualizar" - )} - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={() => { - setShowFilter(!showFilter); - }} - startIcon={<FilterListRoundedIcon />} - > - Filtrar - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - - {showFilter ? ( - <Grid - container - direction="row" - justify="space-between" - alignItems="center" - alignContent="flex-end" - spacing={3} - xs={12} + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.name} + subtitle={row.id} + backColor={"#00bcd4"} + avatar={ + <img + src={row.avatar ? apiDomain + row.avatar : noAvatar} + alt="user avatar" + style={{ + height: "100%", + width: "100%", + borderRadius: "50%", + }} + /> + } + href={`/admin/user?id=${row.id}`} + reset={() => { + + }} + data={[ + { + title: "Email", + subtitle: row.email ? + <Link to={`/admin/sendEmail?email=${row.email}`} style={{ textDecoration: 'none' }}> + <Button + variant='text' + color='primary' + startIcon={<EmailRoundedIcon />} > - <Grid item> - <TextField - select - label="Estado" - value={option ? option : ""} - onChange={handleChange} - helperText="Por favor, selecione uma das opções" - > - {StateOptions.map((option, index) => ( - <MenuItem - key={option.id} - value={option.name} - name={option.id} - onClick={() => - ApplyFilter(option.id, "submitter_request") - } - > - {option.name} - </MenuItem> - ))} - </TextField> - </Grid> - <Grid item> - <TextField label="Nome" onChange={NameHandler} value={name} /> - </Grid> - <Grid item> - <TextField - label="Email" - onChange={EmailHandler} - value={email} - /> - </Grid> - </Grid> - ) : null} - </Paper> - - <div style={{ height: "2em" }}></div> - - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++; - LoadMoreItens( - Url( - "users", - `"submitter_request":"${currStateFilter}","name":"${currNameFilter}","email":"${currEmailFilter}"`, - `${currPage}`, - "DESC" - ) - ); - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.name} - subtitle={row.id} - backColor={"#00bcd4"} - avatar={ - <img - src={row.avatar ? apiDomain + row.avatar : noAvatar} - alt="user avatar" - style={{ - height: "100%", - width: "100%", - borderRadius: "50%", - }} - /> - } - href={`/admin/user/${row.id}`} - reset={() => { - currPage = 0; - currNameFilter = ""; - currEmailFilter = ""; - }} - data={[ - { - title: "Email", - subtitle: row.email ? - <Link to={`/admin/sendEmail/${row.email}`} style={{ textDecoration: 'none' }}> - <Button - variant='text' - color='primary' - startIcon={<EmailRoundedIcon />} - > - {row.email} - </Button> - </Link> : null - - }, - { - title: "Pedido em", - subtitle: DisplayDate(row.created_at), - }, - { - title: "Situação do pedido", - subtitle: ComplaintStatus(row.submitter_request), - }, - { - title: "Ações rápidas", - subtitle: <> - <Button - variant="contained" - color="secondary" - style={{ width: "100%" }} - disabled={ - row.submitter_request === "requested" ? false : true - } - startIcon={ - <CloseRoundedIcon style={{ fill: "#FFFAFA" }} /> - } - onClick={() => { - handleReject(row.id, row.name); - }} - > - Recusar + {row.email} + </Button> + </Link> : null + + }, + { + title: "Pedido em", + subtitle: DisplayDate(row.created_at), + }, + { + title: "Situação do pedido", + subtitle: ComplaintStatus(row.submitter_request), + }, + { + title: "Ações rápidas", + subtitle: <> + <Button + variant="contained" + color="secondary" + style={{ width: "100%" }} + disabled={ + row.submitter_request === "requested" ? false : true + } + startIcon={ + <CloseRoundedIcon style={{ fill: "#FFFAFA" }} /> + } + onClick={() => { + handleReject(row.id, row.name); + }} + > + Recusar </Button> - <div style={{ height: "0.5em" }} /> - <Button - variant="contained" - color="primary" - style={{ width: "100%" }} - disabled={ - row.submitter_request === "requested" ? false : true - } - startIcon={ - <CheckRoundedIcon style={{ fill: "#FFFAFA" }} /> - } - onClick={() => { - handleAprove(row.id, row.name); - }} - > - Aceitar + <div style={{ height: "0.5em" }} /> + <Button + variant="contained" + color="primary" + style={{ width: "100%" }} + disabled={ + row.submitter_request === "requested" ? false : true + } + startIcon={ + <CheckRoundedIcon style={{ fill: "#FFFAFA" }} /> + } + onClick={() => { + handleAprove(row.id, row.name); + }} + > + Aceitar </Button> - </> - } - ]} - /> - <div style={{ height: "0.5em" }} /> - </> - ) - )} + </> + } + ]} + /> + <div style={{ height: "0.5em" }} /> </> - ); - } 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"> - Lista de pedidos para professores - </Typography> - </Grid> - - <Grid item xs={6}> - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0; - UpdateHandler( - Url( - "users", - `"submitter_request":"${currStateFilter}","name":"${currNameFilter}","email":"${currEmailFilter}"`, - `${currPage}`, - "DESC" - ) - ); - }} - startIcon={<UpdateRoundedIcon />} - > - {isUpdating ? ( - <CircularProgress size={24} /> - ) : ( - "Atualizar" - )} - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={() => { - setShowFilter(!showFilter); - }} - startIcon={<FilterListRoundedIcon />} - > - Filtrar - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - - {showFilter ? ( - <Grid - container - direction="row" - justify="space-between" - alignItems="center" - alignContent="flex-end" - spacing={3} - xs={12} - > - <Grid item> - <TextField - select - label="Estado" - value={option ? option : ""} - onChange={handleChange} - helperText="Por favor, selecione uma das opções" - > - {StateOptions.map((option, index) => ( - <MenuItem - key={option.id} - value={option.name} - name={option.id} - onClick={() => - ApplyFilter(option.id, "submitter_request") - } - > - {option.name} - </MenuItem> - ))} - </TextField> - </Grid> - <Grid item> - <TextField label="Nome" onChange={NameHandler} value={name} /> - </Grid> - <Grid item> - <TextField - label="Email" - onChange={EmailHandler} - value={email} - /> - </Grid> - </Grid> - ) : null} - </Paper> - - <div style={{ height: "2em" }}></div> - - <Grid xs={12} container> - <TableData top={TOP_LABELS}> - <TableBody> - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledTableRow key={index}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++; - LoadMoreItens( - Url( - "users", - `"submitter_request":"${currStateFilter}","name":"${currNameFilter}","email":"${currEmailFilter}"`, - `${currPage}`, - "DESC" - ) - ); - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledTableCell> - </StyledTableRow> - ) : ( - <StyledTableRow - key={index} - style={{ flex: 1, width: "100%" }} - > - <StyledTableCell component="th" scope="row"> - {ComplaintStatus(row.submitter_request)} - </StyledTableCell> - <StyledTableCell align="right">{row.id}</StyledTableCell> - <StyledTableCell align="right"> - {row.name} - </StyledTableCell> - <StyledTableCell align="right"> - {row.email} - </StyledTableCell> - <StyledTableCell align="right"> - {DisplayDate(row.created_at)} - </StyledTableCell> - <StyledTableCell align="right"> - <Link to={`/admin/user/${row.id}`}> - <IconButton - onClick={() => { - currPage = 0; - currNameFilter = ""; - currEmailFilter = ""; - }} - > - <VisibilityIcon style={{ fill: "#00bcd4" }} /> - </IconButton> - </Link> - </StyledTableCell> - <StyledTableCell align="right"> - <Button - variant="contained" - color="secondary" - style={{ width: "100%" }} - disabled={ - row.submitter_request === "requested" ? false : true - } - startIcon={ - <CloseRoundedIcon style={{ fill: "#FFFAFA" }} /> - } - onClick={() => { - handleReject(row.id, row.name); - }} - > - Recusar + ) + )} + </> + ); + } else { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) + } + /> + + <PageHeader + title="Aprovação de professores" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + } + ]} + > + {showFilter ? ( + <> + <div style={{ height: "1em" }}></div> + {showFilter ? ( + <Grid + container + direction="row" + justify="space-between" + alignItems="center" + alignContent="flex-end" + spacing={3} + xs={12} + > + <Grid item> + <TextField + select + label="Estado" + value={option ? option : ""} + onChange={handleChange} + helperText="Por favor, selecione uma das opções" + > + {StateOptions.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </Grid> + <Grid item> + <TextField + label="Nome" + onChange={NameHandler} + value={nameValue} + onBlur={(event) => { setName(event.target.value) }} + helperText="Retire o foco do campo de texto ao terminar de digitar" + /> + </Grid> + <Grid item> + <TextField + label="Email" + onChange={EmailHandler} + value={emailValue} + onBlur={(event) => { setEmail(event.target.value) }} + helperText="Retire o foco do campo de texto ao terminar de digitar" + /> + </Grid> + </Grid> + ) : null} + </> + ) : null} + </PageHeader> + + <div style={{ height: "2em" }}></div> + + <Grid xs={12} container> + <TableData + top={TOP_LABELS} + onIconPressed={cleanArrayAndInvert} + > + <TableBody> + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledTableRow key={new Date().toISOString() + row.created_at}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledTableCell> + </StyledTableRow> + ) : ( + <StyledTableRow + key={new Date().toISOString() + index} + style={{ flex: 1, width: "100%" }} + > + <StyledTableCell component="th" scope="row"> + {ComplaintStatus(row.submitter_request)} + </StyledTableCell> + <StyledTableCell align="right">{row.id}</StyledTableCell> + <StyledTableCell align="right"> + {row.name} + </StyledTableCell> + <StyledTableCell align="right"> + {row.email} + </StyledTableCell> + <StyledTableCell align="right"> + {DisplayDate(row.created_at)} + </StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/user?id=${row.id}`}> + <IconButton> + <VisibilityIcon style={{ fill: "#00bcd4" }} /> + </IconButton> + </Link> + </StyledTableCell> + <StyledTableCell align="right"> + <Button + variant="contained" + color="secondary" + style={{ width: "100%" }} + disabled={ + row.submitter_request === "requested" ? false : true + } + startIcon={ + <CloseRoundedIcon style={{ fill: "#FFFAFA" }} /> + } + onClick={() => { + handleReject(row.id, row.name); + }} + > + Recusar </Button> - <div style={{ height: "0.5em" }} /> - <Button - variant="contained" - color="primary" - style={{ width: "100%" }} - disabled={ - row.submitter_request === "requested" ? false : true - } - startIcon={ - <CheckRoundedIcon style={{ fill: "#FFFAFA" }} /> - } - onClick={() => { - handleAprove(row.id, row.name); - }} - > - Aceitar + <div style={{ height: "0.5em" }} /> + <Button + variant="contained" + color="primary" + style={{ width: "100%" }} + disabled={ + row.submitter_request === "requested" ? false : true + } + startIcon={ + <CheckRoundedIcon style={{ fill: "#FFFAFA" }} /> + } + onClick={() => { + handleAprove(row.id, row.name); + }} + > + Aceitar </Button> - </StyledTableCell> - </StyledTableRow> - ) - )} - </TableBody> - </TableData> - </Grid> - </> - ); - } - } else return <Unauthorized />; + </StyledTableCell> + </StyledTableRow> + ) + )} + </TableBody> + </TableData> + </Grid> + </> + ); + } + } }; export default AproveTeacher; diff --git a/src/Admin/Pages/Pages/SubPages/BlockedUsers.js b/src/Admin/Pages/Pages/SubPages/BlockedUsers.js index c89b08bdbc5642225bb3bd45a0eb595db831964b..84a4419b44d2cbb0a7c3d485b9c0b840fabd2014 100644 --- a/src/Admin/Pages/Pages/SubPages/BlockedUsers.js +++ b/src/Admin/Pages/Pages/SubPages/BlockedUsers.js @@ -17,6 +17,7 @@ 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'; import moment from "moment"; +import styled from "styled-components" //Material ui componets import { withStyles } from '@material-ui/core/styles'; import TableBody from '@material-ui/core/TableBody'; @@ -28,7 +29,7 @@ import TextField from "@material-ui/core/TextField"; import TableCell from '@material-ui/core/TableCell'; import RemoveCircleOutlineRoundedIcon from '@material-ui/icons/RemoveCircleOutlineRounded'; import VisibilityIcon from '@material-ui/icons/Visibility'; -import { Button, Typography } from '@material-ui/core'; +import { Button } 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' @@ -37,616 +38,479 @@ import EmailRoundedIcon from '@material-ui/icons/EmailRounded'; import TableData from '../../../Components/Components/Table'; import SnackBar from '../../../../Components/SnackbarComponent'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import { apiDomain } from '../../../../env'; +import noAvatar from "../../../../img/default_profile.png"; +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import PageHeader from "../../../Components/Components/PageHeader" //Services import { getRequest, putRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' import { Url } from '../../../Filters'; //routers import { Link } from 'react-router-dom'; -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" -import styled from "styled-components" -import { apiDomain } from '../../../../env'; -import noAvatar from "../../../../img/default_profile.png"; - -let currPage = 0; //var that controlls the current page that we are -let currContentFilter = 1; -let transformListToAsc = false; const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const BlockedUsers = () => { - const AddOneLenght = ['']; - const WINDOW_WIDTH = window.innerWidth - 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) - const [isUpdating, setIsUpdating] = useState(false) - - const [snackInfo, setSnackInfo] = useState({ - message: '', - icon: '', - open: false, - color: '', - }) - - const StateOptions = [ - { - id: 1, - name: "Semanal" - }, - { - id: 2, - name: "Permanente" - } - ]; - - // Handle snack infos - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color - }) + const ADD_ONE_LENGHT = ['']; + const WINDOW_WIDTH = window.innerWidth + + const [invertList, setInvertList] = useState(false) + 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) + const [stateOpt, setStateOpt] = useState(1) + const [currPage, setCurrPage] = useState(0) + + const [snackInfo, setSnackInfo] = useState({ + message: '', + icon: '', + open: false, + color: '', + }) + + const StateOptions = [ + { + name: 1, + value: "Semanal" + }, + { + name: 2, + value: "Permanente" } - - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true) - getRequest( - api, - (data, header) => { - const arrData = [...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(AddOneLenght)) - } - setIsLoadingMoreItems(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsLoadingMoreItems(false) - } - ) + ]; + + // Handle snack infos + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color + }) + } + + const handleChange = (event) => { + const type = event.target.value + setStateOpt(type) + } + + const BlockStatus = (status) => { + switch (status) { + case "blocked": + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#FF8C00", + fontWeight: "500", + color: "#FFFAFA", + }} + > + SEMANAL + </Paper> + ); + case "banished": + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "red", + fontWeight: "500", + color: "#FFFAFA", + }} + > + PERMANENTE + </Paper> + ); + default: + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#797D7F", + fontWeight: "500", + color: "#FFFAFA", + }} + > + Não avaliado + </Paper> + ); } - - const handleChange = (event) => { - const type = event.target.value - switch (type) { - case "Semanal": - currPage = 0; - currContentFilter = 1; - getRequest( - Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'ASC'), - (data, header) => { - HandleSnack("Filtro aplicado com sucesso!", true, 'success', '#228B22') - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - setIsUpdating(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsUpdating(false) - } - ) - break; - case "Permanente": - currPage = 0; - currContentFilter = 2; - getRequest( - Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'ASC'), - (data, header) => { - HandleSnack("Filtro aplicado com sucesso!", true, 'success', '#228B22') - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - setIsUpdating(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsUpdating(false) - } - ) - break; - default: - currPage = 0; - currContentFilter = 1; - getRequest( - Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'ASC'), - (data, header) => { - HandleSnack("Filtro aplicado com sucesso!", true, 'success', '#228B22') - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - setIsUpdating(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsUpdating(false) - } - ) - break; + }; + + const ReactiveUser = (userId, index) => { + putRequest( + `/users/${userId}/reactivate_user`, + {}, + (data) => { + if (data.errors) + HandleSnack('Erro!', true, 'warning', '#FA8072') + else { + HandleSnack('Usuário foi reativado com sucesso!', true, 'success', '#228B22') + removeItemFromList(index) + setCurrPage(0) } - } - - const InvertList = async () => { - transformListToAsc = !transformListToAsc - currPage = 0 - if (transformListToAsc) { - getRequest( - Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'ASC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + }, + (error) => { + HandleSnack('Erro!', true, 'warning', '#FA8072') + } + ) + } + + const removeItemFromList = (index) => { + const copyList = [...items] + copyList.splice(index, 1) + setItems(copyList) + } + + const DisplayDate = (date) => { + const convertedData = moment.utc(date); + return moment(convertedData) + .format("LLL") + .toString(); + }; + + const cleanArrayAndInvert = () => { + setInvertList(!invertList) + setCurrPage(0) + setItems([]) + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + Url('users', `"state" : ${stateOpt}`, currPage, invertList ? "ASC" : 'DESC'), + + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') } else { - getRequest( - Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'DESC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } } - } - - const UpdateHandler = async (api) => { - setIsUpdating(true) - getRequest( - api, - (data, header) => { - HandleSnack('A lista de dados foi atualizada', true, 'success', '#228B22') - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - setIsUpdating(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsUpdating(false) - } - ) - } - - const BlockStatus = (status) => { - switch (status) { - case 1: - return ( - <Paper - style={{ - textAlign: "center", - padding: "0.5em", - backgroundColor: "#FF8C00", - fontWeight: "500", - color: "#FFFAFA", - }} - > - SEMANAL - </Paper> - ); - case 2: - return ( - <Paper - style={{ - textAlign: "center", - padding: "0.5em", - backgroundColor: "red", - fontWeight: "500", - color: "#FFFAFA", - }} - > - PERMANENTE - </Paper> - ); - default: - return ( - <Paper + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, stateOpt, invertList]) + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." /> + } else { + + //Words in the top part of the table + const topTable = ['ID', 'ESTADO', 'NAME', 'EMAIL', 'BLOQUEADO EM', 'AÇÕES']; + if (WINDOW_WIDTH <= 899) { + return ( + <div> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + <MobilePageHeader + title="Lista de usuários bloqueados" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Inverter lista", + isLoading: false, + func: () => { + cleanArrayAndInvert() + }, + }, + ]} + > + <Grid item> + <TextField + select + label="Estado de bloqueio" + onChange={handleChange} + helperText="Por favor, selecione uma das opções" + > + {StateOptions.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </Grid> + </MobilePageHeader> + + <div style={{ height: '2em' }}></div> + + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton> + <Button + key={new Date().toISOString() + row.created_at} + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledDivButton> + ) : ( + <> + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.name} + subtitle={row.id} + backColor={"#e81f4f"} + avatar={ + <img + src={row.avatar ? apiDomain + row.avatar : noAvatar} + alt="user avatar" style={{ - textAlign: "center", - padding: "0.5em", - backgroundColor: "#797D7F", - fontWeight: "500", - color: "#FFFAFA", + height: "100%", + width: "100%", + borderRadius: "50%", }} - > - Não avaliado - </Paper> - ); - } - }; - - const ReactiveUser = (userId) => { - putRequest( - `/users/${userId}/reactivate_user`, - {}, - (data) => { - if (data.errors) - HandleSnack('Erro!', true, 'warning', '#FA8072') - else { - currPage = 0 - HandleSnack('Usuário foi reativado com sucesso!', true, 'success', '#228B22') - UpdateHandler(Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'DESC')) - } - }, - (error) => { - HandleSnack('Erro!', true, 'warning', '#FA8072') - } - ) - } - - const DisplayDate = (date) => { - const convertedData = moment.utc(date); - return moment(convertedData) - .format("LLL") - .toString(); - }; - - useEffect(() => { - getRequest( - Url('users', `"state" : "${currContentFilter}"`, '0', 'DESC'), - (data, header) => { - setIsLoaded(true); - setItems(data.concat(AddOneLenght)); - }, - (error) => { - setError(true); - } - ) - }, []); - - - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." /> - } else { - - //Words in the top part of the table - const topTable = ['ID', 'ESTADO', 'NAME', 'EMAIL', 'BLOQUEADO EM', 'AÇÕES']; - if (WINDOW_WIDTH <= 899) { - return ( - <div> - <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 direction="row" alignItems="center"> - <Grid container spacing={3} > - <Grid item xs={12}> - <Typography variant="h4"> - Lista de usuários bloqueados - </Typography> - </Grid> - <Grid - item - xs={12} - - > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - <Grid item> - <TextField - select - label="Estado de bloqueio" - onChange={handleChange} - helperText="Por favor, selecione uma das opções" - > - {StateOptions.map((option, index) => ( - <MenuItem - key={option.id} - value={option.name} - name={option.id} - > - {option.name} - </MenuItem> - ))} - </TextField> - </Grid> - - </Grid> - </Paper> - - <div style={{ height: '2em' }}></div> - - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'DESC')) - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.name} - subtitle={row.id} - backColor={"#e81f4f"} - avatar={ - <img - src={row.avatar ? apiDomain + row.avatar : noAvatar} - alt="user avatar" - style={{ - height: "100%", - width: "100%", - borderRadius: "50%", - }} - /> - } - href={`/admin/user/${row.id}`} - reset={() => { - currPage = 0; transformListToAsc = false; currContentFilter = 1 - }} - data={ - [ - { - title: "Email", - subtitle: row.email ? - <Link to={`/admin/sendEmail/${row.email}`} style={{ textDecoration: 'none' }}> - <Button - variant='text' - color='primary' - startIcon={<EmailRoundedIcon />} - > - {row.email} - </Button> - </Link> : null - - }, - { - title: "Estado", - subtitle: BlockStatus(currContentFilter) - }, - { - title: "Ações rápidas", - subtitle: <Button - style={{ width: "100%", marginBottom: "0.5em" }} - variant="contained" - color="secondary" - startIcon={<RemoveCircleOutlineRoundedIcon />} - onClick={() => ReactiveUser(row.id)} - > - Desbloquear + /> + } + href={`/admin/user?id=${row.id}`} + reset={() => { + }} + data={ + [ + { + title: "Email", + subtitle: row.email ? + <Link to={`/admin/sendEmail?email=${row.email}`} style={{ textDecoration: 'none' }}> + <Button + variant='text' + color='primary' + startIcon={<EmailRoundedIcon />} + > + {row.email} + </Button> + </Link> : null + + }, + { + title: "Estado", + subtitle: BlockStatus(row.state) + }, + { + title: "Ações rápidas", + subtitle: <Button + style={{ width: "100%", marginBottom: "0.5em" }} + variant="contained" + color="secondary" + startIcon={<RemoveCircleOutlineRoundedIcon />} + onClick={() => ReactiveUser(row.id, index)} + > + Desbloquear </Button> - } - ] - } - /> - <div style={{ height: "0.5em" }} /> - </> - ) - )} - </div> - ) - } - else { - return ( - <div> - <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 direction="row" alignItems="center"> - <Grid container spacing={3} > - <Grid item xs={6}> - <Typography variant="h4"> - Lista de usuários bloqueados - </Typography> - </Grid> - <Grid - item - xs={6} - > - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - <Grid item> - <TextField - select - label="Estado de bloqueio" - onChange={handleChange} - helperText="Por favor, selecione uma das opções" - > - {StateOptions.map((option, index) => ( - <MenuItem - key={option.id} - value={option.name} - name={option.id} - > - {option.name} - </MenuItem> - ))} - </TextField> - </Grid> - - </Grid> - </Paper> - - <div style={{ height: '2em' }}></div> - - <TableData - top={topTable} - onIconPressed={InvertList} - > - <TableBody> - {items.map((row, index) => ( - index === items.length - 1 ? - <StyledTableRow key={index}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color='primary' - variant='text' - disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('users', `"state" : "${currContentFilter}"`, `${currPage}`, 'DESC')) - } - }} - > - { - isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' - } - </Button> - </StyledTableCell> - </StyledTableRow> - - : - - <StyledTableRow key={index}> - <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> - <StyledTableCell align="right"> - {BlockStatus(currContentFilter)} - </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"> - {DisplayDate(row.suspended_at)} - </StyledTableCell> - <StyledTableCell align="right"> - <Button - style={{ width: "100%", marginBottom: "0.5em" }} - variant="contained" - color="secondary" - startIcon={<RemoveCircleOutlineRoundedIcon />} - onClick={() => ReactiveUser(row.id)} - > - Desbloquear + } + ] + } + /> + <div style={{ height: "0.5em" }} /> + </> + ) + )} + </div> + ) + } + else { + return ( + <div> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + <PageHeader + title="Lista de usuários bloqueados" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + ]} + > + <Grid item> + <TextField + select + label="Estado de bloqueio" + onChange={handleChange} + helperText="Por favor, selecione uma das opções" + > + {StateOptions.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </Grid> + </PageHeader> + + <div style={{ height: '2em' }}></div> + + <TableData + top={topTable} + onIconPressed={cleanArrayAndInvert} + > + <TableBody> + {items.map((row, index) => ( + index === items.length - 1 ? + <StyledTableRow key={new Date().toISOString() + row.created_at}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color='primary' + variant='text' + disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + { + isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' + } + </Button> + </StyledTableCell> + </StyledTableRow> + + : + + <StyledTableRow key={new Date().toISOString() + index}> + <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> + <StyledTableCell align="right"> + {BlockStatus(row.state)} + </StyledTableCell> + <StyledTableCell align="right">{row.name}</StyledTableCell> + <StyledTableCell align="right"> + { + row.email ? + <Link to={`/admin/sendEmail?email=${row.email}`} style={{ textDecoration: 'none' }}> + <Button + variant='text' + color='primary' + startIcon={<EmailRoundedIcon />} + > + {row.email} + </Button> + </Link> : null + } + </StyledTableCell> + <StyledTableCell align="right"> + {DisplayDate(row.suspended_at)} + </StyledTableCell> + <StyledTableCell align="right"> + <Button + style={{ width: "100%", marginBottom: "0.5em" }} + variant="contained" + color="secondary" + startIcon={<RemoveCircleOutlineRoundedIcon />} + onClick={() => ReactiveUser(row.id, index)} + > + Desbloquear </Button> - <Link to={`/admin/user/${row.id}`}> - <Button - onClick={() => { currPage = 0; transformListToAsc = false; currContentFilter = 1 }} - style={{ width: "100%" }} - variant="contained" - color="primary" - startIcon={<VisibilityIcon />} - > - Visualizar + <Link to={`/admin/user?id=${row.id}`}> + <Button + style={{ width: "100%" }} + variant="contained" + color="primary" + startIcon={<VisibilityIcon />} + > + Visualizar </Button> - </Link> - </StyledTableCell> - </StyledTableRow> - ))} - </TableBody> - </TableData> - </div> - ) - } + </Link> + </StyledTableCell> + </StyledTableRow> + ))} + </TableBody> + </TableData> + </div> + ) } + } } diff --git a/src/Admin/Pages/Pages/SubPages/Collections.js b/src/Admin/Pages/Pages/SubPages/Collections.js index 763aa71ea6aaf28df4411103b5fd0ad77c850c15..dd15cbaefc69bf3b14657d8c13393f05b9c0edf0 100644 --- a/src/Admin/Pages/Pages/SubPages/Collections.js +++ b/src/Admin/Pages/Pages/SubPages/Collections.js @@ -24,6 +24,9 @@ import SnackBar from "../../../../Components/SnackbarComponent"; import { Url, DeleteFilter } from "../../../Filters"; import AlertDialog from "../../../Components/Components/AlertDialog"; import LoadingSpinner from "../../../../Components/LoadingSpinner"; +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import PageHeader from "../../../Components/Components/PageHeader" //imports from material ui import { withStyles } from "@material-ui/core/styles"; import TableBody from "@material-ui/core/TableBody"; @@ -33,7 +36,7 @@ import MenuItem from "@material-ui/core/MenuItem"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; import IconButton from "@material-ui/core/IconButton"; -import { Button, Typography, Paper, Grid } from "@material-ui/core"; +import { Button, 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"; @@ -41,654 +44,560 @@ import FilterListRoundedIcon from "@material-ui/icons/FilterListRounded"; import VisibilityIcon from "@material-ui/icons/Visibility"; import DeleteIcon from "@material-ui/icons/Delete"; import { - deleteRequest, - getRequest, + deleteRequest, + getRequest, } from "../../../../Components/HelperFunctions/getAxiosConfig"; //routers import { Link } from "react-router-dom"; -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" import styled from 'styled-components' -let currPage = 0; -let currPrivacyFilter = ""; -let currNameFilter = ""; - const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + "&:nth-of-type(odd)": { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const Collections = () => { - const ADD_ONE_LENGHT = [""]; - const TOP_LABELS = [ - "NOME", - "DESCRIÇÃO", - "DONO(A)", - "CRIAÇÃO", - "ATUALIZAÇÃO", - "PRIVACIDADE", - "VISUALIZAR", - "DELETAR", - ]; //Labels from Table - - const WINDOW_WIDTH = window.innerWidth; - - 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 - - const [showFilter, setShowFilter] = useState(false); - const [search, setSearch] = useState(""); - - const [openAlertDialog, setOpenAlertDialog] = useState(false); - const [deleteItem, setDeleteItem] = useState({}); //Delete Item - const [isLoadingToDelete, setIsLoadingToDelete] = useState(null); - - const [option, setOption] = useState("Todos os usuários"); //labels of the text field 'to' - - const [snackInfo, setSnackInfo] = useState({ - message: "", - icon: "", - open: false, - color: "", + const ADD_ONE_LENGHT = [""]; + const TOP_LABELS = [ + "NOME", + "DESCRIÇÃO", + "DONO(A)", + "CRIAÇÃO", + "ATUALIZAÇÃO", + "PRIVACIDADE", + "VISUALIZAR", + "DELETAR", + ]; //Labels from Table + + const WINDOW_WIDTH = window.innerWidth; + + 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 [showFilter, setShowFilter] = useState(false); + const [valueOfSearch, setValueOfSearch] = useState("") + const [search, setSearch] = useState(""); + const [currPage, setCurrPage] = useState(0) + + const [openAlertDialog, setOpenAlertDialog] = useState(false); + const [deleteItem, setDeleteItem] = useState({}); //Delete Item + const [isLoadingToDelete, setIsLoadingToDelete] = useState(null); + const [option, setOption] = useState(); //labels of the text field 'to' + + const [snackInfo, setSnackInfo] = useState({ + message: "", + icon: "", + open: false, + color: "", + }); + + const privacyOptions = [ + { name: "private", value: "Privado" }, + { name: "public", value: "Público" } + ]; + + + //handle snack info + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color, }); - - const options = [ - { - value: "private", - label: "Privado", - }, - { - value: "public", - label: "Público", - }, - ]; - - //handle snack info - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color, - }); - }; - - //handle load more items - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true); - getRequest( - api, - (data, header) => { - const arrData = [...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)); - } - setIsLoadingMoreItems(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoadingMoreItems(false); - } - ); - }; - - //Defines which row must show the circular progress - const HandleStateCircularProgress = (i) => { - setIsLoadingToDelete(i); - }; - - // handle update list data - const UpdateHandler = async (api) => { - setIsUpdating(true); - getRequest( - api, - (data, header) => { - HandleSnack( - "A lista de dados foi atualizada", - true, - "success", - "#228B22" - ); - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - setIsUpdating(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsUpdating(false); - } - ); - }; - - //Called when user want to delete one institution - async function DeleteHandler() { - const id = deleteItem.id; - HandleStateAlertDialog(null); - deleteRequest( - DeleteFilter("collections", id), - (data) => { - if (data.errors) - HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); - else { - HandleSnack( - "A Coleção foi deletada com sucesso", - true, - "success", - "#228B22" - ); - currPage = 0; - HandleStateCircularProgress(null); - UpdateHandler(Url("collections", "", `${currPage}`, "DESC")); - } - }, - (error) => { - HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); - HandleStateCircularProgress(null); - } - ); + }; + + //Defines which row must show the circular progress + const HandleStateCircularProgress = (i) => { + setIsLoadingToDelete(i); + }; + + //Called when user want to delete one institution + async function DeleteHandler() { + const id = deleteItem.id; + HandleStateAlertDialog(null); + deleteRequest( + DeleteFilter("collections", id), + (data) => { + if (data.errors) + HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); + else { + HandleSnack( + "A Coleção foi deletada com sucesso", + true, + "success", + "#228B22" + ); + setCurrPage(0) + HandleStateCircularProgress(null); + removeItemFromList(id); + } + }, + (error) => { + HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); + HandleStateCircularProgress(null); + } + ); + } + + //Controlls the state of the Alert Dialog + const HandleStateAlertDialog = (i) => { + const obj = { ...items[i] }; + setDeleteItem(obj); + setOpenAlertDialog(!openAlertDialog); + }; + + // handle change of privacy + const handleChange = (e) => { + setOption(e.target.value); + }; + + const HandleSearch = (e) => { + setValueOfSearch(e.target.value) + } + + const DisplayDate = (date) => { + const convertedData = moment.utc(date); + return moment(convertedData) + .format("LLL") + .toString(); + }; + + const buildUrl = (privacyOpt, name) => { + if (privacyOpt && name) + return Url("collections", `"privacy" : "${privacyOpt}", "name" : "${name}"`, currPage, "DESC") + else if (privacyOpt) + return Url("collections", `"privacy" : "${privacyOpt}"`, currPage, "DESC") + else if (name) + return Url("collections", `"name" : "${name}"`, currPage, "DESC") + else + return Url("collections", "", currPage, "DESC") + } + + const removeItemFromList = (itemId) => { + let index = -1; + for (let i = 0; i < items.length; i++) { + const element = items[i]; + if (element.id === itemId) { + index = i + break + } } - - //Controlls the state of the Alert Dialog - const HandleStateAlertDialog = (i) => { - const obj = { ...items[i] }; - setDeleteItem(obj); - setOpenAlertDialog(!openAlertDialog); - }; - - const ApplyFilter = (value) => { - currPrivacyFilter = value - currPage = 0; - setIsLoaded(false); - getRequest( - Url( - "collections", - `"privacy" : "${currPrivacyFilter}" , "name" : "${currNameFilter}"`, - `${currPage}`, - "DESC" - ), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); - setIsLoaded(true); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - } - ); + if (index !== -1) { + const cpyItems = [...items] + cpyItems.splice(index, 1) + setItems(cpyItems) } - - // handle change of privacy - const handleChange = (e) => { - setOption(e.target.value); - }; - - //Handle the search filter - const HandleSearch = (event) => { - currNameFilter = event.target.value - setSearch(currNameFilter); - getRequest( - Url( - "collections", - `"privacy" : "${currPrivacyFilter}" , "name" : "${currNameFilter}"`, - `${currPage}`, - "DESC" - ), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - setIsLoaded(true); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - } - ); - }; - - const DisplayDate = (date) => { - const convertedData = moment.utc(date); - return moment(convertedData) - .format("LLL") - .toString(); - }; - - //getting data from server - useEffect(() => { - getRequest( - Url( - "collections", - `"privacy" : "${currPrivacyFilter}" , "name" : "${currNameFilter}"`, - `${currPage}`, - "DESC" - ), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - setIsLoaded(true); - setError(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(false); - setError(true); + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + buildUrl(option, search), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') + } else { + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } + } + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, search, option]) + + useEffect(() => { + setCurrPage(0) + setOption() + setSearch("") + setValueOfSearch("") + }, [showFilter]) + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." />; + } else { + if (WINDOW_WIDTH <= 1024) { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) } - ); - }, []); - - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." />; - } else { - if (WINDOW_WIDTH <= 954) { - 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={12}> - <Typography variant="h4">Coleções</Typography> - </Grid> - <Grid item xs={12}> - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0; - UpdateHandler( - Url( - "collections", - `"privacy" : "${currPrivacyFilter}" , "name" : "${currNameFilter}"`, - `${currPage}`, - "DESC" - ) - ); - }} - startIcon={<UpdateRoundedIcon />} - > - {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={() => { - setShowFilter(!showFilter); - }} - startIcon={<FilterListRoundedIcon />} - > - Filtrar - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - - {showFilter ? ( - <> - <div style={{ height: "1em" }}></div> - - <Grid - container - alignItems="center" - alignContent="center" - xs={12} - direction="row" - justify="space-between" - > - <Grid item> - <TextField - select - label="Filtro" - value={option ? option : ""} - onChange={handleChange} - helperText="Por favor, selecione uma das opções" - > - {options.map((option, index) => ( - <MenuItem key={index} value={option.value} onClick={() => { ApplyFilter(option.value) }}> - {option.label} - </MenuItem> - ))} - </TextField> - </Grid> - - <Grid item> - <TextField - label="Pesquisa" - value={search} - onChange={(event) => HandleSearch(event)} - ></TextField> - </Grid> - </Grid> - </> - ) : null} - </Paper> - - <div style={{ height: "2em" }}></div> - - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++; - LoadMoreItens( - Url( - "collections", - `"privacy" : "${currPrivacyFilter}" , "name" : "${currNameFilter}"`, - `${currPage}`, - "DESC" - ) - ); - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.name} - subtitle={row.privacy} - backColor={"#e81f4f"} - avatar={<PeopleRoundedIcon />} - href={`/admin/Collection/${row.id}`} - reset={() => { - currPage = 0; - currPrivacyFilter = ""; - currNameFilter = ""; - }} - data={ - [ - { - title: "ID", - subtitle: row.id - - }, - { - title: "Dono(a)", - subtitle: row.owner ? row.owner.name : "Sem dados" - - }, - { - title: "Criado em", - subtitle: DisplayDate(row.created_at) - }, - { - title: "Atualizado em", - subtitle: DisplayDate(row.updated_at) - } - ] - } - /> - <div style={{ height: "0.5em" }} /> - </> - ) + /> + <AlertDialog + open={openAlertDialog} + OnDelete={DeleteHandler} + deleteItem={deleteItem} + HandleClose={() => { + setOpenAlertDialog(false); + HandleStateCircularProgress(null); + }} + /> + <MobilePageHeader + title="Coleções" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + } + ]} + > + {showFilter ? ( + <> + <div style={{ height: "1em" }}></div> + + <Grid + container + alignItems="center" + alignContent="center" + xs={12} + direction="row" + justify="space-between" + > + <Grid item> + <TextField + select + label="Filtro" + value={option} + onChange={handleChange} + helperText="Por favor, selecione uma das opções" + > + {privacyOptions.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </Grid> + + <Grid item> + <TextField + label="Pesquisa" + value={valueOfSearch} + helperText="Ao digitar, tire o foco do campo de texto" + onChange={(event) => HandleSearch(event)} + onBlur={(event) => setSearch(event.target.value)} + ></TextField> + </Grid> + </Grid> + </> + ) : null} + </MobilePageHeader> + + <div style={{ height: "2em" }}></div> + + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton + key={new Date().toISOString() + row.created_at} + > + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" )} - </> - ); - } - else { - return ( + </Button> + </StyledDivButton> + ) : ( <> - <SnackBar - severity={snackInfo.icon} - text={snackInfo.message} - snackbarOpen={snackInfo.open} - color={snackInfo.color} - handleClose={() => - setSnackInfo({ - message: "", - icon: "", - open: false, - color: "", - }) + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.name} + subtitle={row.privacy} + backColor={"#e81f4f"} + avatar={<PeopleRoundedIcon />} + href={`/admin/Collection?collection=${row.id}`} + reset={() => { + + }} + data={ + [ + { + title: "ID", + subtitle: row.id + + }, + { + title: "Dono(a)", + subtitle: row.owner ? row.owner.name : "Sem dados" + + }, + { + title: "Criado em", + subtitle: DisplayDate(row.created_at) + }, + { + title: "Atualizado em", + subtitle: DisplayDate(row.updated_at) + }, + { + title: "Deletar", + subtitle: + <Button + variant="contained" + color="secondary" + onClick={() => { + HandleStateAlertDialog(index); + HandleStateCircularProgress(index); + }} + startIcon={<DeleteIcon />} + > + Deletar + </Button> } - /> - - <Paper style={{ padding: "1em" }}> - <Grid container spacing={3} direction="row" alignItems="center"> - <Grid item xs={6}> - <Typography variant="h4">Coleções</Typography> - </Grid> - <Grid item xs={6}> - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0; - UpdateHandler( - Url( - "collections", - `"privacy" : "${currPrivacyFilter}" , "name" : "${currNameFilter}"`, - `${currPage}`, - "DESC" - ) - ); - }} - startIcon={<UpdateRoundedIcon />} - > - {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={() => { - setShowFilter(!showFilter); - }} - startIcon={<FilterListRoundedIcon />} - > - Filtrar - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - - {showFilter ? ( - <> - <div style={{ height: "1em" }}></div> - - <Grid - container - alignItems="center" - alignContent="center" - xs={12} - direction="row" - justify="space-between" - > - <Grid item> - <TextField - select - label="Filtro" - value={option ? option : ""} - onChange={handleChange} - helperText="Por favor, selecione uma das opções" - > - {options.map((option, index) => ( - <MenuItem key={index} value={option.value} onClick={() => { ApplyFilter(option.value) }}> - {option.label} - </MenuItem> - ))} - </TextField> - </Grid> - - <Grid item> - <TextField - label="Pesquisa" - value={search} - onChange={(event) => HandleSearch(event)} - ></TextField> - </Grid> - </Grid> - </> - ) : null} - </Paper> - - <div style={{ height: "2em" }}></div> - - <TableData top={TOP_LABELS}> - <TableBody> - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledTableRow key={index}> - <StyledTableCell> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++; - LoadMoreItens( - Url( - "collections", - `"privacy" : "${currPrivacyFilter}" , "name" : "${currNameFilter}"`, - `${currPage}`, - "DESC" - ) - ); - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledTableCell> - </StyledTableRow> - ) : ( - <StyledTableRow key={index}> - <StyledTableCell component="th" scope="row"> - {row.name} - </StyledTableCell> - <StyledTableCell align="right"> - <div - dangerouslySetInnerHTML={{ __html: row.description }} - ></div> - </StyledTableCell> - <StyledTableCell align="right"> - {row.owner ? row.owner.name : "Sem dados"} - </StyledTableCell> - <StyledTableCell align="right"> - {DisplayDate(row.created_at)} - </StyledTableCell> - <StyledTableCell align="right"> - {DisplayDate(row.updated_at)} - </StyledTableCell> - <StyledTableCell align="right">{row.privacy}</StyledTableCell> - <StyledTableCell align="right"> - <Link to={`/admin/Collection/${row.id}`}> - <IconButton - onClick={() => { - currPage = 0; - currPrivacyFilter = ""; - currNameFilter = ""; - }} - > - <VisibilityIcon style={{ fill: "#00bcd4" }} /> - </IconButton> - </Link> - </StyledTableCell> - <StyledTableCell align="right"> - {isLoadingToDelete === index ? ( - <CircularProgress size={24} color="primary" /> - ) : ( - <IconButton - onClick={() => { - HandleStateAlertDialog(index); - HandleStateCircularProgress(index); - }} - > - <DeleteIcon style={{ fill: "#FF0000" }} /> - </IconButton> - )} - </StyledTableCell> - </StyledTableRow> - ) - )} - </TableBody> - </TableData> - - {/* This alert will be displayed if the user click to delete an institution */} - <AlertDialog - open={openAlertDialog} - OnDelete={DeleteHandler} - deleteItem={deleteItem} - HandleClose={() => { - setOpenAlertDialog(false); - HandleStateCircularProgress(null); - }} - /> + ] + } + /> + <div style={{ height: "0.5em" }} /> </> - ); - } + ) + )} + </> + ); + } + else { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) + } + /> + + <PageHeader + title="Coleções" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + } + ]} + > + {showFilter ? ( + <> + <div style={{ height: "1em" }}></div> + + <Grid + container + alignItems="center" + alignContent="center" + xs={12} + direction="row" + justify="space-between" + > + <Grid item> + <TextField + select + label="Filtro" + value={option} + onChange={handleChange} + helperText="Por favor, selecione uma das opções" + > + {privacyOptions.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </Grid> + + <Grid item> + <TextField + label="Pesquisa" + value={valueOfSearch} + helperText="Ao digitar, tire o foco do campo de texto" + onChange={(event) => HandleSearch(event)} + onBlur={(event) => setSearch(event.target.value)} + ></TextField> + </Grid> + </Grid> + </> + ) : null} + </PageHeader> + + <div style={{ height: "2em" }}></div> + + <TableData top={TOP_LABELS}> + <TableBody> + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledTableRow key={new Date().toISOString() + row.created_at}> + <StyledTableCell> + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledTableCell> + </StyledTableRow> + ) : ( + <StyledTableRow key={new Date().toISOString() + index}> + <StyledTableCell component="th" scope="row"> + {row.name} + </StyledTableCell> + <StyledTableCell align="right"> + <div + dangerouslySetInnerHTML={{ __html: row.description }} + ></div> + </StyledTableCell> + <StyledTableCell align="right"> + {row.owner ? row.owner.name : "Sem dados"} + </StyledTableCell> + <StyledTableCell align="right"> + {DisplayDate(row.created_at)} + </StyledTableCell> + <StyledTableCell align="right"> + {DisplayDate(row.updated_at)} + </StyledTableCell> + <StyledTableCell align="right">{row.privacy}</StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/Collection?collection=${row.id}`}> + <IconButton> + <VisibilityIcon style={{ fill: "#00bcd4" }} /> + </IconButton> + </Link> + </StyledTableCell> + <StyledTableCell align="right"> + {isLoadingToDelete === index ? ( + <CircularProgress size={24} color="primary" /> + ) : ( + <IconButton + onClick={() => { + HandleStateAlertDialog(index); + HandleStateCircularProgress(index); + }} + > + <DeleteIcon style={{ fill: "#FF0000" }} /> + </IconButton> + )} + </StyledTableCell> + </StyledTableRow> + ) + )} + </TableBody> + </TableData> + + {/* This alert will be displayed if the user click to delete an institution */} + <AlertDialog + open={openAlertDialog} + OnDelete={DeleteHandler} + deleteItem={deleteItem} + HandleClose={() => { + setOpenAlertDialog(false); + HandleStateCircularProgress(null); + }} + /> + </> + ); } + } }; export default Collections; diff --git a/src/Admin/Pages/Pages/SubPages/CommunityQuestions.js b/src/Admin/Pages/Pages/SubPages/CommunityQuestions.js index 8941b8c8d298f11c0ad42917738d09a58473c236..4c93b941127ab8009536a7ada106ca0791ffec23 100644 --- a/src/Admin/Pages/Pages/SubPages/CommunityQuestions.js +++ b/src/Admin/Pages/Pages/SubPages/CommunityQuestions.js @@ -16,763 +16,510 @@ 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, useContext } from "react"; +import React, { useEffect, useState } from "react"; import moment from 'moment'; //imports from local files import TableData from "../../../Components/Components/Table"; import SnackBar from "../../../../Components/SnackbarComponent"; -import Unauthorized from '../../../Components/Components/Unauthorized'; import { Url } from "../../../Filters"; -import { Store } from '../../../../Store'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; import { getRequest } from '../../../../Components/HelperFunctions/getAxiosConfig'; +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import PageHeader from "../../../Components/Components/PageHeader" //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 { Button, 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'; import ContactSupportRoundedIcon from "@material-ui/icons/ContactSupportRounded"; //routers import { Link } from 'react-router-dom'; -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" import styled from "styled-components" -let currPage = 0; - const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + "&:nth-of-type(odd)": { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const CommunityQuestion = () => { - const { state } = useContext(Store); - - const ADD_ONE_LENGHT = [""]; - const TOP_LABELS = [ - "ID", - "DATA DE CONTATO", - "NOME", - "EMAIL", - "MENSAGEM", - "VISUALIZAR" - ]; //Labels from Table - const WINDOW_WIDTH = window.innerWidth - - 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 = (e) => { - setMessage(e.target.value) - getRequest( - Url("contacts", `"message" : "${message}", "email" : "${email}", "name" : "${name}"`, currPage, 'DESC'), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - }, - (error) => { - 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) - getRequest( - Url("contacts", `"message" : "${message}", "email" : "${email}", "name" : "${name}"`, currPage, 'DESC'), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - }, - (error) => { - 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) - getRequest( - Url("contacts", `"message" : "${message}", "email" : "${email}", "name" : "${name}"`, currPage, 'DESC'), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - }, - (error) => { - 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 = (api) => { - setIsLoadingMoreItems(true) - getRequest( - api, - (data, header) => { - const arrData = [...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)); - } - setIsLoadingMoreItems(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoadingMoreItems(false); - } - ) - }; - - // handle update list data - const UpdateHandler = (api) => { - setIsUpdating(true); - getRequest( - api, - (data, header) => { - HandleSnack( - "A lista de dados foi atualizada", - true, - "success", - "#228B22" - ); - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - setIsUpdating(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsUpdating(false); - } - ) - }; - - const DisplayDate = (date) => { - const convertedData = moment.utc(date); - return moment(convertedData) - .format("LLL") - .toString(); - }; - - const CheckUserPermission = () => { - let canUserEdit = false; - - if (state.userIsLoggedIn) { - const roles = [...state.currentUser.roles]; - for (let i = 0; i < roles.length; i++) - if (roles[i].name === 'admin' || roles[i].name === 'editor') - canUserEdit = true; - } - else { - canUserEdit = false; + const ADD_ONE_LENGHT = [""]; + const TOP_LABELS = [ + "ID", + "DATA DE CONTATO", + "NOME", + "EMAIL", + "MENSAGEM", + "VISUALIZAR" + ]; //Labels from Table + const WINDOW_WIDTH = window.innerWidth + + 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 [currPage, setCurrPage] = useState(0) + + //Works with the filter + const [invertList, setInvertList] = useState(false) + const [showFilter, setShowFilter] = useState(false) + const [valueOfMessageField, setValueOfMessageField] = useState("") + const [message, setMessage] = useState(""); + const [valueOfEmailField, setValueOfEmailField] = useState("") + const [email, setEmail] = useState(""); + const [valueOfNameField, setValueOfNameField] = useState("") + const [name, setName] = useState(""); + + const [snackInfo, setSnackInfo] = useState({ + message: "", + icon: "", + open: false, + color: "", + }); + + //handle with the message filter + const valueOfMessageHandler = (e) => { + setValueOfMessageField(e.target.value) + } + + //handle with the email filter + const valueOfEmailHandler = (e) => { + setValueOfEmailField(e.target.value) + } + + //handle with the name filter + const valueOfNameHandler = (e) => { + setValueOfNameField(e.target.value) + } + + //handle snack info + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color, + }); + }; + + const DisplayDate = (date) => { + const convertedData = moment.utc(date); + return moment(convertedData) + .format("LLL") + .toString(); + }; + + const cleanArrayAndInvert = () => { + setInvertList(!invertList) + setCurrPage(0) + setItems([]) + } + + const buildUrl = (message, email, name, direction) => { + if (message && email && name) + return Url("contacts", `"message" : "${message}", "email" : "${email}", "name" : "${name}"`, currPage, direction) + + else if (message && name) + return Url("contacts", `"message" : "${message}", "name" : "${name}"`, currPage, direction) + else if (message && email) + return Url("contacts", `"message" : "${message}", "email" : "${email}"`, currPage, direction) + else if (name && email) + return Url("contacts", `"name" : "${name}", "email" : "${email}"`, currPage, direction) + + else if (message) + return Url("contacts", `"message" : "${message}"`, currPage, direction) + else if (email) + return Url("contacts", `"email" : "${email}"`, currPage, direction) + else if (name) + return Url("contacts", `"name" : "${name}"`, currPage, direction) + else + return Url("contacts", "", currPage, direction) + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + buildUrl(message, email, name, invertList ? "ASC" : "DESC"), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') + } else { + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } } - - return canUserEdit; - } - - //getting data from server - useEffect(() => { - getRequest( - Url("contacts", `"message" : "${message}", "email" : "${email}", "name" : "${name}"`, `${currPage}`, "DESC"), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - setIsLoaded(true); - setError(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - setError(true); + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, message, email, name, invertList]) + + useEffect(() => { + setCurrPage(0) + setName("") + setValueOfNameField("") + setEmail("") + setValueOfEmailField("") + setMessage("") + setValueOfMessageField("") + }, [showFilter]) + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." /> + } else { + if (WINDOW_WIDTH <= 1200) { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) } - ) - }, []); - - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." /> - } else if (CheckUserPermission()) { - if (WINDOW_WIDTH <= 1200) { - return ( + /> + <MobilePageHeader + title="Dúvidas da comunidade" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + }, + { + name: "Inverter lista de dados", + isLoading: false, + func: () => { + cleanArrayAndInvert() + }, + } + ]} + > + {showFilter ? ( + <Grid + container + direction="row" + justify="space-between" + alignItems="center" + alignContent="flex-end" + spacing={3} + xs={12} + > + <Grid item> + <TextField + label="Email" + value={valueOfEmailField} + onChange={valueOfEmailHandler} + onBlur={(e) => { setEmail(e.target.value) }} + helperText="Por favor, ao digitar o email que você quer filtar, retire o foco do campo de texto" + > + </TextField> + </Grid> + <Grid item> + <TextField + label="Mensagem" + value={valueOfMessageField} + onChange={valueOfMessageHandler} + onBlur={(e) => { setMessage(e.target.value) }} + helperText="Por favor, ao digitar a mensagem que você quer filtar, retire o foco do campo de texto" + > + </TextField> + </Grid> + <Grid item> + <TextField + label="Nome" + value={valueOfNameField} + onChange={valueOfNameHandler} + onBlur={(e) => { setName(e.target.value) }} + helperText="Por favor, ao digitar o nome que você quer filtar, retire o foco do campo de texto" + > + </TextField> + </Grid> + </Grid> + ) : null} + </MobilePageHeader> + + <div style={{ height: "2em" }}></div> + + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton + key="Load more" + > + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledDivButton> + ) : ( <> - <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={12}> - <Typography variant="h4">Dúvidas da comunidade</Typography> - </Grid> - <Grid - item - xs={12} - > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0; - UpdateHandler( - Url("contacts", `"message" : "${message}", "email" : "${email}", "name" : "${name}"`, `${currPage}`, "DESC") - ); - }} - startIcon={<UpdateRoundedIcon />} - > - {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={(e) => { - 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; - setMessage("") - UpdateHandler( - Url("contacts", `"message" : "", "email" : "${email}", "name" : "${name}"`, `${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; - setEmail("") - UpdateHandler( - Url("contacts", `"message" : "${message}", "email" : "", "name" : "${name}"`, `${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; - setName("") - UpdateHandler( - Url("contacts", `"message" : "${message}", "email" : "${email}", "name" : ""`, `${currPage}`, "DESC") - ); - setShowNameFilter(false) - }} - > - <CancelRoundedIcon /> - </IconButton> - </Grid> : null - } - </Grid> - </Grid> - </Paper> - - <div style={{ height: "2em" }}></div> - - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> + <MobileList + key={index} + title={row.name} + subtitle={row.id} + backColor={"#00bcd4"} + avatar={<ContactSupportRoundedIcon />} + href={`/admin/CommunityQuestion?question=${row.id}`} + reset={() => { + }} + data={ + [ + { + title: "Email", + subtitle: + row.email ? + <Link to={`/admin/sendEmail?email=${row.email}`} style={{ textDecoration: 'none' }}> <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++; - LoadMoreItens( - Url("contacts", `"message" : "${message}", "email" : "${email}", "name" : "${name}"`, `${currPage}`, "DESC") - ); - }} + variant='text' + color='primary' + startIcon={<EmailRoundedIcon />} > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} + {row.email} </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.name} - subtitle={row.id} - backColor={"#00bcd4"} - avatar={<ContactSupportRoundedIcon />} - href={`/admin/CommunityQuestion/${row.id}`} - reset={() => { - currPage = 0; - - }} - data={ - [ - { - title: "Email", - subtitle: - row.email ? - <Link to={`/admin/sendEmail/${row.email}`} style={{ textDecoration: 'none' }}> - <Button - variant='text' - color='primary' - startIcon={<EmailRoundedIcon />} - > - {row.email} - </Button> - </Link> : null - - }, - { - title: "Mensagem", - subtitle: row.message - - }, - { - title: "Criado em", - subtitle: DisplayDate(row.created_at) - }, - ] - } - /> - <div style={{ height: "0.5em" }} /> - </> - ) - )} - </> - ) - } - else { - return <> - <SnackBar - severity={snackInfo.icon} - text={snackInfo.message} - snackbarOpen={snackInfo.open} - color={snackInfo.color} - handleClose={() => - setSnackInfo({ - message: "", - icon: "", - open: false, - color: "", - }) + </Link> : null + + }, + { + title: "Mensagem", + subtitle: row.message + + }, + { + title: "Criado em", + subtitle: DisplayDate(row.created_at) + }, + ] } - /> - - <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} - > - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0; - UpdateHandler( - Url("contacts", `"message" : "${message}", "email" : "${email}", "name" : "${name}"`, `${currPage}`, "DESC") - ); - }} - startIcon={<UpdateRoundedIcon />} - > - {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={(e) => { - 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; - setMessage("") - UpdateHandler( - Url("contacts", `"message" : "", "email" : "${email}", "name" : "${name}"`, `${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; - setEmail("") - UpdateHandler( - Url("contacts", `"message" : "${message}", "email" : "", "name" : "${name}"`, `${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; - setName("") - UpdateHandler( - Url("contacts", `"message" : "${message}", "email" : "${email}", "name" : ""`, `${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 key={index} style={{ padding: "1em" }}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color="primary" - variant="text" - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++; - LoadMoreItens( - Url("contacts", `"message" : "${message}", "email" : "${email}", "name" : "${name}"`, `${currPage}`, "DESC") - ); - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledTableCell> - </StyledTableRow> - ) : ( - <StyledTableRow key={index}> - <StyledTableCell component="th" scope="row"> - {row.id} - </StyledTableCell> - <StyledTableCell align="right"> - {DisplayDate(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/CommunityQuestion/${row.id}`}> - <IconButton onClick={() => { currPage = 0 }}> - <VisibilityIcon style={{ fill: "#00bcd4" }} /> - </IconButton> - </Link> - </StyledTableCell> - </StyledTableRow> - ) + /> + <div style={{ height: "0.5em" }} /> + </> + ) + )} + </> + ) + } + else { + return <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) + } + /> + + <PageHeader + title="Dúvidas da comunidade" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + } + ]} + > + {showFilter ? ( + <Grid + container + direction="row" + justify="space-between" + alignItems="center" + alignContent="flex-end" + spacing={3} + xs={12} + > + <Grid item> + <TextField + label="Email" + value={valueOfEmailField} + onChange={valueOfEmailHandler} + onBlur={(e) => { setEmail(e.target.value) }} + helperText="Por favor, ao digitar o email que você quer filtar, retire o foco do campo de texto" + > + </TextField> + </Grid> + <Grid item> + <TextField + label="Mensagem" + value={valueOfMessageField} + onChange={valueOfMessageHandler} + onBlur={(e) => { setMessage(e.target.value) }} + helperText="Por favor, ao digitar a mensagem que você quer filtar, retire o foco do campo de texto" + > + </TextField> + </Grid> + <Grid item> + <TextField + label="Nome" + value={valueOfNameField} + onChange={valueOfNameHandler} + onBlur={(e) => { setName(e.target.value) }} + helperText="Por favor, ao digitar o nome que você quer filtar, retire o foco do campo de texto" + > + </TextField> + </Grid> + </Grid> + ) : null} + </PageHeader> + + <div style={{ height: "2em" }}></div> + + <TableData top={TOP_LABELS} onIconPressed={cleanArrayAndInvert}> + <TableBody> + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledTableRow key={row.created_at} style={{ padding: "1em" }}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color="primary" + variant="text" + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" )} - </TableBody> - </TableData> - </> - } - - } else return <Unauthorized /> + </Button> + </StyledTableCell> + </StyledTableRow> + ) : ( + <StyledTableRow key={new Date().toISOString() + index}> + <StyledTableCell component="th" scope="row"> + {row.id} + </StyledTableCell> + <StyledTableCell align="right"> + {DisplayDate(row.created_at)} + </StyledTableCell> + <StyledTableCell align="right"> + {row.name} + </StyledTableCell> + <StyledTableCell align="right"> + { + row.email ? + <Link to={`/admin/sendEmail?email=${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/CommunityQuestion?question=${row.id}`}> + <IconButton> + <VisibilityIcon style={{ fill: "#00bcd4" }} /> + </IconButton> + </Link> + </StyledTableCell> + </StyledTableRow> + ) + )} + </TableBody> + </TableData> + </> + } + } } export default CommunityQuestion; diff --git a/src/Admin/Pages/Pages/SubPages/Complaints.js b/src/Admin/Pages/Pages/SubPages/Complaints.js index 452aaf767e40435fc33ffac975610bbb2e82016c..d03514dc91f170cd84c4807e42c5f4d643de036e 100644 --- a/src/Admin/Pages/Pages/SubPages/Complaints.js +++ b/src/Admin/Pages/Pages/SubPages/Complaints.js @@ -16,15 +16,17 @@ 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, useContext } from "react"; +import React, { useEffect, useState } from "react"; import moment from "moment"; //imports from local files import TableData from "../../../Components/Components/Table"; import SnackBar from "../../../../Components/SnackbarComponent"; import { Url } from "../../../Filters"; -import { Store } from '../../../../Store'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; import { getRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import PageHeader from "../../../Components/Components/PageHeader" //imports from material ui import { withStyles } from "@material-ui/core/styles"; import TableBody from "@material-ui/core/TableBody"; @@ -33,7 +35,7 @@ import MenuItem from "@material-ui/core/MenuItem"; import TableRow from "@material-ui/core/TableRow"; import TextField from "@material-ui/core/TextField"; import IconButton from "@material-ui/core/IconButton"; -import { Button, Typography, Paper, Grid } from "@material-ui/core"; +import { Button, 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"; @@ -42,841 +44,602 @@ import VisibilityIcon from "@material-ui/icons/Visibility"; import LaunchRoundedIcon from "@material-ui/icons/LaunchRounded"; //routers import { Link } from "react-router-dom"; -import Unauthorized from "../../../Components/Components/Unauthorized"; import styled from "styled-components" -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" import AnnouncementRoundedIcon from "@material-ui/icons/AnnouncementRounded"; -let currPage = 0; -let currStateFilter = "0" -let currComplainReasonId; -let currDescriptionFilter = ""; - const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + "&:nth-of-type(odd)": { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const Complaints = () => { - const { state } = useContext(Store); - const WINDOW_WIDTH = window.innerWidth - - const PORTAL_MEC = "https://plataformaintegrada.mec.gov.br/"; - - const ADD_ONE_LENGHT = [""]; - const TOP_LABELS = [ - "ESTADO DO RECURSO", - "ID", - "DESCRIÇÃO", - "ID OBJETO", - "TIPO", - "DATA(MM/DD/YYYY)", - "VISUALIZAR", - "VISITAR", - ]; //Labels from Table - - 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 - - const [showFilter, setShowFilter] = useState(false); - - const [stateOption, setStateOption] = useState("Pendente"); - const [complainOption, setComplainOption] = useState(""); - const [description, setDescription] = useState(""); - - const [snackInfo, setSnackInfo] = useState({ - message: "", - icon: "", - open: false, - color: "", + const WINDOW_WIDTH = window.innerWidth + const ADD_ONE_LENGHT = [""]; + const PORTAL_MEC = "https://plataformaintegrada.mec.gov.br/"; + const TOP_LABELS = [ + "ESTADO DO RECURSO", + "ID", + "DESCRIÇÃO", + "ID OBJETO", + "TIPO", + "DATA(MM/DD/YYYY)", + "VISUALIZAR", + "VISITAR", + ]; //Labels from Table + + const [invertList, setInvertList] = useState(false) + 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 [showFilter, setShowFilter] = useState(false); + + const [stateOption, setStateOption] = useState(0); + const [complainOption, setComplainOption] = useState(""); + const [description, setDescription] = useState(""); + const [valueOfDescField, setValueOfDescField] = useState("") + const [currPage, setCurrPage] = useState(0) + + const [snackInfo, setSnackInfo] = useState({ + message: "", + icon: "", + open: false, + color: "", + }); + + const stateOptions = [ + { name: 0, value: "Pendente" }, + { name: 1, value: "Ativo" }, + { name: 2, value: "Removido" }, + ]; + + const ComplaintReasons = [ + { name: 1, value: "Viola direitos autorais" }, + { name: 2, value: "Conteúdo ofensivo/abusivo" }, + { name: 3, value: "Conta falsa" }, + { name: 4, value: "Spam" }, + { name: 5, value: "Descrição diverge do conteúdo" }, + ]; + + //handle snack info + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color, }); - - const StateOptions = [ - { id: 0, name: "Pendente" }, - { id: 1, name: "Ativo" }, - { id: 2, name: "Bloqueado / Removido" }, - ]; - - const ComplaintReasons = [ - { id: 1, name: "Viola direitos autorais" }, - { id: 2, name: "Conteúdo ofensivo/abusivo" }, - { id: 3, name: "Conta falsa" }, - { id: 4, name: "Spam" }, - { id: 5, name: "Descrição diverge do conteúdo" }, - ]; - - //handle snack info - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color, - }); - }; - - const CheckUserPermission = () => { - let canUserEdit = false; - - if (state.userIsLoggedIn) { - const roles = [...state.currentUser.roles]; - for (let i = 0; i < roles.length; i++) - if (roles[i].name === 'admin' || roles[i].name === 'editor') - canUserEdit = true; - } - else { - canUserEdit = false; - } - - return canUserEdit; + }; + + const handleChangeState = (e, type) => { + const value = e.target.value; + setStateOption(value); + }; + + const handleChangeComplain = (e, type) => { + const value = e.target.value; + setComplainOption(value); + }; + + const DescriptionHandler = (e) => { + setValueOfDescField(e.target.value) + } + + const convertToLink = (type, id) => { + switch (type) { + case "LearningObject": + return `recurso?id=${id}/`; + case "User": + return `usuario-publico/${id}/`; + default: + return ""; } - - //handle load more items - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true); - getRequest( - api, - (data, header) => { - const arrData = [...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)); - } - setIsLoadingMoreItems(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoadingMoreItems(false); - } - ) - }; - - // handle update list data - const UpdateHandler = async (api) => { - setIsUpdating(true); - getRequest( - api, - (data, header) => { - HandleSnack( - "A lista de dados foi atualizada", - true, - "success", - "#228B22" - ); - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - setIsUpdating(false); - - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsUpdating(false); - + }; + + const ComplaintStatus = (status, type) => { + switch (status) { + case "accepted": + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#FA8072", + fontWeight: "500", + color: "#FFFAFA", + }} + > + { + type === "User" ? "BLOQUEADO" : "REMOVIDO" } - ) - }; - - const handleChangeState = (e, type) => { - const value = e.target.value; - setStateOption(value); - }; - - const handleChangeComplain = (e, type) => { - const value = e.target.value; - setComplainOption(value); - }; - - const ApplyFilterState = (id, type) => { - currPage = 0; - currStateFilter = id; - let url; - if (currComplainReasonId) { - url = Url("complaints", - `"state" : "${currStateFilter}", "complaint_reason_id" : "${currComplainReasonId}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - } - else { - url = Url("complaints", - `"state" : "${currStateFilter}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - } - getRequest( - url, - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); - setIsLoaded(true); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - } - ) - }; - - const ApplyFilterComplainReason = (id, type) => { - currPage = 0; - currComplainReasonId = id; - let url; - if (currComplainReasonId) { - url = Url("complaints", - `"state" : "${currStateFilter}", "complaint_reason_id" : "${currComplainReasonId}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - } - else { - url = Url("complaints", - `"state" : "${currStateFilter}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - } - getRequest( - url, - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); - setIsLoaded(true); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - } - ) - }; - - const DescriptionHandler = (e) => { - currPage = 0; - currDescriptionFilter = e.target.value; - setDescription(currDescriptionFilter) - let url; - if (currComplainReasonId) { - url = Url("complaints", - `"state" : "${currStateFilter}", "complaint_reason_id" : "${currComplainReasonId}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - } - else { - url = Url("complaints", - `"state" : "${currStateFilter}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - } - getRequest( - url, - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); - setIsLoaded(true); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - } - ) + </Paper> + ); + case "complained": + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#FF8C00", + fontWeight: "500", + color: "#FFFAFA", + }} + > + PENDENTE + </Paper> + ); + case "rejected": + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#228B22", + fontWeight: "500", + color: "#FFFAFA", + }} + > + REJEITADO + </Paper> + ); + default: + return "NOTHING"; } - - const convertToLink = (type, id) => { - switch (type) { - case "LearningObject": - return `recurso?id=${id}/`; - case "User": - return `usuario-publico/${id}/`; - default: - return ""; - } - }; - - const ComplaintStatus = (status, type) => { - switch (status) { - case "accepted": - return ( - <Paper - style={{ - textAlign: "center", - padding: "0.5em", - backgroundColor: "#FA8072", - fontWeight: "500", - color: "#FFFAFA", - }} - > - { - type === "User" ? "BLOQUEADO" : "REMOVIDO" - } - </Paper> - ); - case "complained": - return ( - <Paper - style={{ - textAlign: "center", - padding: "0.5em", - backgroundColor: "#FF8C00", - fontWeight: "500", - color: "#FFFAFA", - }} - > - PENDENTE - </Paper> - ); - case "rejected": - return ( - <Paper - style={{ - textAlign: "center", - padding: "0.5em", - backgroundColor: "#228B22", - fontWeight: "500", - color: "#FFFAFA", - }} - > - REJEITADO - </Paper> - ); - default: - return "NOTHING"; + }; + + const DisplayDate = (date) => { + const convertedData = moment.utc(date); + return moment(convertedData) + .format("LLL") + .toString(); + }; + + const cleanArrayAndInvert = () => { + setInvertList(!invertList) + setCurrPage(0) + setItems([]) + } + + const buildUrl = (complainOpt, state, description, direction) => { + if (complainOpt && (state >= 0 && state <= 2) && description) + return Url("complaints", `"state" : ${state}, "complaint_reason_id" : ${complainOpt}, "description" : "${description}"`, currPage, direction) + + else if (complainOpt && description) + return Url("complaints", `"complaint_reason_id" : ${complainOpt}, "description" : "${description}"`, currPage, direction) + else if (complainOpt && (state >= 0 && state <= 2)) + return Url("complaints", `"complaint_reason_id" : ${complainOpt}, "state" : ${state}`, currPage, direction) + else if (description && (state >= 0 && state <= 2)) + return Url("complaints", `"description" : "${description}", "state" : ${state}`, currPage, direction) + + else if (complainOpt) + return Url("complaints", `"complaint_reason_id" : ${complainOpt}`, currPage, direction) + else if (state >= 0 && state <= 2) + return Url("complaints", `"state" : ${state}`, currPage, direction) + else if (description) + return Url("complaints", `"description" : ${description}`, currPage, direction) + else + return Url("complaints", "", currPage, direction) + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + buildUrl(complainOption, stateOption, description, invertList ? "ASC" : "DESC"), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') + } else { + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } } - }; - - const DisplayDate = (date) => { - const convertedData = moment.utc(date); - return moment(convertedData) - .format("LLL") - .toString(); - }; - - //getting data from server - useEffect(() => { - getRequest( - Url("complaints", `"state" : "${currStateFilter}"`, `${currPage}`, "DESC"), - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(ADD_ONE_LENGHT)); - setIsLoaded(true); - setError(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoaded(true); - setError(true); + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, complainOption, stateOption, description, invertList]) + + useEffect(() => { + setComplainOption() + setDescription("") + setValueOfDescField("") + setStateOption(0) + setCurrPage(0) + }, [showFilter]) + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." /> + } else { + if (WINDOW_WIDTH <= 994) { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) } - ) - }, []); - - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." /> - } else if (CheckUserPermission()) { - if (WINDOW_WIDTH <= 994) { - 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={12}> - <Typography variant="h4">Denúncias</Typography> - </Grid> - - <Grid - item - xs={12} - > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0; - if (currComplainReasonId) { - UpdateHandler( - Url("complaints", - `"state" : "${currStateFilter}", "complaint_reason_id" : "${currComplainReasonId}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - ); - } - else { - UpdateHandler( - Url("complaints", - `"state" : "${currStateFilter}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - ); - } - }} - startIcon={<UpdateRoundedIcon />} - > - {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={() => { - setShowFilter(!showFilter); - }} - startIcon={<FilterListRoundedIcon />} - > - Filtrar - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - - {showFilter ? ( - <Grid - container - direction="row" - justify="space-between" - alignItems="center" - alignContent="flex-end" - spacing={3} - xs={12} - > - <Grid item> - <TextField - select - label="Motivo" - value={complainOption} - onChange={handleChangeComplain} - helperText="Por favor, selecione uma das opções" - > - {ComplaintReasons.map((option, index) => ( - <MenuItem - key={option.id} - value={option.name} - name={option.id} - onClick={() => - ApplyFilterComplainReason(option.id, "complaint_reason_id") - } - > - {option.name} - </MenuItem> - ))} - </TextField> - </Grid> - <Grid item> - <TextField - select - label="Estado" - value={stateOption} - onChange={handleChangeState} - helperText="Por favor, selecione uma das opções" - > - {StateOptions.map((option, index) => ( - <MenuItem - key={option.id} - value={option.name} - name={option.id} - onClick={() => ApplyFilterState(option.id, "state")} - > - {option.name} - </MenuItem> - ))} - </TextField> - </Grid> - <Grid item> - <TextField label="Descrição" onChange={DescriptionHandler} value={description} /> - </Grid> - </Grid> - ) : null} - </Paper> - - <div style={{ height: "2em" }}></div> - - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++; - if (currComplainReasonId) { - LoadMoreItens( - Url("complaints", - `"state" : "${currStateFilter}", "complaint_reason_id" : "${currComplainReasonId}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - ); - } - else { - LoadMoreItens( - Url("complaints", - `"state" : "${currStateFilter}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - ); - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.complainable_type} - subtitle={row.id} - backColor={"#673ab7"} - avatar={<AnnouncementRoundedIcon />} - href={`/admin/complaint/${row.id}`} - reset={() => { - currPage = 0 - currStateFilter = "0" - currDescriptionFilter = "" - currComplainReasonId = null; - }} - data={ - [ - { - title: "ID do objeto", - subtitle: row.complainable_id - - }, - { - title: "Criado em", - subtitle: DisplayDate(row.created_at) - }, - { - title: "Descrição", - subtitle: row.description - }, - { - title: "Estado", - subtitle: ComplaintStatus(row.state, row.complainable_type) - } - ] - } - /> - <div style={{ height: "0.5em" }} /> - </> - ) + /> + <MobilePageHeader + title="Denúncias" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + }, + { + name: "Inverter lista", + isLoading: false, + func: () => { + cleanArrayAndInvert() + }, + } + ]} + > + {showFilter ? ( + <Grid + container + direction="row" + justify="space-between" + alignItems="center" + alignContent="flex-end" + spacing={3} + xs={12} + > + <Grid item> + <TextField + select + label="Motivo" + value={complainOption} + onChange={handleChangeComplain} + helperText="Por favor, selecione uma das opções" + > + {ComplaintReasons.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </Grid> + <Grid item> + <TextField + select + label="Estado" + value={stateOption} + onChange={handleChangeState} + helperText="Por favor, selecione uma das opções" + > + {stateOptions.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </Grid> + <Grid item> + <TextField label="Descrição" helperText="Ao digitar a descrição, retire o foco do campo de texto" onChange={DescriptionHandler} value={valueOfDescField} onBlur={e => setDescription(e.target.value)} /> + </Grid> + </Grid> + ) : null} + </MobilePageHeader> + + <div style={{ height: "2em" }}></div> + + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton + key={new Date().toISOString() + row.created_at} + > + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" )} - </> - ); - } - else { - return ( + </Button> + </StyledDivButton> + ) : ( <> - <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">Denúncias</Typography> - </Grid> + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.complainable_type} + subtitle={row.id} + backColor={"#673ab7"} + avatar={<AnnouncementRoundedIcon />} + href={`/admin/complaint?id=${row.id}`} + reset={() => { + + }} + data={ + [ + { + title: "ID do objeto", + subtitle: row.complainable_id - <Grid - item - xs={6} + }, + { + title: "Criado em", + subtitle: DisplayDate(row.created_at) + }, + { + title: "Descrição", + subtitle: row.description + }, + { + title: "Estado", + subtitle: ComplaintStatus(row.state, row.complainable_type) + } + ] + } + /> + <div style={{ height: "0.5em" }} /> + </> + ) + )} + </> + ); + } + else { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) + } + /> + + <PageHeader + title="Denúncias" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + } + ]} + > + {showFilter ? ( + <Grid + container + direction="row" + justify="space-between" + alignItems="center" + alignContent="flex-end" + spacing={3} + xs={12} + > + <Grid item> + <TextField + select + label="Motivo" + value={complainOption} + onChange={handleChangeComplain} + helperText="Por favor, selecione uma das opções" + > + {ComplaintReasons.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </Grid> + <Grid item> + <TextField + select + label="Estado" + value={stateOption} + onChange={handleChangeState} + helperText="Por favor, selecione uma das opções" + > + {stateOptions.map((option, index) => ( + <MenuItem + key={option.value} + value={option.name} + name={option.value} + > + {option.value} + </MenuItem> + ))} + </TextField> + </Grid> + <Grid item> + <TextField label="Descrição" helperText="Ao digitar a descrição, retire o foco do campo de texto" onChange={DescriptionHandler} value={valueOfDescField} onBlur={e => setDescription(e.target.value)} /> + </Grid> + </Grid> + ) : null} + </PageHeader> + + <div style={{ height: "2em" }}></div> + + <Grid xs={12} container> + <TableData + top={TOP_LABELS} + onIconPressed={cleanArrayAndInvert} + > + <TableBody> + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledTableRow key={new Date().toISOString() + row.created_at}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledTableCell> + </StyledTableRow> + ) : ( + <StyledTableRow + key={new Date().toISOString() + index} + style={{ flex: 1, width: "100%" }} + > + <StyledTableCell component="th" scope="row"> + {ComplaintStatus(row.state, row.complainable_type)} + </StyledTableCell> + <StyledTableCell align="right">{row.id}</StyledTableCell> + <StyledTableCell align="right"> + {row.description} + </StyledTableCell> + <StyledTableCell align="right"> + {row.complainable_id} + </StyledTableCell> + <StyledTableCell align="right"> + {row.complainable_type} + </StyledTableCell> + <StyledTableCell align="right"> + {DisplayDate(row.created_at)} + </StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/complaint?id=${row.id}`}> + <IconButton + onClick={() => { + }} > - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0; - if (currComplainReasonId) { - UpdateHandler( - Url("complaints", - `"state" : "${currStateFilter}", "complaint_reason_id" : "${currComplainReasonId}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - ); - } - else { - UpdateHandler( - Url("complaints", - `"state" : "${currStateFilter}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - ); - } - }} - startIcon={<UpdateRoundedIcon />} - > - {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={() => { - setShowFilter(!showFilter); - }} - startIcon={<FilterListRoundedIcon />} - > - Filtrar - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - - {showFilter ? ( - <Grid - container - direction="row" - justify="space-between" - alignItems="center" - alignContent="flex-end" - spacing={3} - xs={12} + <VisibilityIcon style={{ fill: "#00bcd4" }} /> + </IconButton> + </Link> + </StyledTableCell> + <StyledTableCell align="right"> + <Button + variant="text" + secondary={true} + startIcon={ + <LaunchRoundedIcon style={{ fill: "#FA8072" }} /> + } + > + <a + style={{ + textDecoration: "none", + color: "#FA8072", + }} + target="_blank" + rel="noreferrer" + href={ + PORTAL_MEC + + convertToLink( + row.complainable_type, + row.complainable_id + ) + } > - <Grid item> - <TextField - select - label="Motivo" - value={complainOption} - onChange={handleChangeComplain} - helperText="Por favor, selecione uma das opções" - > - {ComplaintReasons.map((option, index) => ( - <MenuItem - key={option.id} - value={option.name} - name={option.id} - onClick={() => - ApplyFilterComplainReason(option.id, "complaint_reason_id") - } - > - {option.name} - </MenuItem> - ))} - </TextField> - </Grid> - <Grid item> - <TextField - select - label="Estado" - value={stateOption} - onChange={handleChangeState} - helperText="Por favor, selecione uma das opções" - > - {StateOptions.map((option, index) => ( - <MenuItem - key={option.id} - value={option.name} - name={option.id} - onClick={() => ApplyFilterState(option.id, "state")} - > - {option.name} - </MenuItem> - ))} - </TextField> - </Grid> - <Grid item> - <TextField label="Descrição" onChange={DescriptionHandler} value={description} /> - </Grid> - </Grid> - ) : null} - </Paper> - - <div style={{ height: "2em" }}></div> - - <Grid xs={12} container> - <TableData top={TOP_LABELS}> - <TableBody> - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledTableRow key={index}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++; - if (currComplainReasonId) { - LoadMoreItens( - Url("complaints", - `"state" : "${currStateFilter}", "complaint_reason_id" : "${currComplainReasonId}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - ); - } - else { - LoadMoreItens( - Url("complaints", - `"state" : "${currStateFilter}", "description" : "${currDescriptionFilter}"`, - `${currPage}`, - "DESC" - ) - ); - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledTableCell> - </StyledTableRow> - ) : ( - <StyledTableRow - key={index} - style={{ flex: 1, width: "100%" }} - > - <StyledTableCell component="th" scope="row"> - {ComplaintStatus(row.state, row.complainable_type)} - </StyledTableCell> - <StyledTableCell align="right">{row.id}</StyledTableCell> - <StyledTableCell align="right"> - {row.description} - </StyledTableCell> - <StyledTableCell align="right"> - {row.complainable_id} - </StyledTableCell> - <StyledTableCell align="right"> - {row.complainable_type} - </StyledTableCell> - <StyledTableCell align="right"> - {DisplayDate(row.created_at)} - </StyledTableCell> - <StyledTableCell align="right"> - <Link to={`/admin/complaint/${row.id}`}> - <IconButton - onClick={() => { - currPage = 0 - currStateFilter = "0" - currDescriptionFilter = "" - currComplainReasonId = null; - }} - > - <VisibilityIcon style={{ fill: "#00bcd4" }} /> - </IconButton> - </Link> - </StyledTableCell> - <StyledTableCell align="right"> - <Button - variant="text" - secondary={true} - startIcon={ - <LaunchRoundedIcon style={{ fill: "#FA8072" }} /> - } - > - <a - style={{ - textDecoration: "none", - color: "#FA8072", - }} - target="_blank" - rel="noreferrer" - href={ - PORTAL_MEC + - convertToLink( - row.complainable_type, - row.complainable_id - ) - } - > - MEC RED + MEC RED </a> - </Button> - </StyledTableCell> - </StyledTableRow> - ) - )} - </TableBody> - </TableData> - </Grid> - </> - ); - } - } else return <Unauthorized /> + </Button> + </StyledTableCell> + </StyledTableRow> + ) + )} + </TableBody> + </TableData> + </Grid> + </> + ); + } + } }; export default Complaints; diff --git a/src/Admin/Pages/Pages/SubPages/EducationalObjects.js b/src/Admin/Pages/Pages/SubPages/EducationalObjects.js index a4219eea0efbc89a1af6c218b2d0fce6ca5b47da..69d0dfc326b54a0f970a6e98e905dddff7f0f41f 100644 --- a/src/Admin/Pages/Pages/SubPages/EducationalObjects.js +++ b/src/Admin/Pages/Pages/SubPages/EducationalObjects.js @@ -18,11 +18,14 @@ along with Plataforma Integrada MEC. If not, see <http://www.gnu.org/licenses/> import React, { useState, useEffect } from "react"; import moment from 'moment'; -// Imports from local files +// Imports from local file import TableData from "../../../Components/Components/Table"; import SnackBar from "../../../../Components/SnackbarComponent"; import AlertDialog from "../../../Components/Components/AlertDialog"; import LoadingSpinner from '../../../../Components/LoadingSpinner'; +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import PageHeader from "../../../Components/Components/PageHeader" // Imports about icon import FilterListRoundedIcon from "@material-ui/icons/FilterListRounded"; import AddRoundedIcon from "@material-ui/icons/AddRounded"; @@ -31,16 +34,14 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import IconButton from "@material-ui/core/IconButton"; -import CancelRoundedIcon from "@material-ui/icons/CancelRounded"; import VisibilityIcon from "@material-ui/icons/Visibility"; import DeleteIcon from "@material-ui/icons/Delete"; // Import from material-ui -import { withStyles, makeStyles } from "@material-ui/core/styles"; +import { withStyles } from "@material-ui/core/styles"; import Paper from "@material-ui/core/Paper"; import Button from "@material-ui/core/Button"; import Grid from "@material-ui/core/Grid"; -import { Typography, CircularProgress } from "@material-ui/core"; -import Popover from "@material-ui/core/Popover"; +import { CircularProgress } from "@material-ui/core"; import TextField from "@material-ui/core/TextField"; // services import { getRequest, deleteRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' @@ -50,9 +51,6 @@ import { Url, DeleteFilter } from "../../../Filters"; import { Link } from 'react-router-dom'; import styled from 'styled-components' import MenuBookRoundedIcon from "@material-ui/icons/MenuBookRounded"; -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" - -let currPage = 0; const StyledTableCell = withStyles((theme) => ({ head: { @@ -72,35 +70,18 @@ const StyledTableRow = withStyles((theme) => ({ }, }))(TableRow); -const useStyles = makeStyles((theme) => ({ - root: { - flexGrow: 1, - }, - paper: { - padding: theme.spacing(1), - textAlign: "start", - }, - button: { - margin: theme.spacing(1), - alignSelf: "flex-end", - }, -})); - const EducationalObjects = () => { - const classes = useStyles(); const WINDOW_WIDTH = window.innerWidth - - const addOndeLenght = [""]; + const ADD_ONE_LENGHT = [""]; 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 [currPage, setCurrPage] = useState(0) const [deleteItem, setDeleteItem] = useState({}); //Delete Item const [isLoadingToDelete, setIsLoadingToDelete] = useState(null); - const [isUpdating, setIsUpdating] = useState(false); const [isLoadingMoreItems, setIsLoadingMoreItems] = useState(false); - + const [showFilter, setShowFilter] = useState(false) const [openAlertDialog, setOpenAlertDialog] = useState(false); const [snackInfo, setSnackInfo] = useState({ @@ -110,88 +91,26 @@ const EducationalObjects = () => { color: "", }); - // **************** About the PopOver Menu **************** - const [anchorEl, setAnchorEl] = React.useState(null); - const [showAuthorField, setShowAuthorField] = useState(false); //show the text field of filter by Author - const [showDescriptionField, setShowDescriptionField] = useState(false); //show the text field of the filter by description - const [showStandadSearch, setShowStandarSearchField] = useState(false); const [search, setSeacrh] = useState(""); + const [valueSearch, setValueSearch] = useState("") const [author, setAuthor] = useState(""); - const [description, setDescription] = useState(null); - - const AuthorHandler = () => { - setAuthor("") - setShowAuthorField(!showAuthorField); - let url; - if (description) - url = Url("learning_objects", `"name" : "${search}", "author" : "", "description" : "${description}"`, currPage, "DESC") - else - url = Url("learning_objects", `"name" : "${search}", "author" : ""`, currPage, "DESC") - Filter(url); - }; - - const DescHandler = () => { - setDescription(null) - setShowDescriptionField(!showDescriptionField); - let url; - url = Url("learning_objects", `"name" : "${search}", "author" : "${author}"`, currPage, "DESC") - Filter(url); - }; - - const StandartHandler = () => { - setSeacrh("") - setShowStandarSearchField(!showStandadSearch); - let url; - if (description) - url = Url("learning_objects", `"name" : "", "author" : "${author}", "description" : "${description}"`, currPage, "DESC") - else - url = Url("learning_objects", `"name" : "", "author" : "${author}"`, currPage, "DESC") - Filter(url); - }; + const [valueAuthor, setValueAuthor] = useState("") + const [description, setDescription] = useState(""); + const [valueDescription, setValueDescription] = useState("") - const handleClick = (event) => { - setAnchorEl(event.currentTarget); + const AuthorHandler = (event) => { + setValueAuthor(event.target.value) }; - const handleClose = () => { - setAnchorEl(null); + const DescHandler = (event) => { + setValueDescription(event.target.value) }; - const open = Boolean(anchorEl); - const id = open ? "simple-popover" : undefined; - - const OnChangeSearchHandler = (e) => { - setSeacrh(e.target.value); - let url; - if (description) - url = Url("learning_objects", `"name" : "${search}", "author" : "${author}", "description" : "${description}"`, currPage, "DESC") - else - url = Url("learning_objects", `"name" : "${search}", "author" : "${author}"`, currPage, "DESC") - Filter(url); + const StandartHandler = (event) => { + setValueSearch(event.target.value) }; - const onChangeAuthorHandler = (e) => { - setAuthor(e.target.value); - let url; - if (description) - url = Url("learning_objects", `"name" : "${search}", "author" : "${author}", "description" : "${description}"`, currPage, "DESC") - else - url = Url("learning_objects", `"name" : "${search}", "author" : "${author}"`, currPage, "DESC") - Filter(url); - }; - - const onChangeDescriptionHandler = (e) => { - setDescription(e.target.value); - let url; - if (description) - url = Url("learning_objects", `"name" : "${search}", "author" : "${author}", "description" : "${description}"`, currPage, "DESC") - else - url = Url("learning_objects", `"name" : "${search}", "author" : "${author}"`, currPage, "DESC") - Filter(url); - }; - // **************** About the PopOverMenu **************** - //Controlls the state of the Alert Dialog const HandleStateAlertDialog = (i) => { const obj = { ...items[i] }; @@ -214,60 +133,25 @@ const EducationalObjects = () => { setIsLoadingToDelete(i); }; - //Filters the search - const Filter = (api) => { - getRequest( - api, - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(addOndeLenght)); - }, - (error) => { - setError(true); - } - ) - }; - - //This function updates List every time the content of the api changes - const UpdtateListData = (api) => { - getRequest( - api, - (data, header) => { - setItems([...data.concat(addOndeLenght)]); - HandleSnack( - "A lista de dados foi atualizada", - true, - "success", - "#228B22" - ); - setIsUpdating(false); - }, - (error) => { - HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); - setIsUpdating(false); - } - ) - }; - //Called when user want to delete one institution async function DeleteHandler() { const id = deleteItem.id; HandleStateAlertDialog(null); deleteRequest( - DeleteFilter("institutions", id), + DeleteFilter("learning_objects", id), (data) => { if (data.errors) HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); else { HandleSnack( - "A instituição foi deletada com sucesso", + "O objeto educacional foi deletada com sucesso", true, "success", "#228B22" ); - currPage = 0; - UpdtateListData(Url("institutions", "", `${currPage}`, "DESC")); + setCurrPage(0) HandleStateCircularProgress(null); + removeItemFromList(id) } }, (error) => { @@ -277,33 +161,21 @@ const EducationalObjects = () => { ) } - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true); - getRequest( - api, - (data, header) => { - const arrData = [...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(addOndeLenght)); - } - setIsLoadingMoreItems(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoadingMoreItems(false); + const removeItemFromList = (itemId) => { + let index = -1; + for (let i = 0; i < items.length; i++) { + const element = items[i]; + if (element.id === itemId) { + index = i + break } - ) - }; + } + if (index !== -1) { + const cpyItems = [...items] + cpyItems.splice(index, 1) + setItems(cpyItems) + } + } const DisplayDate = (date) => { const convertedData = moment.utc(date); @@ -312,28 +184,79 @@ const EducationalObjects = () => { .toString(); }; + const buildUrl = (author, description, name) => { + if (author && description && name) + return Url("learning_objects", `"author" : "${author}", "description" : "${description}", "name" : "${name}"`, currPage, "DESC") + + else if (author && name) + return Url("learning_objects", `"author" : "${author}", "name" : "${name}"`, currPage, "DESC") + else if (author && description) + return Url("learning_objects", `"author" : "${author}", "description" : "${description}"`, currPage, "DESC") + else if (name && description) + return Url("learning_objects", `"name" : "${name}", "description" : "${description}"`, currPage, "DESC") + + else if (author) + return Url("learning_objects", `"author" : "${author}"`, currPage, "DESC") + else if (description) + return Url("learning_objects", `"description" : "${description}"`, currPage, "DESC") + else if (name) + return Url("learning_objects", `"name" : "${name}"`, currPage, "DESC") + else + return Url("learning_objects", "", currPage, "DESC") + } + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) getRequest( - Url("learning_objects", `"name" : "${search}", "author" : "${author}"`, `${currPage}`, "DESC"), + buildUrl(author, description, search), (data, header) => { - setIsLoaded(true); - setItems(data.concat(addOndeLenght)); + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') + } else { + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } + } + setIsLoaded(true) + setIsLoadingMoreItems(false) }, (error) => { - setError(true); - + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) } ) - }, []); + }, [currPage, search, description, author]) + + useEffect(() => { + setCurrPage(0) + setSeacrh("") + setValueSearch("") + setDescription("") + setValueDescription("") + setAuthor("") + setValueAuthor("") + }, [showFilter]) if (error) { return <div>Error: {error.message}</div>; } - if (!isLoaded) { + else if (!isLoaded) { return <LoadingSpinner text="Carregando..." /> } else { //Words that defines that column - const topTable = [ + const TOP_TABLE = [ "CRIADO EM", "NOME", "DESCRIÇÃO", @@ -343,46 +266,31 @@ const EducationalObjects = () => { "DELETAR", ]; - //Buttons from PopOverMenu - const flatButtonsFromPopOverMenu = [ - { - label: "Pesquisa padrão", - onClick: StandartHandler, - color: showStandadSearch ? "primary" : "default", - }, - { - label: "Autor", - onClick: AuthorHandler, - color: showAuthorField ? "primary" : "default", - }, - { - label: "Descrição", - onClick: DescHandler, - color: showDescriptionField ? "primary" : "default", - }, - ]; - //Field of the Filter const TextFieldOfTheFilter = [ { label: "Pesquisar", - show: showStandadSearch, - onChange: (event) => OnChangeSearchHandler(event), - hide: StandartHandler, + value: valueSearch, + onChange: (event) => StandartHandler(event), + onBlur: (event) => setSeacrh(event.target.value), + helperText: "Ao terminar de digitar no campo, retire o foco do campo de texto" }, { label: "Autor", - show: showAuthorField, - onChange: (event) => onChangeAuthorHandler(event), - hide: AuthorHandler, + value: valueAuthor, + onChange: (event) => AuthorHandler(event), + onBlur: (event) => setAuthor(event.target.value), + helperText: "Ao terminar de digitar no campo, retire o foco do campo de texto" }, { label: "Descrição", - show: showDescriptionField, - onChange: (event) => onChangeDescriptionHandler(event), - hide: DescHandler, + value: valueDescription, + onChange: (event) => DescHandler(event), + onBlur: (event) => setDescription(event.target.value), + helperText: "Ao terminar de digitar no campo, retire o foco do campo de texto" }, ]; + if (WINDOW_WIDTH <= 1058) { return ( <div> @@ -400,109 +308,58 @@ const EducationalObjects = () => { }) } /> + <AlertDialog + open={openAlertDialog} + OnDelete={DeleteHandler} + deleteItem={deleteItem} + HandleClose={() => { + setOpenAlertDialog(false); + HandleStateCircularProgress(null); + }} + /> {/************** Start of the header **************/} - <Paper style={{ padding: "1em" }}> - <Grid container spacing={3} direction="row" alignItems="center"> + <MobilePageHeader + title="Objetos educacionais" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + } + ]} + > + { + showFilter && <Grid item xs={12}> - <Typography className={classes.paper} variant="h4"> - Lista de objetos educacionais - </Typography> - </Grid> - <Grid - item - xs={12} - - > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - aria-describedby={id} - variant="contained" - color="secondary" - className={classes.button} - onClick={(event) => { - handleClick(event) - }} - startIcon={ - <FilterListRoundedIcon style={{ fill: "white" }} /> - } - > - Filtrar - </Button> - <Popover - id={id} - open={open} - anchorEl={anchorEl} - onClose={handleClose} - anchorOrigin={{ - vertical: "bottom", - horizontal: "center", - }} - transformOrigin={{ - vertical: "top", - horizontal: "center", - }} - > - {flatButtonsFromPopOverMenu.map((flat, index) => ( - <Button - key={index} - onClick={flat.onClick} - color={flat.color} - > - {flat.label} - </Button> - ))} - </Popover> - </Grid> - - <Grid item> - <Button - variant="contained" - color="secondary" - className={classes.button} - startIcon={<UpdateRoundedIcon />} - disabled={isUpdating} - onClick={() => { - currPage = 0; - setIsUpdating(true); - if (description) - UpdtateListData(Url("learning_objects", `"name" : "${search}", "author" : "${author}", "description" : "${description}"`, currPage, "DESC")) - else - UpdtateListData(Url("learning_objects", `"name" : "${search}", "author" : "${author}"`, currPage, "DESC")) - }} - > - {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} - </Button> - </Grid> + <Grid container justify="space-between" spacing={3}> + {TextFieldOfTheFilter.map((field, index) => ( + <Grid item key={field.label}> + <TextField + id={index} + label={field.label} + type="search" + onChange={field.onChange} + onBlur={field.onBlur} + value={field.value} + helperText={field.helperText} + /> + </Grid> + ))} </Grid> </Grid> - </Grid> - <Grid item xs={12}> - <Grid container justify="space-between" spacing={3}> - {TextFieldOfTheFilter.map((field, index) => ( - <Grid item key={index}> - {field.show ? ( - <div> - <TextField - id={index} - label={field.label} - type="search" - onChange={field.onChange} - /> - <IconButton - size="small" - color="primary" - onClick={field.hide} - > - <CancelRoundedIcon /> - </IconButton> - </div> - ) : null} - </Grid> - ))} - </Grid> - </Grid> - </Paper> + } + </MobilePageHeader> {/************** End of the header **************/} <div style={{ height: "2em" }}></div> @@ -512,18 +369,14 @@ const EducationalObjects = () => { index === items.length - 1 ? ( <StyledDivButton> <Button - key={index} + key={new Date().toISOString() + row.created_at} color="primary" variant="text" // disabled={isLoadingMoreItems} startIcon={<AddRoundedIcon />} disabled={isLoadingMoreItems} onClick={() => { - currPage++ - if (description) - LoadMoreItens(Url("learning_objects", `"name" : "${search}", "author" : "${author}", "description" : "${description}"`, currPage, "DESC")) - else - LoadMoreItens(Url("learning_objects", `"name" : "${search}", "author" : "${author}"`, currPage, "DESC")) + setCurrPage(currPage + 1) }} > {isLoadingMoreItems ? ( @@ -536,14 +389,14 @@ const EducationalObjects = () => { ) : ( <> <MobileList - key={index} + key={new Date().toISOString() + row.created_at} title={row.name} subtitle={row.id} backColor={"#673ab7"} avatar={<MenuBookRoundedIcon />} - href={`/admin/learningObject/${row.id}`} + href={`/admin/learningObject?learnObj=${row.id}`} reset={() => { - currPage = 0; + }} data={ [ @@ -563,6 +416,21 @@ const EducationalObjects = () => { title: "Score", subtitle: row.score }, + { + title: "Deletar", + subtitle: + <Button + variant="contained" + color="secondary" + onClick={() => { + HandleStateAlertDialog(index); + HandleStateCircularProgress(index); + }} + startIcon={<DeleteIcon />} + > + Deletar + </Button> + } ] } /> @@ -592,117 +460,58 @@ const EducationalObjects = () => { } /> {/************** Start of the header **************/} - <Paper style={{ padding: "1em" }}> - <Grid container spacing={3} direction="row" alignItems="center"> - <Grid item xs={6}> - <Typography className={classes.paper} variant="h4"> - Lista de objetos educacionais - </Typography> - </Grid> - <Grid - item - xs={6} - > - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - aria-describedby={id} - variant="contained" - color="secondary" - className={classes.button} - onClick={(event) => { - handleClick(event) - }} - startIcon={ - <FilterListRoundedIcon style={{ fill: "white" }} /> - } - > - Filtrar - </Button> - <Popover - id={id} - open={open} - anchorEl={anchorEl} - onClose={handleClose} - anchorOrigin={{ - vertical: "bottom", - horizontal: "center", - }} - transformOrigin={{ - vertical: "top", - horizontal: "center", - }} - > - {flatButtonsFromPopOverMenu.map((flat, index) => ( - <Button - key={index} - onClick={flat.onClick} - color={flat.color} - > - {flat.label} - </Button> - ))} - </Popover> - </Grid> - - <Grid item> - <Button - variant="contained" - color="secondary" - className={classes.button} - startIcon={<UpdateRoundedIcon />} - disabled={isUpdating} - onClick={() => { - currPage = 0; - setIsUpdating(true); - if (description) - UpdtateListData(Url("learning_objects", `"name" : "${search}", "author" : "${author}", "description" : "${description}"`, currPage, "DESC")) - else - UpdtateListData(Url("learning_objects", `"name" : "${search}", "author" : "${author}"`, currPage, "DESC")) - }} - > - {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} - </Button> - </Grid> + <PageHeader + title="Objetos educacionais" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + } + ]} + > + { + showFilter && + <Grid item xs={12}> + <Grid container justify="space-between" spacing={3}> + {TextFieldOfTheFilter.map((field, index) => ( + <Grid item key={field.label}> + <TextField + id={index} + label={field.label} + type="search" + onChange={field.onChange} + onBlur={field.onBlur} + value={field.value} + helperText={field.helperText} + /> + </Grid> + ))} </Grid> </Grid> - </Grid> - <Grid item xs={12}> - <Grid container justify="space-between" spacing={3}> - {TextFieldOfTheFilter.map((field, index) => ( - <Grid item key={index}> - {field.show ? ( - <div> - <TextField - id={index} - label={field.label} - type="search" - onChange={field.onChange} - /> - <IconButton - size="small" - color="primary" - onClick={field.hide} - > - <CancelRoundedIcon /> - </IconButton> - </div> - ) : null} - </Grid> - ))} - </Grid> - </Grid> - </Paper> + } + </PageHeader> {/************** End of the header **************/} <div style={{ height: "2em" }}></div> {/************** Start of display data in table **************/} - <TableData top={topTable}> + <TableData top={TOP_TABLE}> <TableBody> {items.map((row, index) => index === items.length - 1 ? ( - <StyledTableRow key={index}> + <StyledTableRow key={new Date().toISOString() + row.created_at}> {/* Button to load more data */} <StyledTableCell> <Button @@ -713,11 +522,7 @@ const EducationalObjects = () => { isLoadingMoreItems } onClick={() => { - currPage++ - if (description) - LoadMoreItens(Url("learning_objects", `"name" : "${search}", "author" : "${author}", "description" : "${description}"`, currPage, "DESC")) - else - LoadMoreItens(Url("learning_objects", `"name" : "${search}", "author" : "${author}"`, currPage, "DESC")) + setCurrPage(currPage + 1) }} > {isLoadingMoreItems ? ( @@ -729,7 +534,7 @@ const EducationalObjects = () => { </StyledTableCell> </StyledTableRow> ) : ( - <StyledTableRow key={index}> + <StyledTableRow key={new Date().toISOString() + index}> <StyledTableCell component="th" scope="row"> {DisplayDate(row.created_at)} </StyledTableCell> @@ -746,11 +551,8 @@ const EducationalObjects = () => { {row.score} </StyledTableCell> <StyledTableCell align="right"> - <Link to={`/admin/learningObject/${row.id}`}> - <IconButton onClick={() => { - currPage = 0 - - }}> + <Link to={`/admin/learningObject?learnObj=${row.id}`}> + <IconButton> <VisibilityIcon style={{ fill: "#00bcd4" }} /> </IconButton> </Link> diff --git a/src/Admin/Pages/Pages/SubPages/Institutions.js b/src/Admin/Pages/Pages/SubPages/Institutions.js index d8f41e7dac618091750a2fd09e8bb5e0d72c6e48..7f713b9e4f42d42c906092fc0c3e1baccbdb1080 100644 --- a/src/Admin/Pages/Pages/SubPages/Institutions.js +++ b/src/Admin/Pages/Pages/SubPages/Institutions.js @@ -22,6 +22,9 @@ import TableData from "../../../Components/Components/Table"; import SnackBar from "../../../../Components/SnackbarComponent"; import AlertDialog from "../../../Components/Components/AlertDialog"; import LoadingSpinner from '../../../../Components/LoadingSpinner'; +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import PageHeader from "../../../Components/Components/PageHeader" // Imports about icon import FilterListRoundedIcon from "@material-ui/icons/FilterListRounded"; import AddRoundedIcon from "@material-ui/icons/AddRounded"; @@ -30,833 +33,575 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import IconButton from "@material-ui/core/IconButton"; -import CancelRoundedIcon from "@material-ui/icons/CancelRounded"; import VisibilityIcon from "@material-ui/icons/Visibility"; import DeleteIcon from "@material-ui/icons/Delete"; // Import from material-ui -import { withStyles, makeStyles } from "@material-ui/core/styles"; +import { withStyles } from "@material-ui/core/styles"; import Paper from "@material-ui/core/Paper"; import Button from "@material-ui/core/Button"; import Grid from "@material-ui/core/Grid"; -import { Typography, CircularProgress } from "@material-ui/core"; -import Popover from "@material-ui/core/Popover"; +import { CircularProgress } from "@material-ui/core"; import TextField from "@material-ui/core/TextField"; // services import { getRequest, deleteRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' //Filters -import { Url, GetOneOfAllUrl, DeleteFilter } from "../../../Filters"; +import { Url, DeleteFilter } from "../../../Filters"; //router -import { Link } from 'react-router-dom'; +import { Link, useHistory } from 'react-router-dom'; import styled from "styled-components" -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" import AccountBalanceRoundedIcon from "@material-ui/icons/AccountBalanceRounded"; -let currPage = 0; -let transformListToAsc = false - const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + "&:nth-of-type(odd)": { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); -const useStyles = makeStyles((theme) => ({ - root: { - flexGrow: 1, - }, - paper: { - padding: theme.spacing(1), - textAlign: "start", - }, - button: { - margin: theme.spacing(1), - alignSelf: "flex-end", - }, -})); - const Institutions = () => { - const classes = useStyles(); - const WINDOW_WIDTH = window.innerWidth - - const addOndeLenght = [""]; - - 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 [deleteItem, setDeleteItem] = useState({}); //Delete Item - const [isLoadingToDelete, setIsLoadingToDelete] = useState(null); - const [isUpdating, setIsUpdating] = useState(false); - const [isLoadingMoreItems, setIsLoadingMoreItems] = useState(false); - - const [openAlertDialog, setOpenAlertDialog] = useState(false); - - const [snackInfo, setSnackInfo] = useState({ - message: "", - icon: "", - open: false, - color: "", + const WINDOW_WIDTH = window.innerWidth + const ADD_ONE_LENGHT = [""]; + + const router = useHistory() + + const [invertList, setInvertList] = useState(false) + 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 [showFilter, setShowFilter] = useState(false) + const [currPage, setCurrPage] = useState(0) + const [deleteItem, setDeleteItem] = useState({}); //Delete Item + const [isLoadingToDelete, setIsLoadingToDelete] = useState(null); + const [isLoadingMoreItems, setIsLoadingMoreItems] = useState(false); + + const [openAlertDialog, setOpenAlertDialog] = useState(false); + + const [snackInfo, setSnackInfo] = useState({ + message: "", + icon: "", + open: false, + color: "", + }); + + const [search, setSeacrh] = useState(""); + const [valueOfSearch, setValueOfSearch] = useState("") + const [city, setCity] = useState(""); + const [valueOfCity, setValueOfCity] = useState("") + const [country, setCountry] = useState(""); + const [valueOfCountry, setValueOfCountry] = useState("") + const [description, setDescription] = useState(""); + const [valueOfDescription, setValueOfDescription] = useState("") + + const OnChangeSearchHandler = (e) => { + setValueOfSearch(e.target.value); + }; + + const onChangeCityHandler = (e) => { + setValueOfCity(e.target.value); + }; + + const onChangeCountryHandler = (e) => { + setValueOfCountry(e.target.value); + }; + + const onChangeDescriptionHandler = (e) => { + setValueOfDescription(e.target.value); + }; + // **************** About the PopOverMenu **************** + + //Controlls the state of the Alert Dialog + const HandleStateAlertDialog = (i) => { + const obj = { ...items[i] }; + setDeleteItem(obj); + setOpenAlertDialog(!openAlertDialog); + }; + + //Controlls the state and the informations of the snack + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color, }); - - // **************** About the PopOver Menu **************** - const [anchorEl, setAnchorEl] = React.useState(null); - const [showCityField, setShowCityField] = useState(false); //show the text field of filter by city - const [showContryField, setShowCountryField] = useState(false); //show the text field of the filter by country - const [showDescriptionField, setShowDescriptionField] = useState(false); //show the text field of the filter by description - const [showStandadSearch, setShowStandarSearchField] = useState(false); - - const [isFilteringByName, setisFilteringByName] = useState(false); - const [isFilteringByCity, setisFilteringByCity] = useState(false); - const [isFilteringByCounty, setisFilteringByCountry] = useState(false); - const [isFilteringByDesc, setisFilteringByDesc] = useState(false); - - const [search, setSeacrh] = useState(""); - const [city, setCity] = useState(""); - const [country, setCountry] = useState(""); - const [description, setDescription] = useState(""); - - const CityHandler = () => { - currPage = 0; - transformListToAsc = false - setShowCityField(!showCityField); - setisFilteringByCity(!isFilteringByCity); - UpdtateListData(Url("institutions", "", `${currPage}`, "DESC")); - }; - - const CountryHandler = () => { - currPage = 0; - transformListToAsc = false - setShowCountryField(!showContryField); - UpdtateListData(Url("institutions", "", `${currPage}`, "DESC")); - setisFilteringByCountry(!isFilteringByCounty); - }; - - const DescHandler = () => { - currPage = 0; - transformListToAsc = false - setShowDescriptionField(!showDescriptionField); - setisFilteringByDesc(!isFilteringByDesc); - UpdtateListData(Url("institutions", "", `${currPage}`, "DESC")); - }; - - const StandartHandler = () => { - currPage = 0; - transformListToAsc = false - setShowStandarSearchField(!showStandadSearch); - setisFilteringByName(!isFilteringByName); - UpdtateListData(Url("institutions", "", `${currPage}`, "DESC")); - }; - - const handleClick = (event) => { - setAnchorEl(event.currentTarget); - }; - - const handleClose = () => { - setAnchorEl(null); - }; - - const open = Boolean(anchorEl); - const id = open ? "simple-popover" : undefined; - - const OnChangeSearchHandler = (e) => { - setSeacrh(e.target.value); - Filter(GetOneOfAllUrl("institutions", `"name" : "${search}"`)); - }; - - const onChangeCityHandler = (e) => { - setCity(e.target.value); - Filter(GetOneOfAllUrl("institutions", `"city" : "${city}"`)); - }; - - const onChangeCountryHandler = (e) => { - setCountry(e.target.value); - Filter(GetOneOfAllUrl("institutions", `"country" : "${country}"`)); - }; - - const onChangeDescriptionHandler = (e) => { - setDescription(e.target.value); - Filter(GetOneOfAllUrl("institutions", `"description" : "${description}"`)); - }; - // **************** About the PopOverMenu **************** - - //Controlls the state of the Alert Dialog - const HandleStateAlertDialog = (i) => { - const obj = { ...items[i] }; - setDeleteItem(obj); - setOpenAlertDialog(!openAlertDialog); - }; - - //Controlls the state and the informations of the snack - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color, - }); - }; - - //Defines which row must show the circular progress - const HandleStateCircularProgress = (i) => { - setIsLoadingToDelete(i); - }; - - //Filters the search - const Filter = (api) => { - getRequest( - api, - (data, header) => { - const arrData = [...data]; - transformListToAsc = false - setItems(arrData.concat(addOndeLenght)); - }, - (error) => { - setError(true); - } - ) - }; - - //This function updates List every time the content of the api changes - const UpdtateListData = (api) => { - getRequest( - api, - (data, header) => { - const arrData = [...data]; - setItems(arrData.concat(addOndeLenght)); - HandleSnack( - "A lista de dados foi atualizada", - true, - "success", - "#228B22" - ); - setIsUpdating(false); - }, - (error) => { - HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); - setIsUpdating(false); - } - ) - }; - - //Called when user want to delete one institution - async function DeleteHandler() { - const id = deleteItem.id; - HandleStateAlertDialog(null); - deleteRequest( - DeleteFilter("institutions", id), - (data) => { - if (data.errors) - HandleSnack("Ocorreu algum erro!", true, "warning", "#FA8072"); - else { - HandleSnack( - "A instituição foi deletada com sucesso", - true, - "success", - "#228B22" - ); - currPage = 0; - transformListToAsc = false - UpdtateListData(Url("institutions", "", `${currPage}`, "DESC")); - HandleStateCircularProgress(null); - } - }, - (error) => { - HandleSnack("Ocorreu algum erro!", true, "warning", "#FA8072"); - HandleStateCircularProgress(null); - } - ) + }; + + //Defines which row must show the circular progress + const HandleStateCircularProgress = (i) => { + setIsLoadingToDelete(i); + }; + + //Called when user want to delete one institution + async function DeleteHandler() { + const id = deleteItem.id; + HandleStateAlertDialog(null); + deleteRequest( + DeleteFilter("institutions", id), + (data) => { + if (data.errors) + HandleSnack("Ocorreu algum erro!", true, "warning", "#FA8072"); + else { + HandleSnack( + "A instituição foi deletada com sucesso", + true, + "success", + "#228B22" + ); + setCurrPage(0) + removeItemFromList(id); + HandleStateCircularProgress(null); + } + }, + (error) => { + HandleSnack("Ocorreu algum erro!", true, "warning", "#FA8072"); + HandleStateCircularProgress(null); + } + ) + } + + const removeItemFromList = (itemId) => { + let index = -1; + for (let i = 0; i < items.length; i++) { + const element = items[i]; + if (element.id === itemId) { + index = i + break + } } - - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true); - getRequest( - api, - (data, header) => { - const arrData = [...data]; - console.log(arrData); - 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(addOndeLenght)); - } - setIsLoadingMoreItems(false); - }, - (error) => { - HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); - setIsLoadingMoreItems(false); + if (index !== -1) { + const cpyItems = [...items] + cpyItems.splice(index, 1) + setItems(cpyItems) + } + } + + const cleanArrayAndInvert = () => { + setInvertList(!invertList) + setCurrPage(0) + setItems([]) + } + + const buildUrl = () => { + return Url("institutions", `"name" : "${search}", "description" : "${description}", "city" : "${city}", "country" : "${country}"`, currPage, invertList ? "ASC" : "DESC") + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + buildUrl(), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') + } else { + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } + } + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, description, country, search, city, invertList]) + + useEffect(() => { + setSeacrh("") + setDescription("") + setCountry("") + setCity("") + setValueOfDescription("") + setValueOfSearch("") + setValueOfCountry("") + setValueOfCity("") + setCurrPage(0) + }, [showFilter]) + + if (error) { + return <div>Error: {error.message}</div>; + } + else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." /> + } else { + //Words that defines that column + const topTable = [ + "ID", + "NOME", + "DESCRIÇÃO", + "CIDADE", + "PAÃS", + "VISUALIZAR", + "DELETAR", + ]; + + //Field of the Filter + const TextFieldOfTheFilter = [ + { + label: "Pesquisar", + value: valueOfSearch, + helperText: "Ao digitar, retire o foco do campo", + onChange: (event) => OnChangeSearchHandler(event), + onBlur: (event) => setSeacrh(event.target.value) + }, + { + label: "Cidade", + value: valueOfCity, + helperText: "Ao digitar, retire o foco do campo", + onChange: (event) => onChangeCityHandler(event), + onBlur: (event) => setCity(event.target.value) + }, + { + label: "PaÃs", + value: valueOfCountry, + helperText: "Ao digitar, retire o foco do campo", + onChange: (event) => onChangeCountryHandler(event), + onBlur: (event) => setCountry(event.target.value) + + }, + { + label: "Descrição", + value: valueOfDescription, + helperText: "Ao digitar, retire o foco do campo", + onChange: (event) => onChangeDescriptionHandler(event), + onBlur: (event) => setDescription(event.target.value) + }, + ]; + + if (WINDOW_WIDTH <= 977) { + return ( + <div> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) } - ) - }; - - const InvertList = async () => { - transformListToAsc = !transformListToAsc - currPage = 0 - if (transformListToAsc) { - getRequest( - Url('institutions', '', `${currPage}`, 'ASC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(addOndeLenght)) + /> + <AlertDialog + open={openAlertDialog} + OnDelete={DeleteHandler} + deleteItem={deleteItem} + HandleClose={() => { + setOpenAlertDialog(false); + HandleStateCircularProgress(null); + }} + /> + {/************** Start of the header **************/} + <MobilePageHeader + title="Instituições" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) - } else { - getRequest( - Url('institutions', '', `${currPage}`, 'DESC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(addOndeLenght)) + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); }, - (error) => { - HandleSnack('institutions ao carregar os dados', true, 'warning', '#FA8072') - } - ) - } - } - - useEffect(() => { - getRequest( - Url("institutions", "", `${currPage}`, "DESC"), - (data, header) => { - setIsLoaded(true); - setItems(data.concat(addOndeLenght)); - }, - (error) => { - setError(true); + icon: <FilterListRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/InstitutionCreate') + }, + icon: <AddRoundedIcon /> + } + ]} + > + { + showFilter && + <Grid item xs={12}> + <Grid container justify="space-between" spacing={3}> + {TextFieldOfTheFilter.map((field, index) => ( + <Grid item key={field.label}> + <TextField + id={index} + label={field.label} + value={field.value} + helperText={field.helperText} + onChange={field.onChange} + onBlur={field.onBlur} + /> + </Grid> + ))} + </Grid> + </Grid> } - ) - }, []); - - if (error) { - return <div>Error: {error.message}</div>; + </MobilePageHeader> + {/************** End of the header **************/} + + <div style={{ height: "2em" }}></div> + + {/************** Start of display data in table **************/} + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton + key={new Date().toISOString() + row.created_at} + > + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledDivButton> + ) : ( + <> + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.name} + subtitle={row.id} + backColor={"#ff7f00"} + avatar={<AccountBalanceRoundedIcon />} + href={`/admin/institution?institution=${row.id}`} + reset={() => { + + }} + data={ + [ + { + title: "Descrição", + subtitle: row.description ? row.description : "Sem dado" + + }, + { + title: "Cidade", + subtitle: row.city ? row.city : "Sem dado" + + }, + { + title: "PaÃs", + subtitle: row.country ? row.country : "Sem dado" + }, + { + title: "Deletar", + subtitle: + <Button + variant="contained" + color="secondary" + onClick={() => { + HandleStateAlertDialog(index); + HandleStateCircularProgress(index); + }} + startIcon={<DeleteIcon />} + > + Deletar + </Button> + } + ] + } + /> + <div style={{ height: "0.5em" }} /> + </> + ) + )} + {/************** End of display data in table **************/} + + {/* This alert will be displayed if the user click to delete an institution */} + </div> + ) } - if (!isLoaded) { - return <LoadingSpinner text="Carregando..." /> - } else { - //Words that defines that column - const topTable = [ - "ID", - "NOME", - "DESCRIÇÃO", - "CIDADE", - "PAÃS", - "VISUALIZAR", - "DELETAR", - ]; - - //Buttons from PopOverMenu - const flatButtonsFromPopOverMenu = [ - { - label: "Pesquisa padrão", - onClick: StandartHandler, - color: showStandadSearch ? "primary" : "default", - }, - { - label: "Cidade", - onClick: CityHandler, - color: showCityField ? "primary" : "default", - }, - { - label: "PaÃs", - onClick: CountryHandler, - color: showContryField ? "primary" : "default", - }, - { - label: "Descrição", - onClick: DescHandler, - color: showDescriptionField ? "primary" : "default", - }, - ]; - - //Field of the Filter - const TextFieldOfTheFilter = [ - { - label: "Pesquisar", - show: showStandadSearch, - onChange: (event) => OnChangeSearchHandler(event), - hide: StandartHandler, - }, - { - label: "Cidade", - show: showCityField, - onChange: (event) => onChangeCityHandler(event), - hide: CityHandler, - }, - { - label: "PaÃs", - show: showContryField, - onChange: (event) => onChangeCountryHandler(event), - hide: CountryHandler, - }, + else { + return ( + <div> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) + } + /> + {/************** Start of the header **************/} + <PageHeader + title="Instituições" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/InstitutionCreate') + }, + icon: <AddRoundedIcon /> + } + ]} + > { - label: "Descrição", - show: showDescriptionField, - onChange: (event) => onChangeDescriptionHandler(event), - hide: DescHandler, - }, - ]; - - if (WINDOW_WIDTH <= 977) { - return ( - <div> - <SnackBar - severity={snackInfo.icon} - text={snackInfo.message} - snackbarOpen={snackInfo.open} - color={snackInfo.color} - handleClose={() => - setSnackInfo({ - message: "", - icon: "", - open: false, - color: "", - }) - } - /> - {/************** Start of the header **************/} - <Paper style={{ padding: "1em" }}> - <Grid container spacing={3} direction="row" alignItems="center"> - <Grid item xs={12}> - <Typography className={classes.paper} variant="h4"> - Lista de Instituições - </Typography> - </Grid> - <Grid - item - xs={12} - > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - aria-describedby={id} - variant="contained" - color="secondary" - className={classes.button} - onClick={handleClick} - startIcon={ - <FilterListRoundedIcon style={{ fill: "white" }} /> - } - > - Filtrar - </Button> - <Popover - id={id} - open={open} - anchorEl={anchorEl} - onClose={handleClose} - anchorOrigin={{ - vertical: "bottom", - horizontal: "center", - }} - transformOrigin={{ - vertical: "top", - horizontal: "center", - }} - > - {flatButtonsFromPopOverMenu.map((flat, index) => ( - <Button - key={index} - onClick={flat.onClick} - color={flat.color} - > - {flat.label} - </Button> - ))} - </Popover> - </Grid> - - <Grid item> - <Link style={{ textDecoration: 'none' }} to={'/admin/InstitutionCreate'}> - <Button - variant="contained" - color="secondary" - className={classes.button} - startIcon={<AddRoundedIcon style={{ fill: "white" }} />} - onClick={() => { - currPage = 0 - transformListToAsc = false - }} - > - Novo - </Button> - </Link> - </Grid> - - <Grid item> - <Button - variant="contained" - color="secondary" - className={classes.button} - startIcon={<UpdateRoundedIcon />} - disabled={isUpdating} - onClick={() => { - currPage = 0; - transformListToAsc = false - setIsUpdating(true); - UpdtateListData( - Url("institutions", "", `${currPage}`, "DESC") - ); - }} - > - {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - <Grid item xs={12}> - <Grid container justify="space-between" spacing={3}> - {TextFieldOfTheFilter.map((field, index) => ( - <Grid item key={index}> - {field.show ? ( - <div> - <TextField - id={index} - label={field.label} - type="search" - onChange={field.onChange} - /> - <IconButton - size="small" - color="primary" - onClick={field.hide} - > - <CancelRoundedIcon /> - </IconButton> - </div> - ) : null} - </Grid> - ))} - </Grid> - </Grid> - </Paper> - {/************** End of the header **************/} - - <div style={{ height: "2em" }}></div> - - {/************** Start of display data in table **************/} - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('institutions', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('institutions', '', `${currPage}`, 'DESC')) - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> + showFilter && + <Grid item xs={12}> + <Grid container justify="space-between" spacing={3}> + {TextFieldOfTheFilter.map((field, index) => ( + <Grid item key={field.label}> + <TextField + id={index} + label={field.label} + value={field.value} + helperText={field.helperText} + onChange={field.onChange} + onBlur={field.onBlur} + /> + </Grid> + ))} + </Grid> + </Grid> + } + </PageHeader> + {/************** End of the header **************/} + + <div style={{ height: "2em" }}></div> + + {/************** Start of display data in table **************/} + <TableData top={topTable} onIconPressed={cleanArrayAndInvert}> + <TableBody> + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledTableRow key={new Date().toISOString() + row.created_at}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color="primary" + variant="text" + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> ) : ( - <> - <MobileList - key={index} - title={row.name} - subtitle={row.id} - backColor={"#ff7f00"} - avatar={<AccountBalanceRoundedIcon />} - href={`/admin/institution/${row.id}`} - reset={() => { - currPage = 0 - transformListToAsc = false - }} - data={ - [ - { - title: "Descrição", - subtitle: row.description ? row.description : "Sem dado" - - }, - { - title: "Cidade", - subtitle: row.city ? row.city : "Sem dado" - - }, - { - title: "PaÃs", - subtitle: row.country ? row.country : "Sem dado" - }, - ] - } - /> - <div style={{ height: "0.5em" }} /> - </> - ) - )} - {/************** End of display data in table **************/} - - {/* This alert will be displayed if the user click to delete an institution */} - </div> - ) - } - else { - return ( - <div> - <SnackBar - severity={snackInfo.icon} - text={snackInfo.message} - snackbarOpen={snackInfo.open} - color={snackInfo.color} - handleClose={() => - setSnackInfo({ - message: "", - icon: "", - open: false, - color: "", - }) - } - /> - {/************** Start of the header **************/} - <Paper style={{ padding: "1em" }}> - <Grid container spacing={3} direction="row" alignItems="center"> - <Grid item xs={6}> - <Typography className={classes.paper} variant="h4"> - Lista de Instituições - </Typography> - </Grid> - <Grid - item - xs={6} + "Carregar mais itens" + )} + </Button> + </StyledTableCell> + </StyledTableRow> + ) : ( + <StyledTableRow key={new Date().toISOString() + index}> + <StyledTableCell component="th" scope="row"> + {row.id} + </StyledTableCell> + <StyledTableCell align="right">{row.name}</StyledTableCell> + <StyledTableCell align="right"> + {row.description} + </StyledTableCell> + <StyledTableCell align="right">{row.city}</StyledTableCell> + <StyledTableCell align="right"> + {row.country} + </StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/institution?institution=${row.id}`}> + <IconButton> + <VisibilityIcon style={{ fill: "#00bcd4" }} /> + </IconButton> + </Link> + </StyledTableCell> + <StyledTableCell align="right"> + {isLoadingToDelete === index ? ( + <CircularProgress size={24} color="primary" /> + ) : ( + <IconButton + onClick={() => { + HandleStateAlertDialog(index); + HandleStateCircularProgress(index); + }} > - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - aria-describedby={id} - variant="contained" - color="secondary" - className={classes.button} - onClick={handleClick} - startIcon={ - <FilterListRoundedIcon style={{ fill: "white" }} /> - } - > - Filtrar - </Button> - <Popover - id={id} - open={open} - anchorEl={anchorEl} - onClose={handleClose} - anchorOrigin={{ - vertical: "bottom", - horizontal: "center", - }} - transformOrigin={{ - vertical: "top", - horizontal: "center", - }} - > - {flatButtonsFromPopOverMenu.map((flat, index) => ( - <Button - key={index} - onClick={flat.onClick} - color={flat.color} - > - {flat.label} - </Button> - ))} - </Popover> - </Grid> - - <Grid item> - <Link style={{ textDecoration: 'none' }} to={'/admin/InstitutionCreate'}> - <Button - variant="contained" - color="secondary" - className={classes.button} - startIcon={<AddRoundedIcon style={{ fill: "white" }} />} - onClick={() => { - currPage = 0 - transformListToAsc = false - }} - > - Novo - </Button> - </Link> - </Grid> - - <Grid item> - <Button - variant="contained" - color="secondary" - className={classes.button} - startIcon={<UpdateRoundedIcon />} - disabled={isUpdating} - onClick={() => { - currPage = 0; - transformListToAsc = false - setIsUpdating(true); - UpdtateListData( - Url("institutions", "", `${currPage}`, "DESC") - ); - }} - > - {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - <Grid item xs={12}> - <Grid container justify="space-between" spacing={3}> - {TextFieldOfTheFilter.map((field, index) => ( - <Grid item key={index}> - {field.show ? ( - <div> - <TextField - id={index} - label={field.label} - type="search" - onChange={field.onChange} - /> - <IconButton - size="small" - color="primary" - onClick={field.hide} - > - <CancelRoundedIcon /> - </IconButton> - </div> - ) : null} - </Grid> - ))} - </Grid> - </Grid> - </Paper> - {/************** End of the header **************/} - - <div style={{ height: "2em" }}></div> - - {/************** Start of display data in table **************/} - <TableData top={topTable} onIconPressed={InvertList}> - <TableBody> - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledTableRow key={index}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color="primary" - variant="text" - startIcon={<AddRoundedIcon />} - disabled={ - isLoadingMoreItems || - isFilteringByCity || - isFilteringByCounty || - isFilteringByDesc || - isFilteringByName - } - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('institutions', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('institutions', '', `${currPage}`, 'DESC')) - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledTableCell> - </StyledTableRow> - ) : ( - <StyledTableRow key={index}> - <StyledTableCell component="th" scope="row"> - {row.id} - </StyledTableCell> - <StyledTableCell align="right">{row.name}</StyledTableCell> - <StyledTableCell align="right"> - {row.description} - </StyledTableCell> - <StyledTableCell align="right">{row.city}</StyledTableCell> - <StyledTableCell align="right"> - {row.country} - </StyledTableCell> - <StyledTableCell align="right"> - <Link to={`/admin/institution/${row.id}`}> - <IconButton onClick={() => { - currPage = 0 - transformListToAsc = false - }}> - <VisibilityIcon style={{ fill: "#00bcd4" }} /> - </IconButton> - </Link> - </StyledTableCell> - <StyledTableCell align="right"> - {isLoadingToDelete === index ? ( - <CircularProgress size={24} color="primary" /> - ) : ( - <IconButton - onClick={() => { - HandleStateAlertDialog(index); - HandleStateCircularProgress(index); - }} - > - <DeleteIcon style={{ fill: "#FF0000" }} /> - </IconButton> - )} - </StyledTableCell> - </StyledTableRow> - ) - )} - </TableBody> - </TableData> - {/************** End of display data in table **************/} - - {/* This alert will be displayed if the user click to delete an institution */} - <AlertDialog - open={openAlertDialog} - OnDelete={DeleteHandler} - deleteItem={deleteItem} - HandleClose={() => { - setOpenAlertDialog(false); - HandleStateCircularProgress(null); - }} - /> - </div> - ) - } + <DeleteIcon style={{ fill: "#FF0000" }} /> + </IconButton> + )} + </StyledTableCell> + </StyledTableRow> + ) + )} + </TableBody> + </TableData> + {/************** End of display data in table **************/} + + {/* This alert will be displayed if the user click to delete an institution */} + <AlertDialog + open={openAlertDialog} + OnDelete={DeleteHandler} + deleteItem={deleteItem} + HandleClose={() => { + setOpenAlertDialog(false); + HandleStateCircularProgress(null); + }} + /> + </div> + ) } + } }; export default Institutions; diff --git a/src/Admin/Pages/Pages/SubPages/Languages.js b/src/Admin/Pages/Pages/SubPages/Languages.js index 00693f02998a332451f42f0bc8aa744e8d4e28d9..c38ac1e1015d1ad352f23e597ee85240c4e28a2c 100644 --- a/src/Admin/Pages/Pages/SubPages/Languages.js +++ b/src/Admin/Pages/Pages/SubPages/Languages.js @@ -25,469 +25,406 @@ import { Url } from '../../../Filters'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; import { DeleteFilter } from '../../../Filters'; import { getRequest, deleteRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import PageHeader from "../../../Components/Components/PageHeader" //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 IconButton from '@material-ui/core/IconButton'; -import { Button, Typography, Paper, Grid } from '@material-ui/core'; +import { Button, Paper } 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 EditRoundedIcon from '@material-ui/icons/EditRounded'; import DeleteRoundedIcon from '@material-ui/icons/DeleteRounded'; //router -import { Link } from 'react-router-dom'; +import { Link, useHistory } from 'react-router-dom'; import styled from "styled-components" import LanguageRoundedIcon from "@material-ui/icons/LanguageRounded"; -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" - -let currPage = 0; -let transformListToAsc = false; const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const Languages = () => { - const ADD_ONE_LENGHT = [""]; - const TOP_LABELS = ['ID', 'NOME', 'CODE', 'EDITAR', 'DELETAR'] //Labels from Table - const WINDOW_WIDTH = window.innerWidth - - 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 - const [openAlertDialog, setOpenAlertDialog] = useState(false); //controlls the state od alert dialog - - const [deleteItem, setDeleteItem] = useState({}); //Delete Item - const [isLoadingToDelete, setIsLoadingToDelete] = useState(null); - - const [snackInfo, setSnackInfo] = useState({ - message: '', - icon: '', - open: false, - color: '', + const ADD_ONE_LENGHT = [""]; + const TOP_LABELS = ['ID', 'NOME', 'CODE', 'EDITAR', 'DELETAR'] //Labels from Table + const WINDOW_WIDTH = window.innerWidth + const router = useHistory() + + const [invertList, setInvertList] = useState(false) + 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 [openAlertDialog, setOpenAlertDialog] = useState(false); //controlls the state od alert dialog + const [currPage, setCurrPage] = useState(0) + + const [deleteItem, setDeleteItem] = useState({}); //Delete Item + const [isLoadingToDelete, setIsLoadingToDelete] = useState(null); + + const [snackInfo, setSnackInfo] = useState({ + message: '', + icon: '', + open: false, + color: '', + }) + + //handle snack info + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color }) - - //handle snack info - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color - }) - } - - //handle load more items - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true) - getRequest( - api, - (data, header) => { - const arrData = [...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)) - } - setIsLoadingMoreItems(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsLoadingMoreItems(false) - } - ) - } - - // handle update list data - const UpdateHandler = async (api) => { - setIsUpdating(true) - getRequest( - api, - (data, header) => { - HandleSnack('A lista de dados foi atualizada', true, 'success', '#228B22') - const arrData = [...data] - setItems(arrData.concat(ADD_ONE_LENGHT)) - setIsUpdating(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsUpdating(false) - } - ) + } + + //handle Delete + async function DeleteHandler() { + const id = deleteItem.id; + HandleStateAlertDialog(null); + deleteRequest( + DeleteFilter("languages", id), + (data) => { + if (data.errors) + HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); + else { + HandleSnack( + "A lÃngua foi deletada com sucesso", + true, + "success", + "#228B22" + ); + setCurrPage(0) + HandleStateCircularProgress(null); + removeItemFromList(id) + } + }, + (error) => { + HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); + HandleStateCircularProgress(null); + } + ) + } + + const HandleStateCircularProgress = (i) => { + setIsLoadingToDelete(i); + }; + + const HandleStateAlertDialog = (i) => { + const obj = { ...items[i] }; + setDeleteItem(obj); + setOpenAlertDialog(!openAlertDialog); + }; + + const removeItemFromList = (itemId) => { + let index = -1; + for (let i = 0; i < items.length; i++) { + const element = items[i]; + if (element.id === itemId) { + index = i + break + } } - - //handle Delete - async function DeleteHandler() { - const id = deleteItem.id; - HandleStateAlertDialog(null); - deleteRequest( - DeleteFilter("languages", id), - (data) => { - if (data.errors) - HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); - else { - HandleSnack( - "A lÃngua foi deletada com sucesso", - true, - "success", - "#228B22" - ); - currPage = 0; - transformListToAsc = false - UpdateHandler(Url("languages", "", `${currPage}`, "DESC")); - HandleStateCircularProgress(null); - } - }, - (error) => { - HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); - HandleStateCircularProgress(null); - } - ) + if (index !== -1) { + const cpyItems = [...items] + cpyItems.splice(index, 1) + setItems(cpyItems) } - - const HandleStateCircularProgress = (i) => { - setIsLoadingToDelete(i); - }; - - const HandleStateAlertDialog = (i) => { - const obj = { ...items[i] }; - setDeleteItem(obj); - setOpenAlertDialog(!openAlertDialog); - }; - - const InvertList = async () => { - transformListToAsc = !transformListToAsc - currPage = 0 - if (transformListToAsc) { - getRequest( - Url('languages', '', `${currPage}`, 'ASC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(ADD_ONE_LENGHT)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + } + + const cleanArrayAndInvert = () => { + setInvertList(!invertList) + setCurrPage(0) + setItems([]) + } + + //getting data from server + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + + getRequest( + Url("languages", "", currPage, invertList ? "ASC" : "DESC"), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') } else { - getRequest( - Url('languages', '', `${currPage}`, 'DESC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(ADD_ONE_LENGHT)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } } - } - - //getting data from server - useEffect(() => { - getRequest( - Url('languages', '', `${currPage}`, 'DESC'), - (data, header) => { - setIsLoaded(true); - setItems(data.concat(ADD_ONE_LENGHT)); - }, - (error) => { - setError(true); - } - ) - }, []); - - - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." /> - } else { - if (WINDOW_WIDTH <= 755) { - 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={12}> - <Typography variant="h4"> - Linguagens - </Typography> - </Grid> - <Grid - item - xs={12} - > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('languages', '', `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - <Grid item> - - <Link style={{ textDecoration: 'none' }} to={'/admin/languageCreate'}> - <Button - variant="contained" - color="secondary" - startIcon={<AddRoundedIcon />} - > - Novo - </Button> - </Link> - </Grid> - </Grid> - </Grid> - </Grid> - </Paper> - - <div style={{ height: '2em' }}></div> - - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('languages', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('languages', '', `${currPage}`, 'DESC')) - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.name} - subtitle={row.id} - backColor={"#e81f4f"} - avatar={<LanguageRoundedIcon />} - href={`/admin/languageEdit/${row.id}`} - reset={() => { - currPage = 0; - transformListToAsc = false - }} - data={ - [ - { - title: "Code", - subtitle: row.code - - }, - ] - } - /> - <div style={{ height: "0.5em" }} /> - </> - ) + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, invertList]) + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." /> + } else { + if (WINDOW_WIDTH <= 800) { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + <AlertDialog + open={openAlertDialog} + OnDelete={DeleteHandler} + deleteItem={deleteItem} + HandleClose={() => { + setOpenAlertDialog(false); + HandleStateCircularProgress(null); + }} + /> + <MobilePageHeader + title="Linguagens" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/languageCreate') + }, + icon: <AddRoundedIcon /> + } + ]} + > + </MobilePageHeader> + + <div style={{ height: '2em' }}></div> + + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton key={new Date().toISOString() + row.created_at}> + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" )} - </> - ); - } - else { - return ( + </Button> + </StyledDivButton> + ) : ( <> - <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"> - Linguagens - </Typography> - </Grid> - <Grid - item - xs={6} + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.name} + subtitle={row.id} + backColor={"#e81f4f"} + avatar={<LanguageRoundedIcon />} + href={`/admin/languageEdit?language=${row.id}`} + reset={() => { + + }} + data={ + [ + { + title: "Code", + subtitle: row.code + }, + { + title: "Deletar", + subtitle: + <Button + variant="contained" + color="secondary" + onClick={() => { + HandleStateAlertDialog(index); + HandleStateCircularProgress(index); + }} + startIcon={<DeleteRoundedIcon />} > - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('languages', '', `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - <Grid item> - - <Link style={{ textDecoration: 'none' }} to={'/admin/languageCreate'}> - <Button - variant="contained" - color="secondary" - startIcon={<AddRoundedIcon />} - > - Novo - </Button> - </Link> - </Grid> - </Grid> - </Grid> - </Grid> - </Paper> - - <div style={{ height: '2em' }}></div> - - <TableData - top={TOP_LABELS} - onIconPressed={InvertList} - > - <TableBody> - {items.map((row, index) => ( - index === items.length - 1 ? - <StyledTableRow key={index}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color='primary' - variant='text' - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('languages', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('languages', '', `${currPage}`, 'DESC')) - } - }} - > - { - isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' - } - </Button> - </StyledTableCell> - </StyledTableRow> - - : - - <StyledTableRow key={index}> - <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> - <StyledTableCell align="right">{row.name}</StyledTableCell> - <StyledTableCell align="right">{row.code}</StyledTableCell> - <StyledTableCell align="right"> - <Link to={`/admin/languageEdit/${row.id}`}> - <IconButton onClick={() => { currPage = 0; transformListToAsc = false }}> - <EditRoundedIcon style={{ fill: '#00bcd4' }} /> - </IconButton> - </Link> - </StyledTableCell> - <StyledTableCell align="right"> - {isLoadingToDelete === index ? ( - <CircularProgress size={24} color="primary" /> - ) : ( - <IconButton - onClick={() => { - HandleStateAlertDialog(index); - HandleStateCircularProgress(index); - }} - > - <DeleteRoundedIcon style={{ fill: "#FF0000" }} /> - </IconButton> - )} - </StyledTableCell> - </StyledTableRow> - ))} - </TableBody> - </TableData> - - {/* This alert will be displayed if the user click to delete an institution */} - <AlertDialog - open={openAlertDialog} - OnDelete={DeleteHandler} - deleteItem={deleteItem} - HandleClose={() => { - setOpenAlertDialog(false); - HandleStateCircularProgress(null); - }} - /> + Deletar + </Button> + } + ] + } + /> + <div style={{ height: "0.5em" }} /> </> - ); - } + ) + )} + </> + ); + } + else { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + + <PageHeader + title="Linguagens" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/languageCreate') + }, + icon: <AddRoundedIcon /> + } + ]} + > + </PageHeader> + + <div style={{ height: '2em' }}></div> + + <TableData + top={TOP_LABELS} + onIconPressed={cleanArrayAndInvert} + > + <TableBody> + {items.map((row, index) => ( + index === items.length - 1 ? + <StyledTableRow key={new Date().toISOString() + row.created_at}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color='primary' + variant='text' + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + { + isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' + } + </Button> + </StyledTableCell> + </StyledTableRow> + + : + + <StyledTableRow key={new Date().toISOString() + index}> + <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> + <StyledTableCell align="right">{row.name}</StyledTableCell> + <StyledTableCell align="right">{row.code}</StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/languageEdit?language=${row.id}`}> + <IconButton> + <EditRoundedIcon style={{ fill: '#00bcd4' }} /> + </IconButton> + </Link> + </StyledTableCell> + <StyledTableCell align="right"> + {isLoadingToDelete === index ? ( + <CircularProgress size={24} color="primary" /> + ) : ( + <IconButton + onClick={() => { + HandleStateAlertDialog(index); + HandleStateCircularProgress(index); + }} + > + <DeleteRoundedIcon style={{ fill: "#FF0000" }} /> + </IconButton> + )} + </StyledTableCell> + </StyledTableRow> + ))} + </TableBody> + </TableData> + + {/* This alert will be displayed if the user click to delete an institution */} + <AlertDialog + open={openAlertDialog} + OnDelete={DeleteHandler} + deleteItem={deleteItem} + HandleClose={() => { + setOpenAlertDialog(false); + HandleStateCircularProgress(null); + }} + /> + </> + ); } + } } export default Languages; diff --git a/src/Admin/Pages/Pages/SubPages/NoteVariables.js b/src/Admin/Pages/Pages/SubPages/NoteVariables.js index 16c39487c44ed81523beab4d0351ef1e07a5c093..1ad35f99a8c2a8c5a7e8340acfbd1d9551ec5473 100644 --- a/src/Admin/Pages/Pages/SubPages/NoteVariables.js +++ b/src/Admin/Pages/Pages/SubPages/NoteVariables.js @@ -19,7 +19,6 @@ import React, { useEffect, useState } from 'react'; //Material ui componets import { withStyles } from '@material-ui/core/styles'; import TableBody from '@material-ui/core/TableBody'; -import Grid from "@material-ui/core/Grid"; import Paper from "@material-ui/core/Paper"; import TableCell from '@material-ui/core/TableCell'; import TableRow from '@material-ui/core/TableRow'; @@ -35,386 +34,303 @@ import UpdateRoundedIcon from '@material-ui/icons/UpdateRounded' import TableData from '../../../Components/Components/Table'; import SnackBar from '../../../../Components/SnackbarComponent'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import PageHeader from "../../../Components/Components/PageHeader" + //Services import { getRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' import { Url } from '../../../Filters'; //routers import { Link } from 'react-router-dom'; import styled from "styled-components" -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" import TrendingUpRoundedIcon from "@material-ui/icons/TrendingUpRounded"; -let currPage = 0; //var that controlls the current page that we are -let transformListToAsc = false; - const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const NoteVariables = () => { - const WINDOW_WIDTH = window.innerWidth - const AddOneLenght = ['']; - 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) - const [isUpdating, setIsUpdating] = useState(false) + const WINDOW_WIDTH = window.innerWidth + const ADD_ONE_LENGHT = [""]; - const [snackInfo, setSnackInfo] = useState({ - message: '', - icon: '', - open: false, - color: '', - }) + const [invertList, setInvertList] = useState(false) + 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 [currPage, setCurrPage] = useState(0) + const [items, setItems] = useState([]); //Necessary to consult the API, data + const [isLoadingMoreItems, setIsLoadingMoreItems] = useState(false) - // Handle snack infos - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color - }) - } + const [snackInfo, setSnackInfo] = useState({ + message: '', + icon: '', + open: false, + color: '', + }) - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true) - getRequest( - api, - (data, header) => { - const arrData = [...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(AddOneLenght)) - } - setIsLoadingMoreItems(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsLoadingMoreItems(false) - } - ) - } + // Handle snack infos + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color + }) + } - const InvertList = async () => { - transformListToAsc = !transformListToAsc - currPage = 0 - if (transformListToAsc) { - getRequest( - Url('scores', '', `${currPage}`, 'ASC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + const cleanArrayAndInvert = () => { + setInvertList(!invertList) + setCurrPage(0) + setItems([]) + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + Url("scores", "", currPage, invertList ? "ASC" : "DESC"), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') } else { - getRequest( - Url('scores', '', `${currPage}`, 'DESC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } } - } - - const UpdateHandler = async (api) => { - setIsUpdating(true) - getRequest( - api, - (data, header) => { - HandleSnack('A lista de dados foi atualizada', true, 'success', '#228B22') - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - setIsUpdating(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsUpdating(false) - } - ) - } - - useEffect(() => { - getRequest( - Url('scores', '', '0', 'DESC'), - (data, header) => { - setIsLoaded(true); - setItems(data.concat(AddOneLenght)); - }, - (error) => { - setError(true); - } - ) - }, []); + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, invertList]) + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." /> + } else { - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." /> - } else { + //Words in the top part of the table + const topTable = ['ID', 'NOME', 'CÓDIGO', 'PESO', 'ATIVO', 'SCORE TYPE', 'VISUALIZAR']; - //Words in the top part of the table - const topTable = ['ID', 'NOME', 'CÓDIGO', 'PESO', 'ATIVO', 'SCORE TYPE', 'VISUALIZAR']; - - if (WINDOW_WIDTH <= 961) { - return ( - <div> - <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={12}> - <Typography variant="h4"> - Variáveis de nota - </Typography> - </Grid> - <Grid - item - xs={12} - > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('scores', '', `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - </Paper> + if (WINDOW_WIDTH <= 1000) { + return ( + <div> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + <MobilePageHeader + title="Variáveis de nota" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Inverter lista", + isLoading: false, + func: () => { + cleanArrayAndInvert() + }, + }, + ]} + > + </MobilePageHeader> - <div style={{ height: '2em' }}></div> + <div style={{ height: '2em' }}></div> - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('scores', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('scores', '', `${currPage}`, 'DESC')) - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.name} - subtitle={row.id} - backColor={"#e81f4f"} - avatar={<TrendingUpRoundedIcon />} - href={`/admin/noteVar/${row.id}`} - reset={() => { - currPage = 0; - }} - data={ - [ - { - title: "Código", - subtitle: row.code + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton key={new Date().toISOString() + row.created_at}> + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledDivButton> + ) : ( + <> + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.name} + subtitle={row.id} + backColor={"#e81f4f"} + avatar={<TrendingUpRoundedIcon />} + href={`/admin/noteVar?id=${row.id}`} + reset={() => { + }} + data={ + [ + { + title: "Código", + subtitle: row.code - }, - { - title: "Score Type", - subtitle: row.score_type + }, + { + title: "Score Type", + subtitle: row.score_type - }, - { - title: "Ativo", - subtitle: row.active ? <CheckRoundedIcon style={{ fill: '#3CB371' }} /> : <BlockRoundedIcon style={{ fill: '#FA8072' }} /> - }, - ] - } - /> - <div style={{ height: "0.5em" }} /> - </> - ) - )} - </div> - ) - } - else { - return ( - <div> - <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"> - Variáveis de nota - </Typography> - </Grid> - <Grid - item - xs={6} - > - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('scores', '', `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24}/> : 'Atualizar' - } - </Button> - </Grid> - </Grid> - </Grid> - </Grid> - </Paper> + }, + { + title: "Ativo", + subtitle: row.active ? <CheckRoundedIcon style={{ fill: '#3CB371' }} /> : <BlockRoundedIcon style={{ fill: '#FA8072' }} /> + }, + ] + } + /> + <div style={{ height: "0.5em" }} /> + </> + ) + )} + </div> + ) + } + else { + return ( + <div> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + <PageHeader + title="Variáveis de nota" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + ]} + > + </PageHeader> - <div style={{ height: '2em' }}></div> + <div style={{ height: '2em' }}></div> - <TableData - top={topTable} - onIconPressed={InvertList} - > - <TableBody> - {items.map((row, index) => ( - index === items.length - 1 ? - <StyledTableRow key={index}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color='primary' - variant='text' - disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('scores', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('scores', '', `${currPage}`, 'DESC')) - } - }} - > - { - isLoadingMoreItems ? <CircularProgress /> : 'Carregar mais itens' - } - </Button> - </StyledTableCell> - </StyledTableRow> + <TableData + top={topTable} + onIconPressed={cleanArrayAndInvert} + > + <TableBody> + {items.map((row, index) => ( + index === items.length - 1 ? + <StyledTableRow key={new Date().toISOString() + row.created_at}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color='primary' + variant='text' + disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + { + isLoadingMoreItems ? <CircularProgress /> : 'Carregar mais itens' + } + </Button> + </StyledTableCell> + </StyledTableRow> - : + : - <StyledTableRow key={index}> - <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> - <StyledTableCell align="right">{row.name}</StyledTableCell> - <StyledTableCell align="right">{row.code}</StyledTableCell> - <StyledTableCell align="right">{row.weight}</StyledTableCell> - <StyledTableCell align="right"> - { - row.active ? <CheckRoundedIcon style={{ fill: '#3CB371' }} /> : <BlockRoundedIcon style={{ fill: '#FA8072' }} /> - } - </StyledTableCell> - <StyledTableCell align="right"> - { - row['score_type'].map((item) => ( - <Typography key={item} style={{ fontSize: 14 }}> - {item} - </Typography> - )) - } - </StyledTableCell> - <StyledTableCell align="right"> - <Link to={`/admin/noteVar/${row.id}`}> - <IconButton onClick={() => { currPage = 0; transformListToAsc = false }}> - <VisibilityIcon style={{ fill: '#00bcd4' }} /> - </IconButton> - </Link> - </StyledTableCell> - </StyledTableRow> - ))} - </TableBody> - </TableData> - </div> - ) - } + <StyledTableRow key={new Date().toISOString() + index}> + <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> + <StyledTableCell align="right">{row.name}</StyledTableCell> + <StyledTableCell align="right">{row.code}</StyledTableCell> + <StyledTableCell align="right">{row.weight}</StyledTableCell> + <StyledTableCell align="right"> + { + row.active ? <CheckRoundedIcon style={{ fill: '#3CB371' }} /> : <BlockRoundedIcon style={{ fill: '#FA8072' }} /> + } + </StyledTableCell> + <StyledTableCell align="right"> + { + row['score_type'].map((item) => ( + <Typography key={item} style={{ fontSize: 14 }}> + {item} + </Typography> + )) + } + </StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/noteVar?id=${row.id}`}> + <IconButton> + <VisibilityIcon style={{ fill: '#00bcd4' }} /> + </IconButton> + </Link> + </StyledTableCell> + </StyledTableRow> + ))} + </TableBody> + </TableData> + </div> + ) } + } } diff --git a/src/Admin/Pages/Pages/SubPages/Permissions.js b/src/Admin/Pages/Pages/SubPages/Permissions.js index a630739ddad8d375b8255faff563043b878694bf..787ac0de2893aeaa4107d7c57d3ef43935fe78dd 100644 --- a/src/Admin/Pages/Pages/SubPages/Permissions.js +++ b/src/Admin/Pages/Pages/SubPages/Permissions.js @@ -25,479 +25,418 @@ import { Url } from '../../../Filters'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; import { DeleteFilter } from '../../../Filters'; import { getRequest, deleteRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import PageHeader from "../../../Components/Components/PageHeader" //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 { Button, Typography, Paper, Grid } from '@material-ui/core'; +import { Button, Paper } 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 EditRoundedIcon from '@material-ui/icons/EditRounded'; import DeleteRoundedIcon from '@material-ui/icons/DeleteRounded'; //router -import { Link } from 'react-router-dom'; +import { Link, useHistory } from 'react-router-dom'; import styled from "styled-components" import AccountCircleRoundedIcon from "@material-ui/icons/AccountCircleRounded" -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" - -let currPage = 0; -let transformListToAsc = false; const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const UserPermissions = () => { - const ADD_ONE_LENGHT = [""]; - const TOP_LABELS = ['ID', 'NOME', 'DESCRIÇÃO', 'AÇÕES'] //Labels from Table - const WINDOW_WIDTH = window.innerWidth - - 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 - const [openAlertDialog, setOpenAlertDialog] = useState(false); //controlls the state od alert dialog - - const [deleteItem, setDeleteItem] = useState({}); //Delete Item - const [isLoadingToDelete, setIsLoadingToDelete] = useState(null); - - const [snackInfo, setSnackInfo] = useState({ - message: '', - icon: '', - open: false, - color: '', + const ADD_ONE_LENGHT = [""]; + const TOP_LABELS = ['ID', 'NOME', 'DESCRIÇÃO', 'AÇÕES'] //Labels from Table + const WINDOW_WIDTH = window.innerWidth + + const router = useHistory() + + const [invertList, setInvertList] = useState(false) + 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 [currPage, setCurrPage] = useState(0) + const [isLoadingMoreItems, setIsLoadingMoreItems] = useState(false) //controlls the state of loadind more data + const [openAlertDialog, setOpenAlertDialog] = useState(false); //controlls the state od alert dialog + + const [deleteItem, setDeleteItem] = useState({}); //Delete Item + const [isLoadingToDelete, setIsLoadingToDelete] = useState(null); + + const [snackInfo, setSnackInfo] = useState({ + message: '', + icon: '', + open: false, + color: '', + }) + + //handle snack info + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color }) - - //handle snack info - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color - }) - } - - //handle load more items - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true) - getRequest( - api, - (data, header) => { - const arrData = [...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)) - } - setIsLoadingMoreItems(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsLoadingMoreItems(false) - } - ) - } - - // handle update list data - const UpdateHandler = async (api) => { - setIsUpdating(true) - getRequest( - api, - (data, header) => { - HandleSnack('A lista de dados foi atualizada', true, 'success', '#228B22') - const arrData = [...data] - setItems(arrData.concat(ADD_ONE_LENGHT)) - setIsUpdating(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsUpdating(false) - } - ) + } + + //handle Delete + async function DeleteHandler() { + const id = deleteItem.id; + HandleStateAlertDialog(null); + deleteRequest( + DeleteFilter("roles", id), + (data) => { + if (data.errors) + HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); + else { + HandleSnack( + "A lÃngua foi deletada com sucesso", + true, + "success", + "#228B22" + ); + setCurrPage(0) + HandleStateCircularProgress(null); + removeItemFromList(id) + } + }, + (error) => { + HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); + HandleStateCircularProgress(null); + } + ) + } + + const removeItemFromList = (itemId) => { + let index = -1; + for (let i = 0; i < items.length; i++) { + const element = items[i]; + if (element.id === itemId) { + index = i + break + } } - - //handle Delete - async function DeleteHandler() { - const id = deleteItem.id; - HandleStateAlertDialog(null); - deleteRequest( - DeleteFilter("roles", id), - (data) => { - if (data.errors) - HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); - else { - HandleSnack( - "A lÃngua foi deletada com sucesso", - true, - "success", - "#228B22" - ); - currPage = 0; - transformListToAsc = false - UpdateHandler(Url("roles", "", `${currPage}`, "DESC")); - HandleStateCircularProgress(null); - } - }, - (error) => { - HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); - HandleStateCircularProgress(null); - } - ) + if (index !== -1) { + const cpyItems = [...items] + cpyItems.splice(index, 1) + setItems(cpyItems) } - - const HandleStateCircularProgress = (i) => { - setIsLoadingToDelete(i); - }; - - const HandleStateAlertDialog = (i) => { - const obj = { ...items[i] }; - setDeleteItem(obj); - setOpenAlertDialog(!openAlertDialog); - }; - - const InvertList = async () => { - transformListToAsc = !transformListToAsc - currPage = 0 - if (transformListToAsc) { - getRequest( - Url('roles', '', `${currPage}`, 'ASC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(ADD_ONE_LENGHT)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + } + + const HandleStateCircularProgress = (i) => { + setIsLoadingToDelete(i); + }; + + const HandleStateAlertDialog = (i) => { + const obj = { ...items[i] }; + setDeleteItem(obj); + setOpenAlertDialog(!openAlertDialog); + }; + + const cleanArrayAndInvert = () => { + setInvertList(!invertList) + setCurrPage(0) + setItems([]) + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + Url("roles", "", currPage, invertList ? "ASC" : "DESC"), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') } else { - getRequest( - Url('roles', '', `${currPage}`, 'DESC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(ADD_ONE_LENGHT)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } } - } - - //getting data from server - useEffect(() => { - getRequest( - Url('roles', '', `${currPage}`, 'DESC'), - (data, header) => { - setIsLoaded(true); - setItems(data.concat(ADD_ONE_LENGHT)); - }, - (error) => { - setError(true); - } - ) - }, []); - - - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." /> - } else { - if (WINDOW_WIDTH <= 760) { - 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={12}> - <Typography variant="h4"> - Lista de permissões de usuário - </Typography> - </Grid> - <Grid - item - xs={12} - > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('roles', '', `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - <Grid item> - - <Link style={{ textDecoration: 'none' }} to={'/admin/CreateRole'}> - <Button - variant="contained" - color="secondary" - startIcon={<AddRoundedIcon />} - onClick={() => { currPage = 0 }} - > - Novo - </Button> - </Link> - </Grid> - </Grid> - </Grid> - </Grid> - </Paper> - - <div style={{ height: '2em' }}></div> - - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('roles', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('roles', '', `${currPage}`, 'DESC')) - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.name} - subtitle={row.id} - backColor={"#ff7f00"} - avatar={<AccountCircleRoundedIcon />} - href={`/admin/EditPermissions/${row.id}`} - reset={() => { - currPage = 0; - }} - data={ - [ - { - title: "Descrição", - subtitle: row.description - - }, - ] - } - /> - <div style={{ height: "0.5em" }} /> - </> - ) + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, invertList]) + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." /> + } else { + if (WINDOW_WIDTH <= 800) { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + <AlertDialog + open={openAlertDialog} + OnDelete={DeleteHandler} + deleteItem={deleteItem} + HandleClose={() => { + setOpenAlertDialog(false); + HandleStateCircularProgress(null); + }} + /> + <MobilePageHeader + title="Lista de permissões de usuário" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/CreateRole') + }, + icon: <AddRoundedIcon /> + }, + { + name: "Inverter lista", + isLoading: false, + func: () => { + cleanArrayAndInvert() + }, + } + ]} + > + </MobilePageHeader> + + <div style={{ height: '2em' }}></div> + + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton key={new Date().toISOString() + row.created_at}> + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" )} - </> - ); - } - else { - return ( + </Button> + </StyledDivButton> + ) : ( <> - <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"> - Lista de permissões de usuário - </Typography> - </Grid> - <Grid - item - xs={6} - > - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('roles', '', `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - <Grid item> - - <Link style={{ textDecoration: 'none' }} to={'/admin/CreateRole'}> - <Button - variant="contained" - color="secondary" - startIcon={<AddRoundedIcon />} - onClick={() => { currPage = 0 }} - > - Novo - </Button> - </Link> - </Grid> - </Grid> - </Grid> - </Grid> - </Paper> - - <div style={{ height: '2em' }}></div> - - <TableData - top={TOP_LABELS} - onIconPressed={InvertList} - > - <TableBody> - {items.map((row, index) => ( - index === items.length - 1 ? - <StyledTableRow key={index}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color='primary' - variant='text' - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('roles', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('roles', '', `${currPage}`, 'DESC')) - } - }} - > - { - isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' - } - </Button> - </StyledTableCell> - </StyledTableRow> - - : - - <StyledTableRow key={index}> - <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> - <StyledTableCell align="right">{row.name}</StyledTableCell> - <StyledTableCell align="right">{row.description}</StyledTableCell> - <StyledTableCell align="right"> - <Link to={`/admin/EditPermissions/${row.id}`}> - <Button - style={{ width: "100%", marginBottom: "0.5em" }} - variant="contained" - color="primary" - onClick={() => { currPage = 0 }} - startIcon={<EditRoundedIcon />} - > - Editar - </Button> - </Link> - - {isLoadingToDelete === index ? ( - <CircularProgress size={24} color="primary" /> - ) : ( - <Button - style={{ width: "100%" }} - variant="contained" - color="secondary" - onClick={() => { - HandleStateAlertDialog(index) - HandleStateCircularProgress(index) - }} - startIcon={<DeleteRoundedIcon />} - > - Deletar + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.name} + subtitle={row.id} + backColor={"#ff7f00"} + avatar={<AccountCircleRoundedIcon />} + href={`/admin/EditPermissions?role=${row.id}`} + reset={() => { + }} + data={ + [ + { + title: "Descrição", + subtitle: row.description + + }, + { + title: "Ações", + subtitle: <Button + variant="contained" + color="secondary" + onClick={() => { + HandleStateAlertDialog(index) + HandleStateCircularProgress(index) + }} + startIcon={<DeleteRoundedIcon />} + > + Deletar </Button> - )} - - </StyledTableCell> - </StyledTableRow> - ))} - </TableBody> - </TableData> - - {/* This alert will be displayed if the user click to delete an institution */} - <AlertDialog - open={openAlertDialog} - OnDelete={DeleteHandler} - deleteItem={deleteItem} - HandleClose={() => { - setOpenAlertDialog(false); - HandleStateCircularProgress(null); - }} - /> + }, + ] + } + /> + <div style={{ height: "0.5em" }} /> </> - ); - } + ) + )} + </> + ); + } + else { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + + <PageHeader + title="Lista de permissões de usuário" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/CreateRole') + }, + icon: <AddRoundedIcon /> + } + ]} + > + </PageHeader> + + <div style={{ height: '2em' }}></div> + + <TableData + top={TOP_LABELS} + onIconPressed={cleanArrayAndInvert} + > + <TableBody> + {items.map((row, index) => ( + index === items.length - 1 ? + <StyledTableRow key={new Date().toISOString() + row.created_at}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color='primary' + variant='text' + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + { + isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' + } + </Button> + </StyledTableCell> + </StyledTableRow> + + : + + <StyledTableRow key={new Date().toISOString() + index}> + <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> + <StyledTableCell align="right">{row.name}</StyledTableCell> + <StyledTableCell align="right">{row.description}</StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/EditPermissions?role=${row.id}`}> + <Button + style={{ width: "100%", marginBottom: "0.5em" }} + variant="contained" + color="primary" + startIcon={<EditRoundedIcon />} + > + Editar + </Button> + </Link> + + {isLoadingToDelete === index ? ( + <CircularProgress size={24} color="primary" /> + ) : ( + <Button + style={{ width: "100%" }} + variant="contained" + color="secondary" + onClick={() => { + HandleStateAlertDialog(index) + HandleStateCircularProgress(index) + }} + startIcon={<DeleteRoundedIcon />} + > + Deletar + </Button> + )} + + </StyledTableCell> + </StyledTableRow> + ))} + </TableBody> + </TableData> + + {/* This alert will be displayed if the user click to delete an institution */} + <AlertDialog + open={openAlertDialog} + OnDelete={DeleteHandler} + deleteItem={deleteItem} + HandleClose={() => { + setOpenAlertDialog(false); + HandleStateCircularProgress(null); + }} + /> + </> + ); } + } } export default UserPermissions; diff --git a/src/Admin/Pages/Pages/SubPages/Questions.js b/src/Admin/Pages/Pages/SubPages/Questions.js index 8118ec31d8bc7667baeffd9b349337efa591e5b3..ca32e0cd11a506134b40c2801dde53209d615cb2 100644 --- a/src/Admin/Pages/Pages/SubPages/Questions.js +++ b/src/Admin/Pages/Pages/SubPages/Questions.js @@ -16,553 +16,413 @@ 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, useContext } from 'react' +import React, { useEffect, useState } from 'react' import moment from 'moment'; //imports from local files import TableData from '../../../Components/Components/Table'; import SnackBar from '../../../../Components/SnackbarComponent'; -import Unauthorized from '../../../Components/Components/Unauthorized'; import { Url, EditFilter } from '../../../Filters'; -import { Store } from '../../../../Store'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; import { getRequest, putRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import PageHeader from "../../../Components/Components/PageHeader" //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 { Button, Typography, Paper, Grid } from '@material-ui/core'; +import { Button, Paper } 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 CheckCircleRoundedIcon from '@material-ui/icons/CheckCircleRounded'; -import CancelRoundedIcon from '@material-ui/icons/CancelRounded'; import Switch from '@material-ui/core/Switch'; //router -import { Link } from 'react-router-dom'; +import { useHistory } from 'react-router-dom'; import styled from "styled-components" -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" import HelpRoundedIcon from "@material-ui/icons/HelpRounded"; -let currPage = 0; -let transformListToAsc = false; - const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const Questions = () => { - const { state } = useContext(Store); - - const ADD_ONE_LENGHT = [""]; - const WINDOW_WIDTH = window.innerWidth - const TOP_LABELS = ['ID', 'CRIAÇÃO EM', 'DESCRIÇÃO', 'STATUS', 'ATUALIZAÇÃO EM'] //Labels from Table - - 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 - - const [snackInfo, setSnackInfo] = useState({ - message: '', - icon: '', - open: false, - color: '', + const ADD_ONE_LENGHT = [""]; + const WINDOW_WIDTH = window.innerWidth + const TOP_LABELS = ['ID', 'CRIAÇÃO EM', 'DESCRIÇÃO', 'STATUS', 'ATUALIZAÇÃO EM'] //Labels from Table + const router = useHistory() + + const [invertList, setInvertList] = useState(false) + 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 [currPage, setCurrPage] = useState(0) + const [isLoadingMoreItems, setIsLoadingMoreItems] = useState(false) //controlls the state of loadind more data + + const [snackInfo, setSnackInfo] = useState({ + message: '', + icon: '', + open: false, + color: '', + }) + + //handle snack info + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color }) - - //handle snack info - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color - }) - } - - const CheckUserPermission = () => { - let canUserEdit = false; - - if (state.userIsLoggedIn) { - const roles = [...state.currentUser.roles]; - for (let i = 0; i < roles.length; i++) - if (roles[i].name === 'admin') - canUserEdit = true; + } + + const changeStateItem = (index, currState) => { + const copyItems = [...items] + copyItems[index].status = currState + setItems(copyItems) + } + + const handleChange = async (index, status) => { + const id = items[index].id; + const description = items[index].description; + if (status === 'active') { + const body = { + "question": { + "description": description, + "status": "inactive" } - else { - canUserEdit = false; + } + putRequest( + EditFilter('questions', id), + body, + (data) => { + if (data.errors) + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + else { + HandleSnack('Question modificada com sucesso', true, 'success', '#228B22') + changeStateItem(index, "inactive") + setCurrPage(0) + } + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') } - - return canUserEdit; - } - - //handle load more items - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true) - getRequest( - api, - (data, header) => { - const arrData = [...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)) - } - setIsLoadingMoreItems(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsLoadingMoreItems(false) - } - ) - } - - // handle update list data - const UpdateHandler = async (api) => { - setIsUpdating(true) - getRequest( - api, - (data, header) => { - HandleSnack('A lista de dados foi atualizada', true, 'success', '#228B22') - const arrData = [...data] - setItems(arrData.concat(ADD_ONE_LENGHT)) - setIsUpdating(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsUpdating(false) - } - ) + ) + } else { + const body = { + "question": { + "description": description, + "status": "active" + } + } + putRequest( + EditFilter('questions', id), + body, + (data) => { + if (data.errors) + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + else { + setCurrPage(0) + HandleSnack('Question modificada com sucesso', true, 'success', '#228B22') + changeStateItem(index, "active") + } + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + } + ) } - - const InvertList = async () => { - transformListToAsc = !transformListToAsc - currPage = 0 - if (transformListToAsc) { - getRequest( - Url('questions', '', `${currPage}`, 'ASC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(ADD_ONE_LENGHT)) - }, - () => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + } + + const DisplayDate = (date) => { + const convertedData = moment.utc(date); + return moment(convertedData) + .format("LLL") + .toString(); + }; + + const cleanArrayAndInvert = () => { + setInvertList(!invertList) + setCurrPage(0) + setItems([]) + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + Url("questions", "", currPage, invertList ? "ASC" : "DESC"), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') } else { - getRequest( - Url('questions', '', `${currPage}`, 'DESC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(ADD_ONE_LENGHT)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } } - } - - const handleChange = async (index, status) => { - const id = items[index].id; - const description = items[index].description; - if (status === 'active') { - const body = { - "question": { - "description": description, - "status": "inactive" - } - } - putRequest( - EditFilter('questions', id), - body, - (data) => { - if (data.errors) - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - else { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('questions', '', `${currPage}`, 'DESC')) - } + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, invertList]) + + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." /> + } else { + if (WINDOW_WIDTH <= 800) { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + + <MobilePageHeader + title="Perguntas da curadoria" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) - } else { - const body = { - "question": { - "description": description, - "status": "active" - } - } - putRequest( - EditFilter('questions', id), - body, - (data) => { - if (data.errors) - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - else { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('questions', '', `${currPage}`, 'DESC')) - } + icon: <UpdateRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/CreateQuestion') }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) - } - } - - const DisplayDate = (date) => { - const convertedData = moment.utc(date); - return moment(convertedData) - .format("LLL") - .toString(); - }; - - //getting data from server - useEffect(() => { - getRequest( - Url('questions', '', `${currPage}`, 'DESC'), - (data, header) => { - setIsLoaded(true); - setItems(data.concat(ADD_ONE_LENGHT)); - }, - (error) => { - setError(true) - } - ) - }, []); - - - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." /> - } else if (CheckUserPermission()) { - if (WINDOW_WIDTH <= 761) { - 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={12}> - <Typography variant="h4"> - Perguntas da curadoria - </Typography> - </Grid> - <Grid - item - xs={12} - > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('questions', '', `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - <Grid item> - - <Link style={{ textDecoration: 'none' }} to={'/admin/CreateQuestion'}> - <Button - variant="contained" - color="secondary" - startIcon={<AddRoundedIcon />} - onClick={() => { currPage = 0 }} - > - Novo - </Button> - </Link> - </Grid> - </Grid> - </Grid> - </Grid> - </Paper> - - <div style={{ height: '2em' }}></div> - - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('questions', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('questions', '', `${currPage}`, 'DESC')) - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.id} - subtitle={DisplayDate(row.created_at)} - backColor={"#673ab7"} - avatar={<HelpRoundedIcon />} - reset={() => { - currPage = 0; transformListToAsc = false - }} - data={ - [ - { - title: "Descrição", - subtitle: row.description - }, - { - title: "Status", - subtitle: - row.status === 'active' ? - <Grid container direction='row'> - <Grid item> - <CheckCircleRoundedIcon style={{ fill: '#3CB371' }} /> - - <Switch - checked={true} - onChange={() => handleChange(index, row.status)} - name="checkedB" - color="primary" - /> - </Grid> - </Grid> - - : - - <Grid container justify='flex-end' alignItems='center' direction='row'> - <Grid item> - <CancelRoundedIcon style={{ fill: '#FA8072' }} /> - </Grid> - - <Grid item> - <Switch - checked={false} - onChange={() => handleChange(index, row.status)} - name="checkedB" - color="primary" - /> - </Grid> - </Grid> - }, - { - title : "Atualizado em", - subtitle : DisplayDate(row.updated_at) - } - ] - } - /> - <div style={{ height: "0.5em" }} /> - </> - ) + icon: <AddRoundedIcon /> + }, + { + name: "Inverter lista", + isLoading: false, + func: () => { + cleanArrayAndInvert() + }, + }, + ]} + > + </MobilePageHeader> + + <div style={{ height: '2em' }}></div> + + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton + key={new Date().toISOString() + row.created_at} + > + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" )} - </> - ); - } - else { - return ( + </Button> + </StyledDivButton> + ) : ( <> - <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"> - Perguntas da curadoria - </Typography> - </Grid> - <Grid - item - xs={6} - > - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('questions', '', `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - <Grid item> - - <Link style={{ textDecoration: 'none' }} to={'/admin/CreateQuestion'}> - <Button - variant="contained" - color="secondary" - startIcon={<AddRoundedIcon />} - onClick={() => { currPage = 0; transformListToAsc = false }} - > - Novo - </Button> - </Link> - </Grid> - </Grid> - </Grid> - </Grid> - </Paper> - - <div style={{ height: '2em' }}></div> - - <TableData - top={TOP_LABELS} - onIconPressed={InvertList} - > - <TableBody> - {items.map((row, index) => ( - index === items.length - 1 ? - <StyledTableRow key={index}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color='primary' - variant='text' - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('questions', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('questions', '', `${currPage}`, 'DESC')) - } - }} - > - { - isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' - } - </Button> - </StyledTableCell> - </StyledTableRow> - - : - - <StyledTableRow key={index}> - <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> - <StyledTableCell align="right">{DisplayDate(row.created_at)}</StyledTableCell> - <StyledTableCell align="right">{row.description}</StyledTableCell> - <StyledTableCell align="right"> - { - row.status === 'active' ? - <Grid container direction='row'> - <Grid item> - <CheckCircleRoundedIcon style={{ fill: '#3CB371' }} /> - - <Switch - checked={true} - onChange={() => handleChange(index, row.status)} - name="checkedB" - color="primary" - /> - </Grid> - </Grid> - - : - - <Grid container justify='flex-end' alignItems='center' direction='row'> - <Grid item> - <CancelRoundedIcon style={{ fill: '#FA8072' }} /> - </Grid> - - <Grid item> - <Switch - checked={false} - onChange={() => handleChange(index, row.status)} - name="checkedB" - color="primary" - /> - </Grid> - </Grid> - } - </StyledTableCell> - <StyledTableCell align="right">{DisplayDate(row.updated_at)}</StyledTableCell> - </StyledTableRow> - ))} - </TableBody> - </TableData> + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.id} + subtitle={DisplayDate(row.created_at)} + backColor={"#673ab7"} + avatar={<HelpRoundedIcon />} + reset={() => { + }} + data={ + [ + { + title: "Descrição", + subtitle: row.description + }, + { + title: "Status", + subtitle: + row.status === 'active' ? + <Switch + checked={true} + onChange={() => handleChange(index, row.status)} + name="checkedB" + color="primary" + /> + : + + <Switch + checked={false} + onChange={() => handleChange(index, row.status)} + name="checkedB" + color="primary" + /> + }, + { + title: "Atualizado em", + subtitle: DisplayDate(row.updated_at) + } + ] + } + /> + <div style={{ height: "0.5em" }} /> </> - ); - } - } else return <Unauthorized /> + ) + )} + </> + ); + } + else { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + + <PageHeader + title="Perguntas da curadoria" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/CreateQuestion') + }, + icon: <AddRoundedIcon /> + } + ]} + > + </PageHeader> + + <div style={{ height: '2em' }}></div> + + <TableData + top={TOP_LABELS} + onIconPressed={cleanArrayAndInvert} + > + <TableBody> + {items.map((row, index) => ( + index === items.length - 1 ? + <StyledTableRow key={new Date().toISOString() + row.created_at}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color='primary' + variant='text' + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + { + isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' + } + </Button> + </StyledTableCell> + </StyledTableRow> + + : + + <StyledTableRow key={new Date().toISOString() + index}> + <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> + <StyledTableCell align="right">{DisplayDate(row.created_at)}</StyledTableCell> + <StyledTableCell align="right">{row.description}</StyledTableCell> + <StyledTableCell align="right"> + { + row.status === 'active' ? + <Switch + checked={true} + onChange={() => handleChange(index, row.status)} + name="checkedB" + color="primary" + /> + : + + <Switch + checked={false} + onChange={() => handleChange(index, row.status)} + name="checkedB" + color="primary" + /> + } + </StyledTableCell> + <StyledTableCell align="right">{DisplayDate(row.updated_at)}</StyledTableCell> + </StyledTableRow> + ))} + </TableBody> + </TableData> + </> + ); + } + } } export default Questions; diff --git a/src/Admin/Pages/Pages/SubPages/Rating.js b/src/Admin/Pages/Pages/SubPages/Rating.js index 547e140ddf41a9b427bc7fabe894d71bac16be5e..22d57d409dfe56f9b649f36c9ad4b67d10cd923c 100644 --- a/src/Admin/Pages/Pages/SubPages/Rating.js +++ b/src/Admin/Pages/Pages/SubPages/Rating.js @@ -20,476 +20,410 @@ import React, { useEffect, useState } from 'react'; //Material ui componets import { withStyles } from '@material-ui/core/styles'; import TableBody from '@material-ui/core/TableBody'; -import Grid from "@material-ui/core/Grid"; import Paper from "@material-ui/core/Paper"; import TableCell from '@material-ui/core/TableCell'; import TableRow from '@material-ui/core/TableRow'; import IconButton from '@material-ui/core/IconButton'; import VisibilityIcon from '@material-ui/icons/Visibility'; -import { Button, Typography } from '@material-ui/core'; +import { Button } 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 DeleteRoundedIcon from '@material-ui/icons/DeleteRounded'; -//Local files +//Local files' import TableData from '../../../Components/Components/Table'; import SnackBar from '../../../../Components/SnackbarComponent'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import PageHeader from "../../../Components/Components/PageHeader" //Services import AlertDialog from "../../../Components/Components/AlertDialog"; import { Url } from '../../../Filters'; import { DeleteFilter } from '../../../Filters'; import { getRequest, deleteRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' //routers -import { Link } from 'react-router-dom'; +import { Link, useHistory } from 'react-router-dom'; import StarRoundedIcon from "@material-ui/icons/StarRounded"; import styled from "styled-components" -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" - -let currPage = 0; //var that controlls the current page that we are -let transformListToAsc = false; const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const Ratings = () => { - const WINDOW_WIDTH = window.innerWidth - const AddOneLenght = ['']; - 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) - const [isUpdating, setIsUpdating] = useState(false) - - const [openAlertDialog, setOpenAlertDialog] = useState(false); //controlls the state od alert dialog - const [deleteItem, setDeleteItem] = useState({}); //Delete Item - const [isLoadingToDelete, setIsLoadingToDelete] = useState(null); - - const [snackInfo, setSnackInfo] = useState({ - message: '', - icon: '', - open: false, - color: '', + const WINDOW_WIDTH = window.innerWidth + const ADD_ONE_LENGHT = [""]; + + const router = useHistory() + + const [invertList, setInvertList] = useState(false) + 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) + const [currPage, setCurrPage] = useState(0) + const [openAlertDialog, setOpenAlertDialog] = useState(false); //controlls the state od alert dialog + const [deleteItem, setDeleteItem] = useState({}); //Delete Item + const [isLoadingToDelete, setIsLoadingToDelete] = useState(null); + + const [snackInfo, setSnackInfo] = useState({ + message: '', + icon: '', + open: false, + color: '', + }) + + // Handle snack infos + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color }) - - // Handle snack infos - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color - }) + } + + //handle Delete + async function DeleteHandler() { + const id = deleteItem.id; + HandleStateAlertDialog(null); + deleteRequest( + DeleteFilter("ratings", id), + (data) => { + if (data.errors) + HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); + else { + HandleSnack( + "O rating foi deletada com sucesso", + true, + "success", + "#228B22" + ); + setCurrPage(0) + HandleStateCircularProgress(null); + removeItemFromList(id) + } + }, + (error) => { + HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); + HandleStateCircularProgress(null); + } + ) + } + + const removeItemFromList = (itemId) => { + let index = -1; + for (let i = 0; i < items.length; i++) { + const element = items[i]; + if (element.id === itemId) { + index = i + break + } } - - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true) - getRequest( - api, - (data, header) => { - const arrData = [...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(AddOneLenght)) - } - setIsLoadingMoreItems(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsLoadingMoreItems(false) - } - ) + if (index !== -1) { + const cpyItems = [...items] + cpyItems.splice(index, 1) + setItems(cpyItems) } - - const InvertList = async () => { - transformListToAsc = !transformListToAsc - currPage = 0 - if (transformListToAsc) { - getRequest( - Url('ratings', '', `${currPage}`, 'ASC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + } + + const HandleStateCircularProgress = (i) => { + setIsLoadingToDelete(i); + }; + + const HandleStateAlertDialog = (i) => { + const obj = { ...items[i] }; + setDeleteItem(obj); + setOpenAlertDialog(!openAlertDialog); + }; + + const cleanArrayAndInvert = () => { + setInvertList(!invertList) + setCurrPage(0) + setItems([]) + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + Url("ratings", "", currPage, invertList ? "ASC" : "DESC"), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') } else { - getRequest( - Url('ratings', '', `${currPage}`, 'DESC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } } - } - - const UpdateHandler = async (api) => { - setIsUpdating(true) - getRequest( - api, - (data, header) => { - HandleSnack('A lista de dados foi atualizada', true, 'success', '#228B22') - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - setIsUpdating(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsUpdating(false) - } - ) - } - - //handle Delete - async function DeleteHandler() { - const id = deleteItem.id; - HandleStateAlertDialog(null); - deleteRequest( - DeleteFilter("ratings", id), - (data) => { - if (data.errors) - HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); - else { - HandleSnack( - "O rating foi deletada com sucesso", - true, - "success", - "#228B22" - ); - currPage = 0; - transformListToAsc = false - UpdateHandler(Url("ratings", "", `${currPage}`, "DESC")); - HandleStateCircularProgress(null); - } - }, - (error) => { - HandleSnack("Ocorreu algum erro", true, "warning", "#FA8072"); - HandleStateCircularProgress(null); - } - ) - } - - const HandleStateCircularProgress = (i) => { - setIsLoadingToDelete(i); - }; - - const HandleStateAlertDialog = (i) => { - const obj = { ...items[i] }; - setDeleteItem(obj); - setOpenAlertDialog(!openAlertDialog); - }; - - - useEffect(() => { - getRequest( - Url('ratings', '', currPage, 'DESC'), - (data, header) => { - setIsLoaded(true); - setItems(data.concat(AddOneLenght)); - }, - (error) => { - setError(true) - } - ) - }, []); - - - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." /> - } else { - - //Words in the top part of the table - const topTable = ['ID', 'NOME', 'DESCRIÇÃO', 'VISUALIZAR', 'DELETAR']; - if (WINDOW_WIDTH <= 760) { - return ( - <div> - <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={12}> - <Typography variant="h4"> - Lista de ratings - </Typography> - </Grid> - <Grid - item - xs={12} - > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('ratings', '', `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - <Grid item> - <Link style={{ textDecoration: 'none' }} to={'/admin/CreateRating'}> - <Button - variant="contained" - color="secondary" - startIcon={<AddRoundedIcon style={{ fill: "white" }} />} - onClick={() => { - currPage = 0 - transformListToAsc = false - }} - > - Novo - </Button> - </Link> - </Grid> - </Grid> - </Grid> - </Grid> - </Paper> - - <div style={{ height: '2em' }}></div> - - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('ratings', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('ratings', '', `${currPage}`, 'DESC')) - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.name} - subtitle={row.id} - backColor={"#00bcd4"} - avatar={<StarRoundedIcon />} - href={`/admin/Rating/${row.id}`} - reset={() => { - currPage = 0; - }} - data={ - [ - { - title: "Descrição", - subtitle: row.description - } - ] - } - /> - <div style={{ height: "0.5em" }} /> - </> - ) + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoadingMoreItems(false) + setIsLoaded(true) + setError(true) + } + ) + }, [currPage, invertList]) + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." /> + } else { + + //Words in the top part of the table + const topTable = ['ID', 'NOME', 'DESCRIÇÃO', 'VISUALIZAR', 'DELETAR']; + if (WINDOW_WIDTH <= 800) { + return ( + <div> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + <AlertDialog + open={openAlertDialog} + OnDelete={DeleteHandler} + deleteItem={deleteItem} + HandleClose={() => { + setOpenAlertDialog(false); + HandleStateCircularProgress(null); + }} + /> + <MobilePageHeader + title="Lista de ratings" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/CreateRating') + }, + icon: <AddRoundedIcon /> + } + ]} + > + </MobilePageHeader> + + <div style={{ height: '2em' }}></div> + + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton key={new Date().toISOString() + row.created_at}> + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" )} - </div> - ) - } - else { - return ( - <div> - <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"> - Lista de ratings - </Typography> - </Grid> - <Grid - item - xs={6} + </Button> + </StyledDivButton> + ) : ( + <> + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.name} + subtitle={row.id} + backColor={"#00bcd4"} + avatar={<StarRoundedIcon />} + href={`/admin/Rating?rating=${row.id}`} + reset={() => { + + }} + data={ + [ + { + title: "Descrição", + subtitle: row.description + }, + { + title: "Deletar", + subtitle: + <Button + variant="contained" + color="secondary" + onClick={() => { + HandleStateAlertDialog(index); + HandleStateCircularProgress(index); + }} + startIcon={<DeleteRoundedIcon />} > - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('ratings', '', `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - <Grid item> - <Link style={{ textDecoration: 'none' }} to={'/admin/CreateRating'}> - <Button - variant="contained" - color="secondary" - startIcon={<AddRoundedIcon style={{ fill: "white" }} />} - onClick={() => { - currPage = 0 - transformListToAsc = false - }} - > - Novo - </Button> - </Link> - </Grid> - </Grid> - </Grid> - </Grid> - </Paper> - - <div style={{ height: '2em' }}></div> - - <TableData - top={topTable} - onIconPressed={InvertList} - > - <TableBody> - {items.map((row, index) => ( - index === items.length - 1 ? - <StyledTableRow key={index}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color='primary' - variant='text' - disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('ratings', '', `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('ratings', '', `${currPage}`, 'DESC')) - } - }} - > - { - isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' - } - </Button> - </StyledTableCell> - </StyledTableRow> - - : - - <StyledTableRow key={index}> - <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> - <StyledTableCell align="right">{row.name}</StyledTableCell> - <StyledTableCell align="right">{row.description}</StyledTableCell> - <StyledTableCell align="right"> - <Link to={`/admin/Rating/${row.id}`}> - <IconButton onClick={() => { currPage = 0 }}> - <VisibilityIcon style={{ fill: '#00bcd4' }} /> - </IconButton> - </Link> - </StyledTableCell> - <StyledTableCell align="right"> - {isLoadingToDelete === index ? ( - <CircularProgress size={24} color="primary" /> - ) : ( - <IconButton - onClick={() => { - HandleStateAlertDialog(index); - HandleStateCircularProgress(index); - }} - > - <DeleteRoundedIcon style={{ fill: "#FF0000" }} /> - </IconButton> - )} - </StyledTableCell> - </StyledTableRow> - ))} - </TableBody> - </TableData> - - {/* This alert will be displayed if the user click to delete an institution */} - <AlertDialog - open={openAlertDialog} - OnDelete={DeleteHandler} - deleteItem={deleteItem} - HandleClose={() => { - setOpenAlertDialog(false); - HandleStateCircularProgress(null); + Deletar + </Button> + } + ] + } + /> + <div style={{ height: "0.5em" }} /> + </> + ) + )} + </div> + ) + } + else { + return ( + <div> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + <PageHeader + title="Lista de ratings" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/CreateRating') + }, + icon: <AddRoundedIcon /> + } + ]} + > + </PageHeader> + + <div style={{ height: '2em' }}></div> + + <TableData + top={topTable} + onIconPressed={cleanArrayAndInvert} + > + <TableBody> + {items.map((row, index) => ( + index === items.length - 1 ? + <StyledTableRow key={new Date().toISOString() + row.created_at}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color='primary' + variant='text' + disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + onClick={() => { + setCurrPage(currPage + 1) }} - /> - </div> - ) - } + > + { + isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' + } + </Button> + </StyledTableCell> + </StyledTableRow> + + : + + <StyledTableRow key={new Date().toISOString() + index}> + <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> + <StyledTableCell align="right">{row.name}</StyledTableCell> + <StyledTableCell align="right">{row.description}</StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/Rating?rating=${row.id}`}> + <IconButton> + <VisibilityIcon style={{ fill: '#00bcd4' }} /> + </IconButton> + </Link> + </StyledTableCell> + <StyledTableCell align="right"> + {isLoadingToDelete === index ? ( + <CircularProgress size={24} color="primary" /> + ) : ( + <IconButton + onClick={() => { + HandleStateAlertDialog(index); + HandleStateCircularProgress(index); + }} + > + <DeleteRoundedIcon style={{ fill: "#FF0000" }} /> + </IconButton> + )} + </StyledTableCell> + </StyledTableRow> + ))} + </TableBody> + </TableData> + + {/* This alert will be displayed if the user click to delete an institution */} + <AlertDialog + open={openAlertDialog} + OnDelete={DeleteHandler} + deleteItem={deleteItem} + HandleClose={() => { + setOpenAlertDialog(false); + HandleStateCircularProgress(null); + }} + /> + </div> + ) } + } } diff --git a/src/Admin/Pages/Pages/SubPages/SendEmail.js b/src/Admin/Pages/Pages/SubPages/SendEmail.js index 5e9b05ed713d797f2e072811cf573c323b1009de..aff09bc843ce63f5238516695dd3887398987756 100644 --- a/src/Admin/Pages/Pages/SubPages/SendEmail.js +++ b/src/Admin/Pages/Pages/SubPages/SendEmail.js @@ -18,14 +18,12 @@ 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, {useContext} from 'react'; +import React from 'react'; import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import { makeStyles } from "@material-ui/core/styles"; import { Typography } from '@material-ui/core'; import EmailInputs from '../../../Components/Components/Inputs/EmailInputs'; -import { Store } from '../../../../Store'; -import Unauthorized from '../../../Components/Components/Unauthorized'; const useStyles = makeStyles({ root: { @@ -56,42 +54,26 @@ const useStyles = makeStyles({ }, }); + const SendEmail = ({ match }) => { - const { state } = useContext(Store); const classes = useStyles(); + const urlParams = new URLSearchParams(window.location.search); + const email = urlParams.get("email"); - const CheckUserPermission = () => { - let canUserEdit = false; - - if (state.userIsLoggedIn) { - const roles = [...state.currentUser.roles]; - for (let i = 0; i < roles.length; i++) - if (roles[i].name === 'admin' || roles[i].name === 'editor') - canUserEdit = true; - } - else { - canUserEdit = false; - } - - return canUserEdit; - } - - if(CheckUserPermission()){ - return ( - <Card> - <CardContent> - <Typography - className={classes.title} - color="inherit" - gutterBottom - > - Enviar email - </Typography> - <EmailInputs email={`${match.params.email}`} /> - </CardContent> - </Card> - ); - } else return <Unauthorized/> + return ( + <Card> + <CardContent> + <Typography + className={classes.title} + color="inherit" + gutterBottom + > + Enviar email + </Typography> + <EmailInputs email={email} /> + </CardContent> + </Card> + ); } export default SendEmail; \ No newline at end of file diff --git a/src/Admin/Pages/Pages/SubPages/Users.js b/src/Admin/Pages/Pages/SubPages/Users.js index fe3524c9e120bb5586a9965bbdccfa4a541f0d91..cb31af1e213e65b7c8d13be01fb48c68a75dd190 100644 --- a/src/Admin/Pages/Pages/SubPages/Users.js +++ b/src/Admin/Pages/Pages/SubPages/Users.js @@ -25,624 +25,539 @@ import TableCell from '@material-ui/core/TableCell'; import TableRow from '@material-ui/core/TableRow'; import IconButton from '@material-ui/core/IconButton'; import VisibilityIcon from '@material-ui/icons/Visibility'; -import { Button, Typography, Chip } from '@material-ui/core'; +import { Button, Chip } from '@material-ui/core'; import CircularProgress from '@material-ui/core/CircularProgress'; import AddRoundedIcon from '@material-ui/icons/AddRounded'; import TextField from '@material-ui/core/TextField'; import UpdateRoundedIcon from '@material-ui/icons/UpdateRounded' +import FilterListRoundedIcon from "@material-ui/icons/FilterListRounded"; //Local files import TableData from '../../../Components/Components/Table'; import SnackBar from '../../../../Components/SnackbarComponent'; import LoadingSpinner from '../../../../Components/LoadingSpinner'; +import MobileList from "../../../Components/Components/MobileComponents/SimpleList" +import MobilePageHeader from "../../../Components/Components/MobileComponents/MobilePageHeader" +import PageHeader from "../../../Components/Components/PageHeader" //Services import { getRequest, putRequest } from '../../../../Components/HelperFunctions/getAxiosConfig' import { Url } from '../../../Filters'; //routers -import { Link } from 'react-router-dom'; +import { Link, useHistory } from 'react-router-dom'; import moment from 'moment'; import styled from 'styled-components' -import MobileList from "../../../Components/Components/MobileComponents/SimpleList" import EmailRoundedIcon from '@material-ui/icons/EmailRounded'; import { apiDomain } from '../../../../env'; import noAvatar from "../../../../img/default_profile.png"; -let currPage = 0; //var that controlls the current page that we are -let transformListToAsc = false; -let nameFilter = ""; -let emailFilter = ""; const StyledTableCell = withStyles((theme) => ({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, + 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, - }, + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.action.hover, }, + }, }))(TableRow); const Users = () => { - const AddOneLenght = ['']; - const WINDOW_WIDTH = window.innerWidth - 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) - const [isUpdating, setIsUpdating] = useState(false) - const [showFilter, setShowFilter] = useState(false) - - const [name, setName] = useState(""); - const [email, setEmail] = useState(""); - - const [snackInfo, setSnackInfo] = useState({ - message: '', - icon: '', - open: false, - color: '', + const ADD_ONE_LENGHT = ['']; + const WINDOW_WIDTH = window.innerWidth + + const router = useHistory() + + const [invertList, setInvertList] = useState(false) + 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) + const [showFilter, setShowFilter] = useState(false) + const [currPage, setCurrPage] = useState(0) + + const [name, setName] = useState(""); + const [nameValue, setNameValue] = useState("") + const [email, setEmail] = useState(""); + const [emailValue, setEmailValue] = useState("") + + const [snackInfo, setSnackInfo] = useState({ + message: '', + icon: '', + open: false, + color: '', + }) + + // Handle snack infos + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color }) - - // Handle snack infos - const HandleSnack = (message, state, icon, color) => { - setSnackInfo({ - message: message, - icon: icon, - open: state, - color: color - }) + } + + const NameHandler = (event) => { + setNameValue(event.target.value) + } + + const EmailHandler = (event) => { + setEmailValue(event.target.value) + } + + const DisplayDate = (date) => { + const convertedData = moment.utc(date); + return moment(convertedData) + .format("LLL") + .toString(); + }; + + const isUserPublisher = (userRoles) => { + for (let index = 0; index < userRoles.length; index++) { + if (userRoles[index].id === 10) + return true; } - - const NameHandler = (event) => { - currPage = 0 - setName(event.target.value) - nameFilter = event.target.value - getRequest( - Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, `${currPage}`, 'DESC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - HandleSnack('Filtro aplicado com sucesso', true, 'success', '#228B22') - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) - + return false; + } + + const pushPublisherRole = (userId) => { + let index = -1; + for (let i = 0; i < items.length; i++) { + const element = items[i]; + if (element.id === userId) { + index = i + break + } } - - const EmailHandler = (event) => { - currPage = 0 - setEmail(event.target.value) - emailFilter = event.target.value - getRequest( - Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, `${currPage}`, 'DESC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - HandleSnack('Filtro aplicado com sucesso', true, 'success', '#228B22') - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + if (index !== -1) { + const cpyItems = [...items] + cpyItems[index].roles.push({ + id: 10, + name: "publisher" + }) + setItems(cpyItems) } - - const LoadMoreItens = async (api) => { - setIsLoadingMoreItems(true) - getRequest( - api, - (data, header) => { - const arrData = [...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(AddOneLenght)) - } - setIsLoadingMoreItems(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsLoadingMoreItems(false) - } - ) + } + + const turnUserPublisher = (userRoles, userId) => { + let roles_ids = []; + userRoles.map((role) => ( + roles_ids.push(role.id) + )) + roles_ids.push(10); + const body = { + "user": { + "role_ids": roles_ids + } } - - const InvertList = async () => { - transformListToAsc = !transformListToAsc - currPage = 0 - if (transformListToAsc) { - getRequest( - Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, `${currPage}`, 'ASC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) - } else { - getRequest( - Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, `${currPage}`, 'DESC'), - (data, header) => { - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - } - ) + putRequest( + `/users/${userId}`, + body, + (data) => { + if (data.errors) { + HandleSnack('Ocorreu algum erro', true, 'warning', '#FA8072') } - } - - const DisplayDate = (date) => { - const convertedData = moment.utc(date); - return moment(convertedData) - .format("LLL") - .toString(); - }; - - const UpdateHandler = async (api) => { - setIsUpdating(true) - getRequest( - api, - (data, header) => { - HandleSnack('A lista de dados foi atualizada', true, 'success', '#228B22') - const arrData = [...data] - setItems(arrData.concat(AddOneLenght)) - setIsUpdating(false) - }, - (error) => { - HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') - setIsUpdating(false) - } - ) - } - - const isUserPublisher = (userRoles) => { - for (let index = 0; index < userRoles.length; index++) { - if (userRoles[index].id === 10) - return true; + else { + HandleSnack(`O usuário ${userId}, agora é publicador`, true, 'success', '#228B22') + pushPublisherRole(userId) + setCurrPage(0) } - return false; - } - - const turnUserPublisher = (userRoles, userId) => { - let roles_ids = []; - userRoles.map((role) => ( - roles_ids.push(role.id) - )) - roles_ids.push(10); - const body = { - "user": { - "role_ids": roles_ids - } + }, + (error) => { + HandleSnack('Ocorreu algum erro', true, 'warning', '#FA8072') + } + ) + } + + const cleanArrayAndInvert = () => { + setInvertList(!invertList) + setCurrPage(0) + setItems([]) + } + + const buildUrl = (email, name, direction) => { + if (email && name) + return Url("users", `"email" : "${email}", "name" : "${name}"`, currPage, direction) + if (email) + return Url("users", `"email" : "${email}"`, currPage, direction) + if (name) + return Url("users", `"name" : "${name}"`, currPage, direction) + else + return Url("users", "", currPage, direction) + } + + useEffect(() => { + if (currPage === 0) + setIsLoaded(false) + else + setIsLoadingMoreItems(true) + getRequest( + buildUrl(email, name, invertList ? "ASC" : "DESC"), + (data, header) => { + const arrData = [...data] + if (arrData.length === 0) { + HandleSnack('Não há mais dados para serem carregados', true, 'warning', '#FFC125') + } else { + const arrItems = [...items] + if (currPage === 0) { + setItems(arrData.concat(ADD_ONE_LENGHT)) + } + else { + 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)) + } } - putRequest( - `/users/${userId}`, - body, - (data) => { - if (data.errors) { - HandleSnack('Ocorreu algum erro', true, 'warning', '#FA8072') - } - else { - currPage = 0; - HandleSnack(`O usuário ${userId}, agora é publicador`, true, 'success', '#228B22') - UpdateHandler(Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, `${currPage}`, 'DESC')) - } - }, - (error) => { - HandleSnack('Ocorreu algum erro', true, 'warning', '#FA8072') - } - ) - } - - useEffect(() => { - getRequest( - Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, '0', 'DESC'), - (data, header) => { - setIsLoaded(true); - setItems(data.concat(AddOneLenght)); - }, - (error) => { - setError(true); - } - ) - }, []); - - - if (error) { - return <div>Error: {error.message}</div>; - } else if (!isLoaded) { - return <LoadingSpinner text="Carregando..." /> - } else { - - //Words in the top part of the table - const topTable = ['ID', 'NOME', 'EMAIL', 'CRIADO EM', 'SCORE', 'PERMISSÃO', 'AÇÃO', "VISUALIZAR"]; - if (WINDOW_WIDTH <= 1150) { - return ( - <div> - <SnackBar - severity={snackInfo.icon} - text={snackInfo.message} - snackbarOpen={snackInfo.open} - color={snackInfo.color} - handleClose={() => setSnackInfo({ - message: '', - icon: '', - open: false, - color: '' - })} + setIsLoaded(true) + setIsLoadingMoreItems(false) + }, + (error) => { + HandleSnack('Erro ao carregar os dados', true, 'warning', '#FA8072') + setIsLoaded(true) + setError(true) + setIsLoadingMoreItems(false) + } + ) + }, [currPage, email, name, invertList]) + + useEffect(() => { + setNameValue("") + setName("") + setEmailValue("") + setEmail("") + }, [showFilter]) + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." /> + } else { + + //Words in the top part of the table + const topTable = ['ID', 'NOME', 'EMAIL', 'CRIADO EM', 'SCORE', 'PERMISSÃO', 'AÇÃO', "VISUALIZAR"]; + if (WINDOW_WIDTH <= 1150) { + return ( + <div> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + <MobilePageHeader + title="Lista de usuários" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/EditUser?id=-1') + }, + icon: <AddRoundedIcon /> + }, + { + name: "Inverter lista", + isLoading: false, + func: () => { + cleanArrayAndInvert() + }, + } + ]} + > + { + showFilter ? ( + <Grid container direction="row" justify="space-between" alignItems="center"> + <Grid item> + <TextField + label="Name" + value={nameValue} + onChange={(e) => { NameHandler(e) }} + onBlur={(e) => { setEmail(e.target.value) }} + helperText="Ao digitar, retire o foco do campo" + /> + </Grid> + <Grid item> + <TextField + label="Email" + value={emailValue} + onChange={(e) => { EmailHandler(e) }} + onBlur={(e) => { setEmail(e.target.value) }} + helperText="Ao digitar, retire o foco do campo" /> - <Paper style={{ padding: '1em' }}> - <Grid container spacing={3} direction="row" alignItems="center"> - <Grid item xs={12}> - <Typography variant="h4"> - Lista de usuários - </Typography> - </Grid> - <Grid - item - xs={12} + </Grid> + </Grid> + ) : null + } + </MobilePageHeader> + + <div style={{ height: '2em' }}></div> + + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledDivButton key={new Date().toISOString() + row.created_at}> + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + setCurrPage(currPage + 1) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledDivButton> + ) : ( + <> + <MobileList + key={new Date().toISOString() + row.created_at} + title={row.name} + subtitle={row.id} + backColor={"#00bcd4"} + avatar={ + <img + src={row.avatar ? apiDomain + row.avatar : noAvatar} + alt="user avatar" + style={{ + height: "100%", + width: "100%", + borderRadius: "50%", + }} + /> + } + href={`/admin/user?id=${row.id}`} + reset={() => { + }} + data={[ + { + title: "Email", + subtitle: row.email ? + <Link to={`/admin/sendEmail?email=${row.email}`} style={{ textDecoration: 'none' }}> + <Button + variant='text' + color='primary' + startIcon={<EmailRoundedIcon />} > - <Grid container justify="flex-start" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={() => { - setShowFilter(!showFilter) - }} - startIcon={<UpdateRoundedIcon />} - > - filtrar - </Button> - </Grid> - <Grid item> - <Link to="/admin/EditUser/-1"> - <Button - variant="contained" - color="secondary" - startIcon={<AddRoundedIcon />} - > - Novo - </Button> - </Link> - </Grid> - </Grid> - </Grid> - </Grid> - { - showFilter ? ( - <Grid container direction="row" justify="space-between" alignItems="center"> - <Grid item> - <TextField - label="Name" - value={name} - onChange={(e) => { NameHandler(e) }} - /> - </Grid> - <Grid item> - <TextField - label="Email" - value={email} - onChange={(e) => { EmailHandler(e) }} - /> - </Grid> - </Grid> - ) : null - } - </Paper> - - <div style={{ height: '2em' }}></div> - - {items.map((row, index) => - index === items.length - 1 ? ( - <StyledDivButton> - <Button - key={index} - color="primary" - variant="text" - // disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - disabled={isLoadingMoreItems} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, `${currPage}`, 'DESC')) - } - }} - > - {isLoadingMoreItems ? ( - <CircularProgress size={24} /> - ) : ( - "Carregar mais itens" - )} - </Button> - </StyledDivButton> - ) : ( - <> - <MobileList - key={index} - title={row.name} - subtitle={row.id} - backColor={"#00bcd4"} - avatar={ - <img - src={row.avatar ? apiDomain + row.avatar : noAvatar} - alt="user avatar" - style={{ - height: "100%", - width: "100%", - borderRadius: "50%", - }} - /> - } - href={`/admin/user/${row.id}`} - reset={() => { - currPage = 0; - transformListToAsc = false - nameFilter = "" - emailFilter = "" - }} - data={[ - { - title: "Email", - subtitle: row.email ? - <Link to={`/admin/sendEmail/${row.email}`} style={{ textDecoration: 'none' }}> - <Button - variant='text' - color='primary' - startIcon={<EmailRoundedIcon />} - > - {row.email} - </Button> - </Link> : null - }, - { - title: "Criado em", - subtitle: DisplayDate(row.created_at) - }, - { - title: "Score", - subtitle: row.score - }, - { - title: "Permissão", - subtitle: row.roles.map((chip) => ( - <ChipDiv> - <Chip label={chip.name} key={chip.id} /> - </ChipDiv> - )) - }, - { - title: "Score", - subtitle: row.score - }, - { - title: "Ações rápidas", - subtitle: <Button - variant="contained" - color="primary" - disabled={isUserPublisher(row.roles)} - onClick={() => { turnUserPublisher(row.roles, row.id) }} - > - Tornar publicador + {row.email} + </Button> + </Link> : null + }, + { + title: "Criado em", + subtitle: DisplayDate(row.created_at) + }, + { + title: "Score", + subtitle: row.score + }, + { + title: "Permissão", + subtitle: row.roles.map((chip) => ( + <ChipDiv> + <Chip label={chip.name} key={chip.id} /> + </ChipDiv> + )) + }, + { + title: "Score", + subtitle: row.score + }, + { + title: "Ações rápidas", + subtitle: <Button + variant="contained" + color="primary" + disabled={isUserPublisher(row.roles)} + onClick={() => { turnUserPublisher(row.roles, row.id) }} + > + Tornar publicador </Button> - } - - ]} - /> - <div style={{ height: "0.5em" }} /> - </> - ) - )} - </div> - ) - } - else { - return ( - <div> - <SnackBar - severity={snackInfo.icon} - text={snackInfo.message} - snackbarOpen={snackInfo.open} - color={snackInfo.color} - handleClose={() => setSnackInfo({ - message: '', - icon: '', - open: false, - color: '' - })} + } + + ]} + /> + <div style={{ height: "0.5em" }} /> + </> + ) + )} + </div> + ) + } + else { + return ( + <div> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => setSnackInfo({ + message: '', + icon: '', + open: false, + color: '' + })} + /> + <PageHeader + title="Lista de usuários" + actions={[ + { + name: "Atualizar", + isLoading: false, + func: () => { + setCurrPage(0) + }, + icon: <UpdateRoundedIcon /> + }, + { + name: "Filtrar", + isLoading: false, + func: () => { + setShowFilter(!showFilter); + }, + icon: <FilterListRoundedIcon /> + }, + { + name: "Novo", + isLoading: false, + func: () => { + router.push('/admin/EditUser?id=-1') + }, + icon: <AddRoundedIcon /> + } + ]} + > + { + showFilter ? ( + <Grid container direction="row" justify="space-between" alignItems="center"> + <Grid item> + <TextField + label="Name" + value={nameValue} + onChange={(e) => { NameHandler(e) }} + onBlur={(e) => { setEmail(e.target.value) }} + helperText="Ao digitar, retire o foco do campo" /> - <Paper style={{ padding: '1em' }}> - <Grid container spacing={3} direction="row" alignItems="center"> - <Grid item xs={6}> - <Typography variant="h4"> - Lista de usuários - </Typography> - </Grid> - <Grid - item - xs={6} - > - <Grid container justify="flex-end" spacing={3}> - <Grid item> - <Button - variant="contained" - color="secondary" - disabled={isUpdating} - onClick={() => { - currPage = 0 - transformListToAsc = false - UpdateHandler(Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, `${currPage}`, 'DESC')) - }} - startIcon={<UpdateRoundedIcon />} - > - { - isUpdating ? <CircularProgress size={24} /> : 'Atualizar' - } - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={() => { - setShowFilter(!showFilter) - }} - startIcon={<UpdateRoundedIcon />} - > - filtrar - </Button> - </Grid> - <Grid item> - <Link to="/admin/EditUser/-1"> - <Button - variant="contained" - color="secondary" - startIcon={<AddRoundedIcon />} - > - Novo - </Button> - </Link> - </Grid> - </Grid> - </Grid> - </Grid> + </Grid> + <Grid item> + <TextField + label="Email" + value={emailValue} + onChange={(e) => { EmailHandler(e) }} + onBlur={(e) => { setEmail(e.target.value) }} + helperText="Ao digitar, retire o foco do campo" + /> + </Grid> + </Grid> + ) : null + } + </PageHeader> + + <div style={{ height: '2em' }}></div> + + <TableData + top={topTable} + onIconPressed={cleanArrayAndInvert} + > + <TableBody> + {items.map((row, index) => ( + index === items.length - 1 ? + <StyledTableRow key={new Date().toISOString() + row.created_at}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color='primary' + variant='text' + disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + onClick={() => { + setCurrPage(currPage + 1) + }} + > { - showFilter ? ( - <Grid container direction="row" justify="space-between" alignItems="center"> - <Grid item> - <TextField - label="Name" - value={name} - onChange={(e) => { NameHandler(e) }} - /> - </Grid> - <Grid item> - <TextField - label="Email" - value={email} - onChange={(e) => { EmailHandler(e) }} - /> - </Grid> - </Grid> - ) : null + isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' } - </Paper> - - <div style={{ height: '2em' }}></div> - - <TableData - top={topTable} - onIconPressed={InvertList} - > - <TableBody> - {items.map((row, index) => ( - index === items.length - 1 ? - <StyledTableRow key={index}> - {/* Button to load more data */} - <StyledTableCell> - <Button - color='primary' - variant='text' - disabled={isLoadingMoreItems} - startIcon={<AddRoundedIcon />} - onClick={() => { - currPage++ - if (transformListToAsc) { - LoadMoreItens(Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, `${currPage}`, 'ASC')) - } else { - LoadMoreItens(Url('users', `"name" : "${nameFilter}", "email" : "${emailFilter}"`, `${currPage}`, 'DESC')) - } - }} - > - { - isLoadingMoreItems ? <CircularProgress size={24} /> : 'Carregar mais itens' - } - </Button> - </StyledTableCell> - </StyledTableRow> - - : - - <StyledTableRow key={index}> - <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> - <StyledTableCell align="right">{row.name}</StyledTableCell> - <StyledTableCell align="right">{row.email ? row.email : ""}</StyledTableCell> - <StyledTableCell align="right"> - {DisplayDate(row.created_at)} - </StyledTableCell> - <StyledTableCell align="right">{row.score}</StyledTableCell> - <StyledTableCell align="right"> - { - row.roles.map((chip) => ( - <ChipDiv> - <Chip label={chip.name} key={chip.id} /> - </ChipDiv> - )) - } - </StyledTableCell> - <StyledTableCell align="right"> - <Button - variant="contained" - color="primary" - disabled={isUserPublisher(row.roles)} - onClick={() => { turnUserPublisher(row.roles, row.id) }} - > - Tornar publicador + </Button> + </StyledTableCell> + </StyledTableRow> + + : + + <StyledTableRow key={new Date().toISOString() + index}> + <StyledTableCell component="th" scope="row">{row.id}</StyledTableCell> + <StyledTableCell align="right">{row.name}</StyledTableCell> + <StyledTableCell align="right">{row.email ? row.email : ""}</StyledTableCell> + <StyledTableCell align="right"> + {DisplayDate(row.created_at)} + </StyledTableCell> + <StyledTableCell align="right">{row.score}</StyledTableCell> + <StyledTableCell align="right"> + { + row.roles.map((chip) => ( + <ChipDiv> + <Chip label={chip.name} key={chip.id} /> + </ChipDiv> + )) + } + </StyledTableCell> + <StyledTableCell align="right"> + <Button + variant="contained" + color="primary" + disabled={isUserPublisher(row.roles)} + onClick={() => { turnUserPublisher(row.roles, row.id) }} + > + Tornar publicador </Button> - </StyledTableCell> - <StyledTableCell align="right"> - <Link to={`/admin/user/${row.id}`}> - <IconButton onClick={() => { - currPage = 0; - transformListToAsc = false - nameFilter = "" - emailFilter = "" - } - }> - <VisibilityIcon style={{ fill: '#00bcd4' }} /> - </IconButton> - </Link> - </StyledTableCell> - </StyledTableRow> - ))} - </TableBody> - </TableData> - </div> - ) - } + </StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/user?id=${row.id}`}> + <IconButton> + <VisibilityIcon style={{ fill: '#00bcd4' }} /> + </IconButton> + </Link> + </StyledTableCell> + </StyledTableRow> + ))} + </TableBody> + </TableData> + </div> + ) } + } } export default Users; diff --git a/src/App.js b/src/App.js index 1400c7a2cb90a656777c7f1b8608f48298cd20b5..c97423244a92cc6662c82335e42e3dd8794d1c49 100644 --- a/src/App.js +++ b/src/App.js @@ -17,6 +17,8 @@ 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, { useContext, useEffect, useState } from "react"; +import { Store } from './Store' +import Unauthorized from './Admin/Components/Components/Unauthorized' import Home from "./Pages/HomeFunction"; import Search from "./Pages/Search"; import Header from "./Components/Header"; @@ -35,8 +37,7 @@ import TabManageAc from "./Pages/TabsHelp/TabManageAc"; import PasswordRecoveryPage from "./Pages/PasswordRecoveryPage.js"; import PageProfessor from "./Pages/PageProfessor.js"; import ResourcePage from "./Pages/ResourcePage"; -import { BrowserRouter, Switch, Route, Link } from "react-router-dom"; -import { Store } from "./Store"; +import { BrowserRouter, Switch, Route } from "react-router-dom"; import TermsPage from "./Pages/TermsPage.js"; import PublicationPermissionsPage from "./Pages/PublicationPermissionsPage.js"; import TabPlataformaMEC from "./Pages/TabsHelp/TabPlataformaMEC"; @@ -51,13 +52,8 @@ import CollectionPage from "./Pages/CollectionPage.js"; import FormationMaterialPage from "./Pages/FormationMaterialPage.js"; import FormationMaterialIframe from "./Pages/FormationMaterialIframe.js"; import MaterialPage from "./Pages/MaterialPage"; +import Maintence from './Components/maintenance' -//material ui -import { Tab, Tabs } from "@material-ui/core"; - -//admin -import { makeStyles } from "@material-ui/core/styles"; -import DisplayIcon from "./Admin/Components/Components/DisplayIcon"; import NoteVariables from "./Admin/Pages/Pages/SubPages/NoteVariables"; import Institution from "./Admin/Pages/Pages/SubPages/Institutions"; import SendEmail from "./Admin/Pages/Pages/SubPages/SendEmail"; @@ -96,64 +92,30 @@ import UserPermissions from "./Admin/Pages/Pages/SubPages/Permissions"; import EditRole from "./Admin/Components/Components/Inputs/EditRoles"; import CreateRole from "./Admin/Components/Components/Inputs/CreateRole"; import BlockedUser from "./Admin/Pages/Pages/SubPages/BlockedUsers"; -import PropTypes from "prop-types"; -import Typography from "@material-ui/core/Typography"; -import Box from "@material-ui/core/Box"; -import AppBar from "@material-ui/core/AppBar"; - -function TabPanel(props) { - const { children, value, index, ...other } = props; - - return ( - <div - role="tabpanel" - hidden={value !== index} - id={`nav-tabpanel-${index}`} - aria-labelledby={`nav-tab-${index}`} - {...other} - > - {value === index && ( - <Box p={3}> - <Typography>{children}</Typography> - </Box> - )} - </div> - ); -} - -TabPanel.propTypes = { - children: PropTypes.node, - index: PropTypes.any.isRequired, - value: PropTypes.any.isRequired, -}; - -function a11yProps(index) { - return { - id: `nav-tab-${index}`, - "aria-controls": `nav-tabpanel-${index}`, - }; -} - -const useStyles = makeStyles({ - list: { - width: 250, - }, - fullList: { - width: "auto", - }, -}); +import AppBarAdmin from './Admin/Components/Components/AppBar' +import Maintenance from "./Components/maintenance"; export default function App() { // eslint-disable-next-line - const classes = useStyles(); - const { dispatch } = useContext(Store); + const { state, dispatch } = useContext(Store); const [hideFooter, setHideFooter] = useState(false); - const [value, setValue] = React.useState(0); - const handleChange = (event, newValue) => { - setValue(newValue); - }; + const CheckUserPermission = () => { + let canUserEdit = false; + + if (state.userIsLoggedIn) { + const roles = [...state.currentUser.roles]; + for (let i = 0; i < roles.length; i++) + if (roles[i].name === 'admin' || roles[i].name === 'editor') + canUserEdit = true; + } + else { + canUserEdit = false; + } + + return canUserEdit; + } useEffect(() => { setHideFooter(String(window.location.href).includes("iframe-colecao")); @@ -187,6 +149,7 @@ export default function App() { return ( <BrowserRouter basename="/react"> + <Maintenance /> <Header /> <div style={{ @@ -235,194 +198,259 @@ export default function App() { <Route path="/iframe-colecao" component={FormationMaterialIframe} /> <Route path="/material-formacao" component={MaterialPage} /> <div style={{ backgroundColor: " #D3D3D3" }}> - <AppBar position="static" color="default"> - <Tabs - variant="scrollable" - scrollButtons="on" - value={value} - onChange={handleChange} - aria-label="nav tabs example" - > - <Tab - label="Home" - to="/admin/home" - icon={<DisplayIcon i={0} />} - component={Link} - {...a11yProps(0)} - /> - <Tab - label="Coleções" - to="/admin/Collections" - icon={<DisplayIcon i={1} />} - component={Link} - {...a11yProps(1)} - /> - <Tab - label="Atividades" - to="/admin/activities" - icon={<DisplayIcon i={2} />} - component={Link} - {...a11yProps(2)} - /> - <Tab - label="Dúvidas da comunidade" - to="/admin/CommunityQuestions" - icon={<DisplayIcon i={3} />} - component={Link} - {...a11yProps(3)} - /> - <Tab - label="Instituição" - to="/admin/intitutions" - icon={<DisplayIcon i={4} />} - component={Link} - {...a11yProps(4)} - /> - <Tab - label="Linguagens" - to="/admin/languages" - icon={<DisplayIcon i={5} />} - component={Link} - {...a11yProps(5)} - /> - <Tab - label="Objetos educacionais" - to="/admin/learningObjects" - icon={<DisplayIcon i={6} />} - component={Link} - {...a11yProps(6)} - /> - <Tab - label="Rating" - to="/admin/Ratings" - icon={<DisplayIcon i={7} />} - component={Link} - {...a11yProps(7)} - /> - <Tab - label="Permissões do usuário" - to="/admin/permissions" - icon={<DisplayIcon i={8} />} - component={Link} - {...a11yProps(8)} - /> - <Tab - label="Variáveis de nota" - to="/admin/noteVars" - icon={<DisplayIcon i={9} />} - component={Link} - {...a11yProps(9)} - /> - <Tab - label="Perguntas da curadoria" - to="/admin/Questions" - icon={<DisplayIcon i={10} />} - component={Link} - {...a11yProps(10)} - /> - <Tab - label="Aprovação de professores" - to="/admin/users/teacher_requests" - icon={<DisplayIcon i={11} />} - component={Link} - {...a11yProps(11)} - /> - <Tab - label="Usuários" - to="/admin/usersList" - icon={<DisplayIcon i={12} />} - component={Link} - {...a11yProps(12)} - /> - <Tab - label="Usuários bloqueados" - to="/admin/BlockedUsers" - icon={<DisplayIcon i={13} />} - component={Link} - {...a11yProps(13)} - /> - <Tab - label="Denúncias" - to="/admin/complaints" - icon={<DisplayIcon i={14} />} - component={Link} - {...a11yProps(14)} - /> - <Tab - label="Enviar email" - to="/admin/sendEmail/:email" - icon={<DisplayIcon i={15} />} - component={Link} - {...a11yProps(15)} - /> - </Tabs> - </AppBar> + <AppBarAdmin /> <div style={{ padding: "2em" }}> - <Route path="/admin/home" exact={true} component={Inframe} /> - <Route path="/admin/intitutions" component={Institution} /> - <Route path="/admin/institution/:id" component={InstitutionCard} /> + <Route path="/admin/home" exact={true} render={() => { + if (CheckUserPermission()) + return <Inframe /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/intitutions" render={() => { + if (CheckUserPermission()) + return <Institution /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/institution" render={() => { + if (CheckUserPermission()) + return <InstitutionCard /> + else + return <Unauthorized /> + }} /> <Route - path="/admin/institutionEdit/:id" - component={InstitutionsInput} + path="/admin/institutionEdit" + render={() => { + if (CheckUserPermission()) + return <InstitutionsInput /> + else + return <Unauthorized /> + }} /> <Route path="/admin/InstitutionCreate" - component={CreateInstitution} + render={() => { + if (CheckUserPermission()) + return <CreateInstitution /> + else + return <Unauthorized /> + }} /> - <Route path="/admin/noteVars" component={NoteVariables} /> - <Route path="/admin/noteVar/:id" component={NoteVarCard} /> - <Route path="/admin/noteVarEdit/:id" component={NoteVarInputs} /> - <Route path="/admin/languages" component={Languages} /> - <Route path="/admin/languageEdit/:id" component={EditLanguage} /> - <Route path="/admin/languageCreate" component={CreateLanguage} /> + <Route path="/admin/noteVars" render={() => { + if (CheckUserPermission()) + return <NoteVariables /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/noteVar" render={() => { + if (CheckUserPermission()) + return <NoteVarCard /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/noteVarEdit" render={() => { + if (CheckUserPermission()) + return <NoteVarInputs /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/languages" render={() => { + if (CheckUserPermission()) + return <Languages /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/languageEdit" render={() => { + if (CheckUserPermission()) + return <EditLanguage /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/languageCreate" render={() => { + if (CheckUserPermission()) + return <CreateLanguage /> + else + return <Unauthorized /> + }} /> <Route path="/admin/CommunityQuestions" - component={CommunityQuestions} + render={() => { + if (CheckUserPermission()) + return <CommunityQuestions /> + else + return <Unauthorized /> + }} /> <Route - path="/admin/CommunityQuestion/:id" - component={CommunityCard} + path="/admin/CommunityQuestion" + render={() => { + if (CheckUserPermission()) + return <CommunityCard /> + else + return <Unauthorized /> + }} /> - <Route path="/admin/Collections" component={Collections} /> - <Route path="/admin/Collection/:id" component={CollectionCard} /> + <Route path="/admin/Collections" render={() => { + if (CheckUserPermission()) + return <Collections /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/Collection" render={() => { + if (CheckUserPermission()) + return <CollectionCard /> + else + return <Unauthorized /> + }} /> <Route - path="/admin/EditCollection/:id" - component={EditCollection} + path="/admin/EditCollection" + render={() => { + if (CheckUserPermission()) + return <EditCollection /> + else + return <Unauthorized /> + }} /> - <Route path="/admin/Ratings" component={Ratings} /> - <Route path="/admin/Rating/:id" component={RatingCard} /> - <Route path="/admin/EditRating/:id" component={EditRating} /> - <Route path="/admin/CreateRating" component={CreateRating} /> - <Route path="/admin/Questions" component={Questions} /> - <Route path="/admin/CreateQuestion" component={CreateQuestions} /> - <Route path="/admin/activities" component={Activity} /> - <Route path="/admin/activity/:id" component={ActivityCard} /> + <Route path="/admin/Ratings" render={() => { + if (CheckUserPermission()) + return <Ratings /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/Rating" render={() => { + if (CheckUserPermission()) + return <RatingCard /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/EditRating" render={() => { + if (CheckUserPermission()) + return <EditRating /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/CreateRating" render={() => { + if (CheckUserPermission()) + return <CreateRating /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/Questions" render={() => { + if (CheckUserPermission()) + return <Questions /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/CreateQuestion" render={() => { + if (CheckUserPermission()) + return <CreateQuestions /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/activities" render={() => { + if (CheckUserPermission()) + return <Activity /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/activity" render={() => { + if (CheckUserPermission()) + return <ActivityCard /> + else + return <Unauthorized /> + }} /> <Route path="/admin/learningObjects" - component={EducationalObject} - /> + render={() => { + if (CheckUserPermission()) + return <EducationalObject /> + else + return <Unauthorized /> + }} /> <Route - path="/admin/learningObject/:id" - component={EducationalObjectCard} - /> + path="/admin/learningObject" + render={() => { + if (CheckUserPermission()) + return <EducationalObjectCard /> + else + return <Unauthorized /> + }} /> <Route - path="/admin/learningObjectEdit/:id" - component={EducationalObjectEdit} - /> - <Route path="/admin/complaints" component={Complaints} /> - <Route path="/admin/complaint/:id" component={ComplaintCard} /> + path="/admin/learningObjectEdit" + render={() => { + if (CheckUserPermission()) + return <EducationalObjectEdit /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/complaints" render={() => { + if (CheckUserPermission()) + return <Complaints /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/complaint" render={() => { + if (CheckUserPermission()) + return <ComplaintCard /> + else + return <Unauthorized /> + }} /> <Route path="/admin/users/teacher_requests" - component={AproveTeacher} - /> - <Route path="/admin/usersList" component={UserList} /> - <Route path="/admin/user/:id" component={UserCard} /> - <Route path="/admin/EditUser/:id" component={EditUser} /> - <Route path="/admin/permissions" component={UserPermissions} /> - <Route path="/admin/EditPermissions/:id" component={EditRole} /> - <Route path="/admin/CreateRole" component={CreateRole} /> - <Route path="/admin/BlockedUsers" component={BlockedUser} /> - <Route path="/admin/sendEmail/:email" component={SendEmail} /> + render={() => { + if (CheckUserPermission()) + return <AproveTeacher /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/usersList" render={() => { + if (CheckUserPermission()) + return <UserList /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/user" render={() => { + if (CheckUserPermission()) + return <UserCard /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/EditUser" render={() => { + if (CheckUserPermission()) + return <EditUser /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/permissions" render={() => { + if (CheckUserPermission()) + return <UserPermissions /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/EditPermissions" render={() => { + if (CheckUserPermission()) + return <EditRole /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/CreateRole" render={() => { + if (CheckUserPermission()) + return <CreateRole /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/BlockedUsers" render={() => { + if (CheckUserPermission()) + return <BlockedUser /> + else + return <Unauthorized /> + }} /> + <Route path="/admin/sendEmail" render={() => { + if (CheckUserPermission()) + return <SendEmail /> + else + return <Unauthorized /> + }} /> </div> </div> </Switch> diff --git a/src/Components/ColCardOwnerOptions.js b/src/Components/ColCardOwnerOptions.js index 279ffa96b70221a6d28b2d34bdcf8082fdadd2b7..a075780622f76c453592afb7d07b84de6ccd3df3 100644 --- a/src/Components/ColCardOwnerOptions.js +++ b/src/Components/ColCardOwnerOptions.js @@ -42,7 +42,6 @@ export default function ColCardOwnerOptions (props) { } const [modalExcluirOpen, toggleModalExcluir] = useState(false) - const openModalExcluir = () => {toggleModalExcluir(true)} const [modalEditarOpen, toggleModalEditar] = useState(false) @@ -50,7 +49,7 @@ export default function ColCardOwnerOptions (props) { return ( <> <ModalExcluirColecao id={props.id} - open={modalExcluirOpen} handleClose={() => {toggleModalExcluir(false)}} + open={modalExcluirOpen} handleClose={() => {toggleModalExcluir(false)}} removeColl={props.removeColl} /> <ModalEditarColecao id={props.id} open={modalEditarOpen} handleClose={() => {toggleModalEditar(false)}} @@ -78,7 +77,7 @@ export default function ColCardOwnerOptions (props) { <ListItemIcon><CreateIcon /></ListItemIcon>Editar </StyledMenuItem> - <StyledMenuItem onClick={openModalExcluir}> + <StyledMenuItem onClick={() => {toggleModalExcluir(true)}} > <ListItemIcon><DeleteForeverIcon /></ListItemIcon>Excluir </StyledMenuItem> diff --git a/src/Components/CollectionCardFunction.js b/src/Components/CollectionCardFunction.js index 85f59e03ce1471a18330239ee2480e0ef1b41d99..6f7322e7261536655d78098ad28b3639e87af2a5 100644 --- a/src/Components/CollectionCardFunction.js +++ b/src/Components/CollectionCardFunction.js @@ -272,6 +272,7 @@ export default function CollectionCardFunction(props) { id={props.id} changeColName={changeColName} changeColPrivacy={changeColPrivacy} + removeColl={props.removeColl} /> </Grid> </Grid> diff --git a/src/Components/EcFooter.js b/src/Components/EcFooter.js index 2bdf8a2f0fb480c64970b913b8f223121b906273..eca582f2730cc230d7554d97acbda3afcfac95f5 100644 --- a/src/Components/EcFooter.js +++ b/src/Components/EcFooter.js @@ -16,11 +16,11 @@ 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, {Component} from 'react'; -import {Row, Col, Container} from 'react-grid-system'; +import React, { Component } from 'react'; +import { Row, Col, Container } from 'react-grid-system'; import eduConectada from '../img/educa-conectada.png'; import styled from 'styled-components'; -import {Link} from 'react-router-dom' +import { HashLink as Link } from 'react-router-hash-link'; const BlueFooter = styled.div` background-color : #00bcd4; @@ -30,12 +30,10 @@ const BlueFooter = styled.div` @media screen and (min-width : 502px) { padding-bottom : 2em; } - - vertical-align: bottom; ` -const listStyle={ +const listStyle = { listStyleType: "none", fontSize: "80%", padding: "0", @@ -46,35 +44,35 @@ const WhiteLink = styled(Link)` color: white; ` -class EcFooter extends Component{ - render(){ - return( +class EcFooter extends Component { + render() { + return ( <BlueFooter> <Container> - <Row> - <Col md={4} sm={6} xs={6} style={window.innerWidth < 502 && {textAlign : "center"} }> - <h4>Sobre</h4> - <ul style={listStyle}> - <li> <WhiteLink to="/sobre">Sobre a Plataforma</WhiteLink> </li> - <li> <WhiteLink to="/sobre#portaisparceiros">Portais Parceiros</WhiteLink> </li> - <li> <WhiteLink to="/termos">Termos de Uso</WhiteLink> </li> - <li> <WhiteLink to="/contato">Contato</WhiteLink> </li> - </ul> - </Col> - <Col md={4} sm={6} xs={6} style={window.innerWidth < 502 && {textAlign : "center"} }> - <h4>Ajuda</h4> - <ul style={listStyle}> - <li> <WhiteLink to="/ajuda">Central de Ajuda</WhiteLink> </li> - <li> <WhiteLink to="/publicando-recurso">Publicando Recursos</WhiteLink> </li> - <li> <WhiteLink to="/encontrando-recurso">Encontrando Recursos</WhiteLink> </li> - <li> <WhiteLink to="/participando-da-rede">Participando da Rede</WhiteLink> </li> - <li> <WhiteLink to="/gerenciando-conta">Gerenciando a Conta</WhiteLink> </li> - </ul> - </Col> - <Col md={4} sm={12} xs={12} style={window.innerWidth < 502 && {textAlign : "center"} }> - <img src={eduConectada} height="50%" alt="logo educação conectada"/> - </Col> - </Row> + <Row> + <Col md={4} sm={6} xs={6} style={window.innerWidth < 502 && { textAlign: "center" }}> + <h4>Sobre</h4> + <ul style={listStyle}> + <li> <WhiteLink to="/sobre">Sobre a Plataforma</WhiteLink> </li> + <li> <WhiteLink to="/sobre#portaisparceiros">Portais Parceiros</WhiteLink> </li> + <li> <WhiteLink to="/termos">Termos de Uso</WhiteLink> </li> + <li> <WhiteLink to="/contato">Contato</WhiteLink> </li> + </ul> + </Col> + <Col md={4} sm={6} xs={6} style={window.innerWidth < 502 && { textAlign: "center" }}> + <h4>Ajuda</h4> + <ul style={listStyle}> + <li> <WhiteLink to="/ajuda">Central de Ajuda</WhiteLink> </li> + <li> <WhiteLink to="/publicando-recurso">Publicando Recursos</WhiteLink> </li> + <li> <WhiteLink to="/encontrando-recurso">Encontrando Recursos</WhiteLink> </li> + <li> <WhiteLink to="/participando-da-rede">Participando da Rede</WhiteLink> </li> + <li> <WhiteLink to="/gerenciando-conta">Gerenciando a Conta</WhiteLink> </li> + </ul> + </Col> + <Col md={4} sm={12} xs={12} style={window.innerWidth < 502 && { textAlign: "center" }}> + <img src={eduConectada} height="50%" alt="logo educação conectada" /> + </Col> + </Row> </Container> </BlueFooter> ) diff --git a/src/Components/HelperFunctions/getAxiosConfig.js b/src/Components/HelperFunctions/getAxiosConfig.js index aa645cc9c86714f5cbbdf3439cbad7ab6f190db6..6d1608bc91648d8b83374f9c4949a9ada3401cdd 100644 --- a/src/Components/HelperFunctions/getAxiosConfig.js +++ b/src/Components/HelperFunctions/getAxiosConfig.js @@ -100,17 +100,9 @@ export async function getRequest (url, onSuccess, onError) { headers : fetchHeaders() }) if (response.ok) { - /*if (response.headers.has('access-token')) { - updateHeaders(response.headers) - }*/ if (response.headers.has('access-token')) { updateAccessToken(response.headers.get('access-token')) } - /*if (response.headers.has('client')) { - let auth_headers = JSON.parse(sessionStorage.getItem('@portalmec/auth_headers')) - auth_headers['client'] = response.headers.get('client') - sessionStorage.setItem('@portalmec/auth_headers', JSON.stringify(auth_headers)) - }*/ let json = await response.json() onSuccess(json, response.headers) } @@ -224,17 +216,9 @@ export async function fetchAllRequest (urls, onSuccess, onError) { var headers = [] for (let res of responses) { - /*if (checkPreviousTokens(res.headers.get('access-token'))) { - updateHeaders(res.headers) - }*/ if (res.headers.has('access-token') && res.status !== 304) { updateAccessToken(res.headers.get('access-token')) } - /*if (res.headers.has('client')) { - let auth_headers = JSON.parse(sessionStorage.getItem('@portalmec/auth_headers')) - auth_headers['client'] = res.headers.get('client') - sessionStorage.setItem('@portalmec/auth_headers', JSON.stringify(auth_headers)) - }*/ let json = await res.json().catch(err => { return {}; }) diff --git a/src/Components/HomeScreenSearchBar.js b/src/Components/HomeScreenSearchBar.js index 4427eb29fc05fdf4405695a860e83c4c3917d092..ef12b7cc21d761f9ac73d634d1a4e24fe180bd0d 100644 --- a/src/Components/HomeScreenSearchBar.js +++ b/src/Components/HomeScreenSearchBar.js @@ -27,55 +27,55 @@ import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown'; import SearchIcon from '@material-ui/icons/Search'; /*import {Link} from 'react-router-dom'*/ -export default function HomeScreenSearchBar (props) { - const [ query, setQuery ] = useState("") - const [ searchClass, setSearchClass ] = useState('LearningObject') +export default function HomeScreenSearchBar(props) { + const [query, setQuery] = useState("") + const [searchClass, setSearchClass] = useState('LearningObject') const { state, dispatch } = useContext(Store) - const [ goSearch, setGoSearch ] = useState(false) - - useEffect(()=>{ - if(window.location.pathname.includes('busca')){ - const urlParams = new URLSearchParams(window.location.search) - const urlQuery = urlParams.get('query') - const urlSearchClass = urlParams.get('search_class') - if( searchClass !== urlSearchClass || query !== urlQuery){ - setQuery(urlQuery) - setSearchClass(urlSearchClass) - } + const [goSearch, setGoSearch] = useState(false) + + useEffect(() => { + if (window.location.pathname.includes('busca')) { + const urlParams = new URLSearchParams(window.location.search) + const urlQuery = urlParams.get('query') + const urlSearchClass = urlParams.get('search_class') + if (searchClass !== urlSearchClass || query !== urlQuery) { + setQuery(urlQuery) + setSearchClass(urlSearchClass) + } } - },[]) + }, []) - useEffect(()=>setGoSearch(false),[goSearch]) + useEffect(() => setGoSearch(false), [goSearch]) - const handleChange = ( event ) => { - setQuery(event.target.value) + const handleChange = (event) => { + setQuery(event.target.value) } const handleKeyDown = (event) => { - if(event.key === 'Enter' || event.type === 'click'){ - dispatch({ - type: 'SAVE_SEARCH', - newSearch: { - query: query !== '' ? query: '*', - class: searchClass - } - }) - setGoSearch(true) - } + if (event.key === 'Enter' || event.type === 'click') { + dispatch({ + type: 'SAVE_SEARCH', + newSearch: { + query: query !== '' ? query : '*', + class: searchClass + } + }) + setGoSearch(true) + } } const options = [ - {text : "Recursos", value : "LearningObject", color : "#ff7f00"}, - {text : "Coleções", value : "Collection", color : "#673ab7"}, - {text : "Usuários", value : "User", color : "#00bcd4"}, + { text: "Recursos", value: "LearningObject", color: "#ff7f00" }, + { text: "Coleções", value: "Collection", color: "#673ab7" }, + { text: "Usuários", value: "User", color: "#00bcd4" }, ] const [anchorEl, setAnchorEl] = React.useState(null); const [selectedIndex, setSelectedIndex] = React.useState(0); const handleClickListItem = (event) => { - setAnchorEl(event.currentTarget); + setAnchorEl(event.currentTarget); }; const handleMenuItemClick = (event, index, value) => { @@ -93,69 +93,69 @@ export default function HomeScreenSearchBar (props) { return ( - <StyledGrid container> - {goSearch && <Redirect to={`/busca?query=${state.search.query}&search_class=${state.search.class}`} />} - <Grid item md={7} xs={12} className="first white"> - <StyledTextField - id="standard-search" - placeholder="O que está buscando?" - type="search" - margin="normal" - value={query} - onChange={handleChange} - onKeyPress={handleKeyDown} - fullwidth + <StyledGrid container> + {goSearch && <Redirect to={`/busca?query=${state.search.query}&search_class=${state.search.class}`} />} + <Grid item md={7} xs={12} className="first white"> + <StyledTextField + id="standard-search" + placeholder="O que está buscando?" + type="search" + margin="normal" + value={query} + onChange={handleChange} + onKeyPress={handleKeyDown} + fullwidth + /> + </Grid> + <Grid item md={3} xs={12} className="second white"> + <List component="nav" aria-label="Recurso"> + <ListItem + button + aria-haspopup="true" + aria-controls="lock-menu" + aria-label="Recurso" + onClick={handleClickListItem} + > + <ListItemText + style={{ color: options[selectedIndex].color }} + primary={options[selectedIndex].text} /> - </Grid> - <Grid item md={3} xs={12} className="second white"> - <List component="nav" aria-label="Recurso"> - <ListItem - button - aria-haspopup="true" - aria-controls="lock-menu" - aria-label="Recurso" - onClick={handleClickListItem} - > - <ListItemText - style={{color : options[selectedIndex].color}} - primary={options[selectedIndex].text} - /> - <ListItemIcon> - <ArrowDropDownIcon/> - </ListItemIcon> - </ListItem> - </List> - <Menu - id="simple-menu" - anchorEl={anchorEl} - keepMounted - open={Boolean(anchorEl)} - onClose={handleClose} - > - {options.map((option, index) => ( - <MenuItem + <ListItemIcon> + <ArrowDropDownIcon /> + </ListItemIcon> + </ListItem> + </List> + <Menu + id="simple-menu" + anchorEl={anchorEl} + keepMounted + open={Boolean(anchorEl)} + onClose={handleClose} + > + {options.map((option, index) => ( + <MenuItem key={option.value} selected={index === selectedIndex} onClick={(event) => handleMenuItemClick(event, index, option.value)} - style={{color : option.color}} - > + style={{ color: option.color }} + > {option.text} - </MenuItem> - ))} - </Menu> - </Grid> - <Grid item md={2} xs={12}> - <div style={{height : "100%"}}> - <Button onClick={handleKeyDown} className="custom-button" style={{backgroundColor : options[selectedIndex].color, color : "#fff"}}> - { - WIDTH < 503 && - <span>Buscar</span> - } - <SearchIcon fontSize="large"/> - </Button> - </div> - </Grid> - </StyledGrid> + </MenuItem> + ))} + </Menu> + </Grid> + <Grid item md={2} xs={12}> + <div style={{ height: "100%" }}> + <Button onClick={handleKeyDown} className="custom-button" style={{ backgroundColor: options[selectedIndex].color, color: "#fff" }}> + { + WIDTH < 503 && + <span>Buscar</span> + } + <SearchIcon fontSize="large" /> + </Button> + </div> + </Grid> + </StyledGrid> ) } diff --git a/src/Components/MenuBar.js b/src/Components/MenuBar.js index 0f1b536b4d1e45139a9a73b28bb63b6d27319cb8..7cf1153b7bdf834d4694b1d7367df27fbc9319ca 100644 --- a/src/Components/MenuBar.js +++ b/src/Components/MenuBar.js @@ -107,7 +107,7 @@ export default function MenuBar(props) { { name: "Favoritos", href: "/perfil", value: '2' }, { name: "Coleções", href: "/perfil", value: '3' }, { name: "Rede", href: "/perfil", value: '4' }, - { name: "Configurações", href: "/editarperfil", value: '5'}, + { name: "Configurações", href: "/editarperfil", value: '5' }, ] if (state.currentUser.roles) { @@ -116,15 +116,15 @@ export default function MenuBar(props) { const userRoles = [...state.currentUser.roles] while (!canUserAdmin && index < userRoles.length) { - if(userRoles[index].id === 3 || userRoles[index].id === 7) + if (userRoles[index].id === 3 || userRoles[index].id === 7) canUserAdmin = true index++ } - - if(canUserAdmin) + + if (canUserAdmin) minhaArea.push({ - name: "Administrador", - href: "/admin/home", + name: "Administrador", + href: "/admin/home", value: '6', }) } @@ -186,14 +186,14 @@ export default function MenuBar(props) { </div> <MenuList items={minhaArea} /> - + </> ) : ( <React.Fragment> <ButtonPubRecursoStyled onClick={props.openLogin}>PUBLICAR RECURSO?</ButtonPubRecursoStyled> <ButtonStyled onClick={props.openLogin}><ExitToAppIcon style={{ color: "#00bcd4" }} />Entrar</ButtonStyled> - <ButtonStyled onClick={props.openSignUp}>Cadastre-se</ButtonStyled> + <ButtonStyled onClick={props.openSignUp}>Cadastre-<span style={{textTransform: 'lowercase'}}>se</span></ButtonStyled> </React.Fragment> ) } diff --git a/src/Components/MobileDrawerMenu.js b/src/Components/MobileDrawerMenu.js index 469fa378e9dd7787829eee223147c59710c96b30..654ee7b9154f7fd34b15c8b36ee0c163e301f45f 100644 --- a/src/Components/MobileDrawerMenu.js +++ b/src/Components/MobileDrawerMenu.js @@ -172,7 +172,7 @@ export default function MobileDrawerMenu(props) { <div> <ButtonStyled onClick={props.openSignUp}> - Cadastre-se + Cadastre-<span style={{textTransform: 'lowercase'}}>se</span> </ButtonStyled> </div> </div> diff --git a/src/Components/ModalExcluirColecao.js b/src/Components/ModalExcluirColecao.js index 879112aebb46690447dcc1b3cdecb62e90adbbff..f23b819d88584a3ee2fab19dd94bf3935c90b782 100644 --- a/src/Components/ModalExcluirColecao.js +++ b/src/Components/ModalExcluirColecao.js @@ -31,6 +31,7 @@ export default function ModalExcluirColecao (props) { function handleDeleteSuccess (data) { toggleSnackbar(true) + props.removeColl(props.id) props.handleClose() } const handleDelete = () => { diff --git a/src/Components/TabPanels/PanelComponents/TemplateRede.js b/src/Components/TabPanels/PanelComponents/TemplateRede.js index 4fd3364085585a62ff575b4833c9aedd7ba97394..c792b7d2de531c63ef2ec1b44b2f4a61b992b163 100644 --- a/src/Components/TabPanels/PanelComponents/TemplateRede.js +++ b/src/Components/TabPanels/PanelComponents/TemplateRede.js @@ -76,7 +76,7 @@ export default function PanelTemplateRede(props) { props.sliceArr.map((card) => <> { - card.follower && + card.follower && card.followable && <Grid item xs={12} sm={6} md={'auto'} lg={3} key={card.id}> {RenderContactCard(card, props.follower)} </Grid> diff --git a/src/Components/TabPanels/PublicUserPageTabs/LastCollections.js b/src/Components/TabPanels/PublicUserPageTabs/LastCollections.js index 553b9788dc860e290de3b72bf1acdfd7e06b1730..6e32577f77617b47bda1298c2a583ce7a50cf249 100644 --- a/src/Components/TabPanels/PublicUserPageTabs/LastCollections.js +++ b/src/Components/TabPanels/PublicUserPageTabs/LastCollections.js @@ -54,7 +54,7 @@ export default function LastCols(props) { <StyledGrid container spacing={1} style={{ paddingLeft: "0.5em" }}> { props.collections.slice(0, 4).map((card) => - <Grid item md={3} xs={12} key={card.id}> + <Grid item container md={3} xs={12} key={card.id}> <CollectionCardFunction name={card.name} tags={card.tags} diff --git a/src/Components/TabPanels/PublicUserPageTabs/TabColecoes.js b/src/Components/TabPanels/PublicUserPageTabs/TabColecoes.js index 22fe8e4da3e4ba7e536b2227ca7319f39f600805..4b46dc0700385baa2b787e847b8a671ed3f1f262 100644 --- a/src/Components/TabPanels/PublicUserPageTabs/TabColecoes.js +++ b/src/Components/TabPanels/PublicUserPageTabs/TabColecoes.js @@ -17,79 +17,104 @@ 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, { useState, useEffect } from 'react' -import { HeaderGrid, ContainerStyled, Carregados, StyledGrid } from '../StyledComponents.js' -import Grid from '@material-ui/core/Grid'; -import CollectionCardFunction from '../../CollectionCardFunction.js' -import { ButtonMostrarMaisColecao } from '../PanelComponents/ButtonsArea.js' - -export default function TabRecursos(props) { - const [arr, setArr] = useState([]) - const [colsSlice, setSlice] = useState([]) - const handleSlice = (newArr) => { setSlice(newArr) } - +import { fetchAllRequest, getRequest } from '../../HelperFunctions/getAxiosConfig' +import PanelTemplateColecao from '../PanelComponents/TemplateColecao.js' +import LoadingSpinner from '../../LoadingSpinner.js' + +export default function TabColecoes(props) { + const [loading, handleLoading] = useState(true) + + const [errorInUserColl, setErrorInUserColl] = useState(false) + + const [userCollections, setUserCollections] = useState([]) + + const [currLimitUserColl, setCurrLimitUserColl] = useState(4) + + const [loadingMoreUserColl, setLoadingMoreUserColl] = useState(false); + + const [endOfUserColl, setEndOfUserColl] = useState(false); + + function handleSuccess(responseArr, headersArr) { + setErrorInUserColl(responseArr[0].errors ? true : false) + + handleLoading(false) + setUserCollections(responseArr[0]) + + if (headersArr[0].has('X-Total-Count')) { + setEndOfUserColl(headersArr[0].get('X-Total-Count')); + } + } + + function handleError(error) { + handleLoading(false) + setErrorInUserColl(true) + } + + const getInfo = () => { + const urls = [ + `/users/${props.id}/collections?offset=0&limit=4`, + ] + fetchAllRequest(urls, handleSuccess, handleError) + } + useEffect(() => { - setArr(props.collections) - setSlice(props.collections.slice(0, 4)) + handleLoading(true) + getInfo() }, []) - - const showMore = (quantity) => { - var sliceLength = colsSlice.length - handleSlice(arr.slice(0, sliceLength + quantity)) + + const showMoreUserCollections = (limite) => { + const limit = limite; + setLoadingMoreUserColl(true); + setCurrLimitUserColl(currLimitUserColl + limit) + const url = `/users/${props.id}/collections?offset=${currLimitUserColl}&limit=${limit}`; + getRequest(url, + (data) => { + if (data.errors) { + setLoadingMoreUserColl(false); + setEndOfUserColl(true) + setErrorInUserColl(true) + } + else if (data.length >= 1) { + let currData = [...userCollections]; + currData = [...currData.concat(data)]; + setLoadingMoreUserColl(false); + setUserCollections(currData); + } + else { + setLoadingMoreUserColl(false); + setEndOfUserColl(true) + } + }, + (error) => { + setLoadingMoreUserColl(false); + setEndOfUserColl(true) + setErrorInUserColl(true) + } + ) } return ( - <ContainerStyled style={{ flexDirection: "column" }}> - - <HeaderGrid container> - <Grid item xs={12}> - <h3>Coleções públicas <b style={{ fontWeight: "500" }}>({props.count})</b></h3> - </Grid> - </HeaderGrid> - - <StyledGrid container spacing={1} style={{ paddingLeft: "30px", paddingRight: "15px" }}> - { - colsSlice.map((card) => - <Grid item xs={12} sm={6} md={'auto'} lg={3} key={card.id}> - <CollectionCardFunction - name={card.name} - tags={card.tags} - rating={card.review_average} - id={card.id} - author={card.owner.name} - description={card.description} - thumbnails={card.items_thumbnails} - avatar={card.owner.avatar} - likeCount={card.likes_count} - followed={card.followed} - liked={card.liked} - collections={card.collection_items} - authorID={card.owner.id} - /> - </Grid> - ) - } - </StyledGrid> - - <Carregados> - <p style={{ margin: "0 0 10px", fontSize: "14px" }}> - Carregados {colsSlice.length} de {arr.length} - </p> - - { - props.count > 5 && - <React.Fragment> - <ButtonMostrarMaisColecao onClick={() => { showMore(4) }}> - <span style={{ color: "#fff", fontSize: "14px", fontWeight: "500" }}>MOSTRAR MAIS 4</span> - </ButtonMostrarMaisColecao> - - <ButtonMostrarMaisColecao onClick={() => { showMore(20) }}> - <span style={{ color: "#fff", fontSize: "14px", fontWeight: "500" }}>MOSTRAR MAIS 20</span> - </ButtonMostrarMaisColecao> - </React.Fragment> - } - - </Carregados> - - </ContainerStyled> + <> + { + loading ? + ( + <LoadingSpinner text={'CARREGANDO COLEÇÕES'} /> + ) + : + ( + <PanelTemplateColecao + title={"Coleções Públicas"} + length={userCollections.length} + noContentText={props.username + " não possui nenhuma coleção."} + sliceArr={userCollections} + showMore={showMoreUserCollections} + loadingMore={loadingMoreUserColl} + end={endOfUserColl} + followed={false} + error={errorInUserColl} + /> + ) + } + </> ) } diff --git a/src/Components/TabPanels/PublicUserPageTabs/TabRede.js b/src/Components/TabPanels/PublicUserPageTabs/TabRede.js index c173dc195d4000acbeda628ffbbef127d1934339..6b8a8a8ee73eb0ede45b2b3ed40785697169cbac 100644 --- a/src/Components/TabPanels/PublicUserPageTabs/TabRede.js +++ b/src/Components/TabPanels/PublicUserPageTabs/TabRede.js @@ -18,62 +18,158 @@ along with Plataforma Integrada MEC. If not, see <http://www.gnu.org/licenses/> import React, {useState, useEffect} from 'react' import PanelTemplateRede from '../PanelComponents/TemplateRede.js' -import {fetchAllRequest} from '../../HelperFunctions/getAxiosConfig' +import { fetchAllRequest, getRequest } from '../../HelperFunctions/getAxiosConfig' +import LoadingSpinner from '../../LoadingSpinner.js' export default function TabRede (props) { - const [followers, setFollowers] = useState([]) - const [followersSlice, setFollowersSlice] = useState([]) + const [loading, handleLoading] = useState(true) - const showMoreFollowers = () => { - let varSlice = followersSlice.length - setFollowersSlice(followers.slice(0, varSlice + 4)) - } - const showAllFollowers = () => {setFollowersSlice(followers)} + const [errorInFollowing, setErrorInFollowing] = useState(false) + const [errorInFollowers, setErrorInFollowers] = useState(false) + + const [followingList, setFollowing] = useState([]) + const [currFollowingLimit, setCurrFollowingLimit] = useState(12) + const [loadingMoreFollowing, setLoadingFollowing] = useState(false) + const [endOfFollowing, setEndOfFollowing] = useState(false) + + const [followersList, setFollowers] = useState([]) + const [currFollowerLimit, setFollowersLimit] = useState(12) + const [loadingMoreFollowers, setLoadingMoreFollowers] = useState(false) + const [endOfFollowers, setEndOfFollowers] = useState(false) - const [following, setFollowing] = useState([]) - const [followingSlice, setFollowingSlice] = useState([]) - const showMoreFollowing = () => { - let varSlice = followingSlice.length - setFollowingSlice(following.slice(0, varSlice + 4)) - } - const showAllFollowing = () => {setFollowingSlice(following)} + const showMoreFollowing = (limite) => { + setLoadingFollowing(true); + const limit = limite; + setCurrFollowingLimit(currFollowingLimit + limit) + const url = `/users/${props.id}/following/User?offset=${currFollowingLimit}&limit=${limit}`; + getRequest(url, + (data) => { + if (data.errors) { + setLoadingFollowing(false); + setEndOfFollowing(true); + setErrorInFollowing(true); + } + else if (data.length >= 1) { + let currData = [...followingList]; + currData = [...currData.concat(data)]; + setLoadingFollowing(false); + setFollowing(currData); + } + else { + setLoadingFollowing(false); + setEndOfFollowing(true); + } + }, + (error) => { + setLoadingFollowing(false); + setEndOfFollowing(true); + setErrorInFollowing(true); + } + ) + } + + const showMoreFollowers = (limite) => { + setLoadingMoreFollowers(true); + const limit = limite; + setFollowersLimit(currFollowerLimit + limit) + const url = `/users/${props.id}/followers?offset=${currFollowerLimit}&limit=${limit}`; + getRequest(url, + (data) => { + if (data.errors) { + setLoadingMoreFollowers(false); + setEndOfFollowers(true); + setErrorInFollowers(true); + } + else { + if (data.length >= 1) { + let currData = [...followersList]; + currData = [...currData.concat(data)]; + setLoadingMoreFollowers(false); + setFollowers(currData); + } + else { + setLoadingMoreFollowers(false); + setEndOfFollowers(true) + } + } + }, + (error) => { + setLoadingMoreFollowers(false); + setEndOfFollowers(true); + setErrorInFollowers(true); + } + ) + } - function handleSuccess (responseArr) { + async function handleSuccess (responseArr, headersArr) { + setErrorInFollowing(responseArr[0].errors ? true : false) // prevent of crashing the portal, do not remove it + setErrorInFollowers(responseArr[1].errors ? true : false) // prevent of crashing the portal, do not remove it setFollowers(responseArr[0]) - setFollowersSlice(responseArr[0].slice(0,4)) - setFollowing(responseArr[1]) - setFollowingSlice(responseArr[1].slice(0,4)) + + if (headersArr[1].has('X-Total-Count')) { + setEndOfFollowing(headersArr[1].get('X-Total-Count')); + } + if (headersArr[0].has('X-Total-Count')) { + setEndOfFollowers(headersArr[0].get('X-Total-Count')); + } + handleLoading(false) + } + + function handleErrors() { + setLoadingMoreFollowers(false); + setEndOfFollowers(true); + setErrorInFollowers(true); } useEffect( () => { + handleLoading(true) const urls = [`/users/${props.id}/followers`, `/users/${props.id}/following/User`] - fetchAllRequest(urls, handleSuccess, (error) => {console.log(error)}) + fetchAllRequest(urls, handleSuccess, handleErrors) }, []) return ( - <React.Fragment> - <PanelTemplateRede - title={"Seguidores"} - length={followers.length} - sliceArr={followersSlice} - showMore={showMoreFollowers} - showAll={showAllFollowers} - follower={true} - noContentText={props.username + ' não possui nenhum seguidor'} - /> - - <PanelTemplateRede - title={"Seguindo"} - length={following.length} - sliceArr={followingSlice} - showMore={showMoreFollowing} - showAll={showAllFollowing} - follower={false} - noContentText={props.username + ' não segue nenhum usuário'} - /> - </React.Fragment> + <> + { + loading ? + ( + [ + <LoadingSpinner text={'CARREGANDO...'} /> + ] + ) + : + ( + [ + <React.Fragment> + <PanelTemplateRede + title={"Seguidores"} + length={followersList.length} + sliceArr={followersList} + showMore={showMoreFollowers} + follower={true} + end={endOfFollowers} + loadingMore={loadingMoreFollowers} + error={errorInFollowers} + noContentText={props.username + ' não possui nenhum seguidor'} + /> + + <PanelTemplateRede + title={"Seguindo"} + length={followingList.length} + sliceArr={followingList} + showMore={showMoreFollowing} + follower={false} + end={endOfFollowing} + loadingMore={loadingMoreFollowing} + error={errorInFollowing} + noContentText={props.username + ' não segue nenhum usuário'} + /> + </React.Fragment> + ] + ) + } + </> ) } diff --git a/src/Components/TabPanels/StyledComponents.js b/src/Components/TabPanels/StyledComponents.js index c8e75d5d2774b63cbb3140a3f40d7d45abb97f84..182fd013462a57191b7482f708e4379537c4255c 100644 --- a/src/Components/TabPanels/StyledComponents.js +++ b/src/Components/TabPanels/StyledComponents.js @@ -173,7 +173,7 @@ export const UserProfileContainer = styled.div` export const CoverContainer = styled.div` height : 230px; position : relative; - @media screen and (max-width: 501px) { + @media screen and (max-width: 600px) { height : 128px } ` diff --git a/src/Components/TabPanels/UserPageTabs/PanelColecoes.js b/src/Components/TabPanels/UserPageTabs/PanelColecoes.js index 420071c2cf0b7ec4b7a4feb7a12826ad1041b063..eef4d1eaa7df0728081c75d13d87e15db0f199b7 100644 --- a/src/Components/TabPanels/UserPageTabs/PanelColecoes.js +++ b/src/Components/TabPanels/UserPageTabs/PanelColecoes.js @@ -50,6 +50,12 @@ export default function TabPanelColecoes(props) { const [endOfUserColl, setEndOfUserColl] = useState(false); const [endOfFollowedColl, setEndOfFollowedColl] = useState(false); + const removeColl = (itemId) => { + let newSlice = userCollections.filter(item => item.id !== itemId); + setUserCollections(newSlice); + setEndOfUserColl(String(endOfUserColl - 1)) + }; + function handleSuccess(responseArr, headersArr) { setErrorInUserColl(responseArr[0].errors ? true : false) setErrorInFollowedColl(responseArr[1].errors ? true : false) @@ -181,10 +187,11 @@ export default function TabPanelColecoes(props) { end={endOfUserColl} callback={getInfo} error={errorInUserColl} + removeColl={removeColl} /> <PanelTemplateColecao - title={"Coleções que eu sigo"} + title={"Coleções que você segue"} length={followedCollections.length} noContentText={"Você ainda não segue nenhuma coleção."} sliceArr={followedCollections} @@ -272,6 +279,7 @@ function Tentativa(props) { liked={card.liked} collections={card.collection_items} authorID={card.owner.id} + removeColl={props.removeColl} /> </Grid> ) diff --git a/src/Components/TabPanels/UserPageTabs/PanelEditarPerfil.js b/src/Components/TabPanels/UserPageTabs/PanelEditarPerfil.js index e8d253324b68c006cc892d5084ab8d0f15e3f977..ce5a319efaacbf631c7a3871c0ee8672a8f68db1 100644 --- a/src/Components/TabPanels/UserPageTabs/PanelEditarPerfil.js +++ b/src/Components/TabPanels/UserPageTabs/PanelEditarPerfil.js @@ -37,13 +37,13 @@ export default function TabPanelEditarPerfil(props) { const [hoverAlterarFoto, handleAlterarFoto] = React.useState(false) const [formNome, setNome] = useState({ - key: false, - value: "" + key: state.currentUser.name ? false : true, + value: state.currentUser.name ? state.currentUser.name : "" }) const [formAboutMe, setAboutMe] = useState({ - key: false, - value: "", + key: state.currentUser.description ? false : true, + value: state.currentUser.description ? state.currentUser.description : "" }) const handleHoverAlterarFoto = () => { @@ -86,14 +86,14 @@ export default function TabPanelEditarPerfil(props) { const limpaCamposForm = () => { setNome({ ...formNome, - key: false, - value: '' + key: state.currentUser.name ? false : true, + value: state.currentUser.name ? state.currentUser.name : "" }) setAboutMe({ ...formAboutMe, - key: false, - value: '' + key: state.currentUser.description ? false : true, + value: state.currentUser.description ? state.currentUser.description : "" }) } @@ -102,7 +102,7 @@ export default function TabPanelEditarPerfil(props) { const handleSubmit = (e) => { e.preventDefault() - const info = { user: { name: formNome.value, description: formAboutMe.value, email: sessionStorage.getItem('@portalmec/uid') } } + const info = { user: { name: formNome.value, description: formAboutMe.value, email: state.currentUser.email } } const flagNome = formNome.key const flagAboutMe = formAboutMe.key @@ -172,7 +172,7 @@ export default function TabPanelEditarPerfil(props) { rows="3" rowsMax="3" error={formAboutMe.key} - placeholder={"Sobre Mim"} + placeholder={"Sobre mim (visÃvel no seu perfil público)"} handleChange={e => handleChange(e, 'aboutMe')} required={false} help={formAboutMe.value.length + '/160'} diff --git a/src/Components/UploadPageComponents/UploadFileWrapper.js b/src/Components/UploadPageComponents/UploadFileWrapper.js index 123512f2dc9e81026f99a2173cd573e1ed0f7e32..b8919a54a0de3a1872de7c5258d32fdecfedc656 100644 --- a/src/Components/UploadPageComponents/UploadFileWrapper.js +++ b/src/Components/UploadPageComponents/UploadFileWrapper.js @@ -22,7 +22,7 @@ import ChooseLink from './ChooseLinkSection.js' import {WrapperBox, BlueButton, GrayButton} from './StyledComponents.js'; import {DottedBox} from './StyledComponents.js'; import {getAxiosConfigFromJSON, updateHeaders, deleteRequest, putRequest} from '../HelperFunctions/getAxiosConfig.js' -import AddAPhotoIcon from '@material-ui/icons/AddAPhoto'; +import AttachFileIcon from '@material-ui/icons/AttachFile'; import axios from 'axios' import {apiUrl} from '../../env'; import DoneIcon from '@material-ui/icons/Done'; @@ -246,7 +246,7 @@ export default function UploadFileWrapper (props) { onDrop={e => handleDrop(e)} onDragOver={e => handleDragOver(e)} > - <AddAPhotoIcon className="icon"/> + <AttachFileIcon className="icon"/> <input type="file" onChange = {(e) => {onFileChange(e.target.files[0])}} @@ -255,7 +255,7 @@ export default function UploadFileWrapper (props) { /> <BlueButton> <label htmlFor="upload-file" style={{width : "inherit", cursor : "pointer"}}> - ESCOLHER IMAGEM + ESCOLHER ARQUIVO </label> </BlueButton> <span style={{marginTop : "6px"}}>Ou arrastar e soltar o arquivo aqui</span> diff --git a/src/Components/UserPageComponents/Avatar.js b/src/Components/UserPageComponents/Avatar.js index 368b54b6fdbb513f7c397ebf755da60f4d300a7f..8c381f197741f833d9171c58b780ffb37bb8ad1b 100644 --- a/src/Components/UserPageComponents/Avatar.js +++ b/src/Components/UserPageComponents/Avatar.js @@ -68,7 +68,7 @@ const ProfileAvatarDiv = styled.div` outline : 0; cursor : pointer; background-color : #a5a5a5; - @media screen and (max-width: 501px) { + @media screen and (max-width: 600px) { height : 73px; width : 73px; position:absolute; diff --git a/src/Components/maintenance.js b/src/Components/maintenance.js new file mode 100644 index 0000000000000000000000000000000000000000..f39358e42ef75e8ee1a1b4afbfb14abd44365340 --- /dev/null +++ b/src/Components/maintenance.js @@ -0,0 +1,19 @@ +import React from 'react' +import styled from 'styled-components' + +export default function Maintenance() { + return ( + <MaintenanceDiv> + Estamos em manuntenção. Em breve voltaremos! + </MaintenanceDiv> + ) +} + +const MaintenanceDiv = styled.div` + z-index: 1000; + position: fixed; + color:white; + background-color: red; + text-align: center; + width: 100%; +` \ No newline at end of file diff --git a/src/Pages/AboutPage.js b/src/Pages/AboutPage.js index 56b8404129be79f65c0d98f971bb7006e316d1dd..98fdfd0596c3aa455cac4ee0b3769a7cdac3a1cd 100644 --- a/src/Pages/AboutPage.js +++ b/src/Pages/AboutPage.js @@ -16,7 +16,7 @@ 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 from 'react'; +import React, { useEffect } from 'react'; import Grid from '@material-ui/core/Grid'; import styled from 'styled-components'; import Modal from '../Components/ModalAbout'; @@ -551,26 +551,31 @@ const Secao8 = styled.div` export default function AboutPage(props) { var pageWidth = window.innerWidth - const calculateMargin = ((pageWidth)=>{ - if (pageWidth > 700 && pageWidth <= 850){ + const calculateMargin = ((pageWidth) => { + if (pageWidth > 700 && pageWidth <= 850) { return "40%" } - if (pageWidth > 850 && pageWidth <= 900){ + if (pageWidth > 850 && pageWidth <= 900) { return "25%" } - if (pageWidth > 900 && pageWidth < 1100){ + if (pageWidth > 900 && pageWidth < 1100) { return "13%" } - else{ + else { return "0%" } }) var marginSet = calculateMargin(pageWidth) - const styleIMGSec3 = {float:"right", width:"80%", maxWidth:475, marginRight:30, marginTop: marginSet} + const styleIMGSec3 = { float: "right", width: "80%", maxWidth: 475, marginRight: 30, marginTop: marginSet } + + useEffect(() => { + window.scrollTo(0, 0) + }, []) + return ( <> - <link href="https://fonts.googleapis.com/css?family=Pompiere|Roboto:300,400&display=swap" rel="stylesheet"/> + <link href="https://fonts.googleapis.com/css?family=Pompiere|Roboto:300,400&display=swap" rel="stylesheet" /> <Secao1> <iframe title="VÃdeo página sobre" src="https://player.vimeo.com/video/231609051" width="100%" height="100%" frameBorder="0" allow="autoplay; fullscreen" allowFullScreen></iframe> @@ -582,7 +587,7 @@ export default function AboutPage(props) { <div className="container-secao"> <div className="conteudo-secao"> <h2>Um Pouco da História</h2> - <p style={{marginLeft:20, marginRight:20, marginBottom:40}}> + <p style={{ marginLeft: 20, marginRight: 20, marginBottom: 40 }}> A partir de uma iniciativa do Ministério da Educação, surge em outubro de 2015 a proposta de reunir e disponibilizar, em um único lugar, os Recursos Educacionais Digitais dos principais @@ -592,13 +597,13 @@ export default function AboutPage(props) { da Educação Básica de todo o Brasil. Assim, a Plataforma MEC pretende se tornar uma referência em Recursos Educacionais Digitais, como um ambiente de busca, interação e colaboração - entre professoras(es)!<br/><br/>Faça parte deste espaço de + entre professoras(es)!<br /><br />Faça parte deste espaço de colaborativo você também! </p> <img src={Agpl} alt="agpl" /> <p> Este programa é software livre, sob os termos da - <a href="https://www.gnu.org/licenses/agpl-3.0.en.html" rel="noreferrer" target="_blank"> licença GNU/AGPL</a><br/> + <a href="https://www.gnu.org/licenses/agpl-3.0.en.html" rel="noreferrer" target="_blank"> licença GNU/AGPL</a><br /> Seu código fonte está disponÃvel no <a href="https://gitlab.c3sl.ufpr.br/portalmec/portalmec" rel="noreferrer" target="_blank">GitLab</a> </p> @@ -613,7 +618,7 @@ export default function AboutPage(props) { <div className="container-secao"> <div className="conteudo-secao"> <Grid container spacing={0}> - <Grid item xs style={{paddingRight:20}}> + <Grid item xs style={{ paddingRight: 20 }}> <h2>O que nos faz diferentes?</h2> <h3>Espaço construÃdo por e para professores</h3> <p> @@ -630,19 +635,19 @@ export default function AboutPage(props) { </p> <h3>Todos os recursos em um só lugar</h3> <p> - Aqui você consegue otimizar o seu tempo! A plataforma integra - os Recursos Educacionais Digitais dos principais portais abertos. + Aqui você consegue otimizar o seu tempo! A plataforma integra + os Recursos Educacionais Digitais dos principais portais abertos. </p> </Grid> { - pageWidth >= 751? - <Grid item xs={6} style={{position:"relative"}}> - <img src={Notebook} alt="Imagem Notebook" style={styleIMGSec3}/> - </Grid> - : - <div/> + pageWidth >= 751 ? + <Grid item xs={6} style={{ position: "relative" }}> + <img src={Notebook} alt="Imagem Notebook" style={styleIMGSec3} /> + </Grid> + : + <div /> } - + </Grid> @@ -651,10 +656,10 @@ export default function AboutPage(props) { </div> </Secao3> - - + + <Secao4> - <div className="container"> + <div className="container"> <div className="container-secao" id="portaisparceiros"> <div className="conteudo-secao" > <div> @@ -662,18 +667,18 @@ export default function AboutPage(props) { <p>Aqui na Plataforma você encontra os Recursos Digitais dos principais portais do MEC e de vários outros parceiros.</p> </div> - <AboutCarouselPartner/> - + <AboutCarouselPartner /> + <div> <h3>Você busca Recursos Educacionais Digitais em outros sites?</h3> <p> - Você gostaria que a plataforma tivesse os recursos do site que - você acessa?<br/>Deixe a sua sugestão pra que juntos possamos + Você gostaria que a plataforma tivesse os recursos do site que + você acessa?<br />Deixe a sua sugestão pra que juntos possamos avançar na integração dos mais variados recursos. </p> </div> - <div style={{marginTop:"30px"}}> - <Modal/> + <div style={{ marginTop: "30px" }}> + <Modal /> </div> </div> @@ -686,7 +691,7 @@ export default function AboutPage(props) { <div className="container-secao"> <div className="conteudo-secao"> <h2>AQUI VOCÊ É PROTAGONISTA</h2> - <br/> + <br /> <p> Construa conosco a plataforma e amplie sua rede de conhecimento interagindo com pessoas envolvidas com experiências que ocorrem em todo o Brasil! @@ -697,20 +702,20 @@ export default function AboutPage(props) { </Secao5> <Secao6> - <div className="container"> - <div className="container-secao"> - <div className="conteudo-secao"> - <div> - <h2>Aqui você pode:</h2> + <div className="container"> + <div className="container-secao"> + <div className="conteudo-secao"> + <div> + <h2>Aqui você pode:</h2> - </div> - <div> - <AboutCarousel/> - </div> + </div> + <div> + <AboutCarousel /> + </div> + </div> </div> </div> - </div> </Secao6> <Secao7> @@ -720,7 +725,7 @@ export default function AboutPage(props) { <div className="cabecalho"> <h2>A quem se destina?</h2> <p>A plataforma é aberta e destina-se a todos e todas que se - interessam<br/>pela relação entre a escola e a Cultura Digital:</p> + interessam<br />pela relação entre a escola e a Cultura Digital:</p> </div> <div> <Grid container spacing={3}> @@ -776,18 +781,18 @@ export default function AboutPage(props) { </Secao7> <Secao8> - <div className="container"> - <div className="container-secao"> - <div className="conteudo-secao"> + <div className="container"> + <div className="container-secao"> + <div className="conteudo-secao"> - <h2>Ficou alguma dúvida? Gostaria de fazer alguma sugestão ou crÃtica? Construa conosco.</h2> - <div> - <button><a href="contato">ENTRAR EM CONTATO</a></button> - </div> + <h2>Ficou alguma dúvida? Gostaria de fazer alguma sugestão ou crÃtica? Construa conosco.</h2> + <div> + <button><a href="contato">ENTRAR EM CONTATO</a></button> + </div> + </div> </div> </div> - </div> </Secao8> </> ); diff --git a/src/Pages/Contact.js b/src/Pages/Contact.js index cf2b6458651e13aa36791ed17ee0c60f896c655d..181e16d47158efdbdd9492fc29fe49b7d2df80de 100644 --- a/src/Pages/Contact.js +++ b/src/Pages/Contact.js @@ -16,7 +16,7 @@ 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 from "react"; +import React, { useEffect } from "react"; import styled from "styled-components"; import Banner1 from "../img/banner-sobre.jpg"; import InputFormulario from "../Components/ContactForm.js"; @@ -137,6 +137,11 @@ const Formulario = styled.div` `; function Contact(props) { + + useEffect(() => { + window.scrollTo(0, 0) + }) + return ( <> <link diff --git a/src/Pages/HelpCenter.js b/src/Pages/HelpCenter.js index f70481b0db11f0001894d7909721f1f293758eca..8b5ae50935da62fd6dc530bd1b82d50e6d4df6eb 100644 --- a/src/Pages/HelpCenter.js +++ b/src/Pages/HelpCenter.js @@ -16,10 +16,10 @@ 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 from 'react'; +import React, { useEffect } from 'react'; import styled from 'styled-components'; import Grid from '@material-ui/core/Grid'; -import { Link } from 'react-router-dom'; +import { Link } from 'react-router-dom'; @@ -36,20 +36,22 @@ import CardGerenciando from '../Components/HelpCenter/Cards/CardGerenciando'; function HelpCenter(props) { let windowWidth = window.innerWidth - return( - <div style={{backgroundColor: "#f4f4f4"}}> - <link href="https://fonts.googleapis.com/css?family=Pompiere|Roboto:300,400&display=swap" rel="stylesheet"/> + useEffect(() => { window.scrollTo(0, 0) }, []) + + return ( + <div style={{ backgroundColor: "#f4f4f4" }}> + <link href="https://fonts.googleapis.com/css?family=Pompiere|Roboto:300,400&display=swap" rel="stylesheet" /> <Secao1> - <div className= "container"> + <div className="container"> { - windowWidth > 420? - <img src={Banner3} alt="banner3"/> - : - <div/> + windowWidth > 420 ? + <img src={Banner3} alt="banner3" /> + : + <div /> } - <div className= "conteudo"> - <div className= "title"> + <div className="conteudo"> + <div className="title"> <h2>OLÃ! COMO PODEMOS AJUDAR?</h2> </div> </div> @@ -64,18 +66,18 @@ function HelpCenter(props) { <h2>Tópicos de Ajuda</h2> </div> <div> - <Grid container justify="center" style={{margin:-8}}> - <Grid item xs={12} md={5} style={{padding:8}}> - <CardPublicando/> + <Grid container justify="center" style={{ margin: -8 }}> + <Grid item xs={12} md={5} style={{ padding: 8 }}> + <CardPublicando /> </Grid> - <Grid item xs={12} md={5} style={{padding:8}}> - <CardEncontrando/> + <Grid item xs={12} md={5} style={{ padding: 8 }}> + <CardEncontrando /> </Grid> - <Grid item xs={12} md={5} style={{padding:8}}> - <CardParticipando/> + <Grid item xs={12} md={5} style={{ padding: 8 }}> + <CardParticipando /> </Grid> - <Grid item xs={12} md={5} style={{padding:8}}> - <CardGerenciando/> + <Grid item xs={12} md={5} style={{ padding: 8 }}> + <CardGerenciando /> </Grid> </Grid> </div> @@ -84,10 +86,10 @@ function HelpCenter(props) { </div> </Secao2> - <div style={{width:"100%"}}> - <Secao3> - <Grid style={{height:"100%"}} container justify="center"> - <Grid style={{backgroundColor: "#333",paddingInline:"0" }} item xs={12} md={6}> + <div style={{ width: "100%" }}> + <Secao3> + <Grid style={{ height: "100%" }} container justify="center"> + <Grid style={{ backgroundColor: "#333", paddingInline: "0" }} item xs={12} md={6}> <iframe title="VÃdeo página ajuda" src="https://player.vimeo.com/video/231609051" width="100%" height="100%" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe> </Grid> <Grid item xs={12} md={6}> @@ -102,39 +104,39 @@ function HelpCenter(props) { <Grid container> <Grid item xs={12} md={6}> <p className="links"> - <br/> + <br /> <Link to={{ - pathname : 'plataforma-mec', - state : {value : '0'} + pathname: 'plataforma-mec', + state: { value: '0' } }}>O que é a Plataforma MEC</Link> - <br/> + <br /> <Link to={{ - pathname : 'plataforma-mec', - state : {value : '1'} - }}>Como foi construida a Plataforma<br/>MEC?</Link> - <br/> + pathname: 'plataforma-mec', + state: { value: '1' } + }}>Como foi construida a Plataforma<br />MEC?</Link> + <br /> <Link to={{ - pathname : 'plataforma-mec', - state : {value : '3'} + pathname: 'plataforma-mec', + state: { value: '3' } }}>Quais são os Portais Parceiros?</Link> </p> </Grid> <Grid item xs={12} md={6}> <p className="links"> - <br/> + <br /> <Link to={{ - pathname : 'plataforma-mec', - state : {value : '2'} + pathname: 'plataforma-mec', + state: { value: '2' } }}>Entendendo as 3 áreas</Link> - <br/> + <br /> <Link to={{ - pathname : 'plataforma-mec', - state : {value : '4'} + pathname: 'plataforma-mec', + state: { value: '4' } }}>Tipos de recursos</Link> - <br/> + <br /> <Link to={{ - pathname : 'plataforma-mec', - state : {value : '5'} + pathname: 'plataforma-mec', + state: { value: '5' } }}>Softwares especÃficos</Link> </p> </Grid> @@ -150,8 +152,8 @@ function HelpCenter(props) { <div className="conteudo"> <h2>Não encontrou o que você precisa?</h2> <span>Entre em contato com a nossa Central de Ajuda</span> - <br/> - <button style={{marginBottom:50, marginTop:20}}><a href="contato">ENTRAR EM CONTATO</a></button> + <br /> + <button style={{ marginBottom: 50, marginTop: 20 }}><a href="contato">ENTRAR EM CONTATO</a></button> </div> </div> diff --git a/src/Pages/PublicUserPage.js b/src/Pages/PublicUserPage.js index 0f2a14d5930535cd1309fa7f10fcb591c45f8af6..070d3cb4f7e265299ddf3efe5dfbad3124f57cbe 100644 --- a/src/Pages/PublicUserPage.js +++ b/src/Pages/PublicUserPage.js @@ -42,7 +42,7 @@ function RenderFollowContainer(props) { const { state } = useContext(Store) const [followed, setFollowed] = useState(props.followed) const toggleFollowed = () => { setFollowed(!followed) } - console.log(followed); + return ( <FollowContainer> <> @@ -103,7 +103,7 @@ export default function PublicUserPage(props) { const { state } = useContext(Store) /*user info variables--------------------------------------*/ const WIDTH = window.innerWidth; - const id = props.match.params.userId + const [id, setId] = useState(props.match.params.userId) const [loading, setLoading] = useState(false); @@ -148,10 +148,12 @@ export default function PublicUserPage(props) { /*Component Will Mount*/ useEffect(() => { + const id = props.match.params.userId + setId(id) const urls = [`/users/${id}`, `/users/${id}/learning_objects`, `/users/${id}/collections`, `/users/${id}/following/User`] setLoading(true); fetchAllRequest(urls, handleSuccess, (error) => { console.log(error) }) - }, [state.currentUser.id]) + }, [state.currentUser.id, props.match.params.userId]) /*---------------------------------------------------------*/ return ( @@ -226,7 +228,7 @@ export default function PublicUserPage(props) { { tabs.map((tab) => <Tab label={tab} key={tab} - disabled={(tab === "Recursos" && learningObjArr.length === 0) || (tab === "Coleções" && collectionsArr.length === 0)} + disabled={(tab === "Recursos" && learningObjArr.length === 0) || (tab === "Coleções" && collectionsArr.length === 0) || (tab === "Rede" && state.currentUser.id === '')} /> ) } @@ -238,18 +240,19 @@ export default function PublicUserPage(props) { </div> </Grid> - <Grid item xs={12}> - {tabValue === 0 && - <TabInicio id={id} user={userData} learningObjs={learningObjArr} collections={collectionsArr} />} - {tabValue === 1 && - <TabRecursos count={userData.learning_objects_count} learningObjs={learningObjArr} id={id} />} - {tabValue === 2 && - <TabColecoes count={userData.collections_count} collections={collectionsArr} - />} - {tabValue === 3 && - <TabRede id={id} username={userData.name} />} - - </Grid> + { + !loading && + <Grid item xs={12}> + {tabValue === 0 && + <TabInicio id={id} user={userData} learningObjs={learningObjArr} collections={collectionsArr} />} + {tabValue === 1 && + <TabRecursos count={userData.learning_objects_count} learningObjs={learningObjArr} id={id} />} + {tabValue === 2 && + <TabColecoes id={id} username={userData.name} />} + {tabValue === 3 && + <TabRede id={id} username={userData.name} />} + </Grid> + } </Grid> </BackgroundDiv> </React.Fragment> diff --git a/src/Pages/TabsHelp/TabManageAc.js b/src/Pages/TabsHelp/TabManageAc.js index 9aa293b3fac8e07bc551a59e97f6161618f4d4f9..a8280274999063167a3fe55b5eb46891df5e7e37 100644 --- a/src/Pages/TabsHelp/TabManageAc.js +++ b/src/Pages/TabsHelp/TabManageAc.js @@ -16,7 +16,7 @@ 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, { useState } from "react"; +import React, { useState, useEffect } from "react"; import styled from "styled-components"; import Tabs from "@material-ui/core/Tabs"; import Tab from "@material-ui/core/Tab"; @@ -49,6 +49,8 @@ export default function TabManageAc(props) { setTabValue(newValue); }; + useEffect(() => { window.scrollTo(0, 0) }, []) + return ( <div style={{ backgroundColor: "#f4f4f4" }}> <link @@ -73,19 +75,19 @@ export default function TabManageAc(props) { <img src={GerenciandoConta} alt="Gerenciando a conta" /> <span>{tabs[5]}</span> </div> - <TabsStyled orientation = "vertical" - variant = "scrollable" - value = {tabValue} - onChange = {handleChangeTab} - TabIndicatorProps = {{style:{display: "none"}}} + <TabsStyled orientation="vertical" + variant="scrollable" + value={tabValue} + onChange={handleChangeTab} + TabIndicatorProps={{ style: { display: "none" } }} > - <TabStyled label={tabs[0]}></TabStyled> - <TabStyled label={tabs[1]}></TabStyled> - <TabStyled label={tabs[2]}></TabStyled> - <TabStyled label={tabs[3]}></TabStyled> - <TabStyled label={tabs[4]}></TabStyled> + <TabStyled label={tabs[0]}></TabStyled> + <TabStyled label={tabs[1]}></TabStyled> + <TabStyled label={tabs[2]}></TabStyled> + <TabStyled label={tabs[3]}></TabStyled> + <TabStyled label={tabs[4]}></TabStyled> </TabsStyled> - <br/> + <br /> <div className="voltarInicio"> <a href="ajuda">VOLTAR AO ÃNICIO</a> </div> @@ -104,21 +106,21 @@ export default function TabManageAc(props) { </div> </Principal> - </Grid> - </Grid> + </Grid> + </Grid> + - <Grid style={{ marginBottom: "50px" }} container justify={"center"}> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardPublicando /> - </Grid> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardEncontrando /> - </Grid> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardParticipando /> - </Grid> - </Grid> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardPublicando /> + </Grid> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardEncontrando /> + </Grid> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardParticipando /> + </Grid> + </Grid> </Secao> </div> ); diff --git a/src/Pages/TabsHelp/TabNetPart.js b/src/Pages/TabsHelp/TabNetPart.js index 107a998b5eda35618bd647ec5a266c41bc86e871..c08e3ea1197c5a44ea33931e49c13079df6e57f5 100644 --- a/src/Pages/TabsHelp/TabNetPart.js +++ b/src/Pages/TabsHelp/TabNetPart.js @@ -16,7 +16,7 @@ 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, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import styled from 'styled-components'; import Tabs from '@material-ui/core/Tabs' import Tab from '@material-ui/core/Tab'; @@ -28,7 +28,7 @@ import What from '../../Components/HelpCenter/TabsNetPart/What' import CardEncontrando from '../../Components/HelpCenter/Cards/CardEncontrando'; import CardPublicando from '../../Components/HelpCenter/Cards/CardPublicando'; import CardGerenciando from '../../Components/HelpCenter/Cards/CardGerenciando'; -import { Link } from 'react-router-dom'; +import { Link } from 'react-router-dom'; @@ -36,25 +36,25 @@ import { Link } from 'react-router-dom'; -export default function TabNetPart (props) { - const tabs= [ +export default function TabNetPart(props) { + const tabs = [ 'Como comentar ou avaliar um recurso?', 'Que tipo de comentário posso fazer sobre o recurso?', 'Participando da Rede' ] - + const [tabValue, setTabValue] = useState(props.location.state === "undefined" ? 0 : props.location.state); const handleChangeTab = (e, newValue) => { setTabValue(newValue) -} + } + useEffect(() => { window.scrollTo(0, 0) }, []) + return ( + <div style={{ backgroundColor: "#f4f4f4" }}> + <link href="https://fonts.googleapis.com/css?family=Pompiere|Roboto:500,400&display=swap" rel="stylesheet" /> - return( - <div style={{backgroundColor:"#f4f4f4"}}> - <link href="https://fonts.googleapis.com/css?family=Pompiere|Roboto:500,400&display=swap" rel="stylesheet"/> - <Secao> <BreadCrumbsDiv> <StyledBreadCrumbs> @@ -64,7 +64,7 @@ export default function TabNetPart (props) { <Link to="ajuda" > Ajuda </Link> - + <span> {tabs[2]} </span> @@ -78,26 +78,26 @@ export default function TabNetPart (props) { <Principal> <Menu> <div className="fixo"> - <img src={ParticipandoRede} alt="Participando da Rede"/> + <img src={ParticipandoRede} alt="Participando da Rede" /> <span>{tabs[2]}</span> </div> - <TabsStyled orientation = "vertical" - variant = "scrollable" - value = {tabValue} - onChange = {handleChangeTab} - TabIndicatorProps = {{style:{display: "none"}}} + <TabsStyled orientation="vertical" + variant="scrollable" + value={tabValue} + onChange={handleChangeTab} + TabIndicatorProps={{ style: { display: "none" } }} > - <TabStyled label={tabs[0]}></TabStyled> - <TabStyled label={tabs[1]}></TabStyled> + <TabStyled label={tabs[0]}></TabStyled> + <TabStyled label={tabs[1]}></TabStyled> </TabsStyled> - <br/> + <br /> <div className="voltarInicio"> <a href="ajuda">VOLTAR AO ÃNICIO</a> </div> </Menu> - {tabValue === 0 && <How title={tabs[0]}/>} - {tabValue === 1 && <What title={tabs[1]}/>} + {tabValue === 0 && <How title={tabs[0]} />} + {tabValue === 1 && <What title={tabs[1]} />} <div className="resultadosProcura"> <span>Não era bem o que você procurava?</span> <div className="subtitulo"> @@ -106,21 +106,21 @@ export default function TabNetPart (props) { </div> </Principal> - </Grid> + </Grid> + </Grid> + + + <Grid style={{ paddingBottom: "50px" }} container justify={"center"}> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardPublicando /> + </Grid> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardEncontrando /> + </Grid> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardGerenciando /> + </Grid> </Grid> - - - <Grid style={{paddingBottom:"50px"}} container justify={"center"}> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardPublicando/> - </Grid> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardEncontrando/> - </Grid> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardGerenciando/> - </Grid> - </Grid> </Secao> diff --git a/src/Pages/TabsHelp/TabResourseFind.js b/src/Pages/TabsHelp/TabResourseFind.js index 8691d2822ea4f4f7100eb8a413f104a78db94788..3ea892563437144c7f79a1c482c16f475e21bde8 100644 --- a/src/Pages/TabsHelp/TabResourseFind.js +++ b/src/Pages/TabsHelp/TabResourseFind.js @@ -16,7 +16,7 @@ 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, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import styled from 'styled-components'; import Tabs from '@material-ui/core/Tabs' import Tab from '@material-ui/core/Tab'; @@ -29,7 +29,7 @@ import HowToFilter from '../../Components/HelpCenter/TabsResourseFind/HowToFilte import CardPublicando from '../../Components/HelpCenter/Cards/CardPublicando'; import CardParticipando from '../../Components/HelpCenter/Cards/CardParticipando'; import CardGerenciando from '../../Components/HelpCenter/Cards/CardGerenciando'; -import { Link } from 'react-router-dom'; +import { Link } from 'react-router-dom'; @@ -37,25 +37,26 @@ import { Link } from 'react-router-dom'; -export default function TabResourseFind (props) { - const tabs= [ +export default function TabResourseFind(props) { + const tabs = [ 'Como fazer uma busca?', 'Como filtrar os resultados?', 'Como os recursos são ranqueados?', 'Encontrando Recursos' ] - + const [tabValue, setTabValue] = useState(props.location.state === "undefined" ? 0 : props.location.state); const handleChangeTab = (e, newValue) => { setTabValue(newValue) -} + } + useEffect(() => { window.scrollTo(0, 0) }, []) + + return ( + <div style={{ backgroundColor: "#f4f4f4" }}> + <link href="https://fonts.googleapis.com/css?family=Pompiere|Roboto:500,400&display=swap" rel="stylesheet" /> - return( - <div style={{backgroundColor:"#f4f4f4"}}> - <link href="https://fonts.googleapis.com/css?family=Pompiere|Roboto:500,400&display=swap" rel="stylesheet"/> - <Secao> <BreadCrumbsDiv> <StyledBreadCrumbs> @@ -65,7 +66,7 @@ export default function TabResourseFind (props) { <Link to="ajuda" > Ajuda </Link> - + <span> {tabs[3]} </span> @@ -78,51 +79,51 @@ export default function TabResourseFind (props) { <Principal> <Menu> <div className="fixo"> - <img src={EncontrandoRecurso} alt="Encontrando Recursos"/> + <img src={EncontrandoRecurso} alt="Encontrando Recursos" /> <span>{tabs[3]}</span> </div> - <TabsStyled orientation = "vertical" - variant = "scrollable" - value = {tabValue} - onChange = {handleChangeTab} - TabIndicatorProps = {{style:{display: "none"}}} + <TabsStyled orientation="vertical" + variant="scrollable" + value={tabValue} + onChange={handleChangeTab} + TabIndicatorProps={{ style: { display: "none" } }} > - <TabStyled label={tabs[0]}></TabStyled> - <TabStyled label={tabs[1]}></TabStyled> - <TabStyled label={tabs[2]}></TabStyled> + <TabStyled label={tabs[0]}></TabStyled> + <TabStyled label={tabs[1]}></TabStyled> + <TabStyled label={tabs[2]}></TabStyled> </TabsStyled> - <br/> + <br /> <div className="voltarInicio"> <a href="ajuda">VOLTAR AO ÃNICIO</a> </div> </Menu> - {tabValue === 0 && <HowToDo title={tabs[0]}/>} - {tabValue === 1 && <HowToFilter title={tabs[1]}/>} - {tabValue === 2 && <HowToRank title={tabs[2]}/>} + {tabValue === 0 && <HowToDo title={tabs[0]} />} + {tabValue === 1 && <HowToFilter title={tabs[1]} />} + {tabValue === 2 && <HowToRank title={tabs[2]} />} <div className="resultadosProcura"> <span>Não era bem o que você procurava?</span> <div className="subtitulo"> <span>Você pode navegar pelos tópicos de ajuda ou entrar em <a href="contato">Contato</a>.</span> </div> </div> - + </Principal> - </Grid> - </Grid> - <Grid style={{paddingBottom:"50px"}} container justify={"center"}> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardPublicando/> </Grid> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardParticipando/> + </Grid> + <Grid style={{ paddingBottom: "50px" }} container justify={"center"}> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardPublicando /> </Grid> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardGerenciando/> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardParticipando /> + </Grid> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardGerenciando /> </Grid> </Grid> - + </Secao> </div> diff --git a/src/Pages/TabsHelp/TabResoursePub.js b/src/Pages/TabsHelp/TabResoursePub.js index 75dead021e85c99fc38053789a634f487d94e9dd..514362aa97d6a8f88a9653fb5dff007ccd51fb59 100644 --- a/src/Pages/TabsHelp/TabResoursePub.js +++ b/src/Pages/TabsHelp/TabResoursePub.js @@ -16,7 +16,7 @@ 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, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import styled from 'styled-components'; import Tabs from '@material-ui/core/Tabs' import Tab from '@material-ui/core/Tab'; @@ -29,40 +29,42 @@ import Which from '../../Components/HelpCenter/TabsResoursePub/Which' import CardEncontrando from '../../Components/HelpCenter/Cards/CardEncontrando'; import CardParticipando from '../../Components/HelpCenter/Cards/CardParticipando'; import CardGerenciando from '../../Components/HelpCenter/Cards/CardGerenciando'; -import { Link } from 'react-router-dom'; +import { Link } from 'react-router-dom'; -export default function TabResoursePub (props) { +export default function TabResoursePub(props) { console.log(props) - - const tabs= [ + + const tabs = [ 'Por que enviar um recurso?', 'Como publicar um recurso?', 'Quais tipos de recursos e formatos de arquivo a plataforma aceita?', 'Publicando Recursos' ] - + const [tabValue, setTabValue] = useState(props.location.state === "undefined" ? 0 : props.location.state); const handleChangeTab = (e, newValue) => { setTabValue(newValue) -} + } + + useEffect(() => { window.scrollTo(0, 0) }, []) + + return ( + <div style={{ backgroundColor: "#f4f4f4" }}> + <link href="https://fonts.googleapis.com/css?family=Pompiere|Roboto:500,400&display=swap" rel="stylesheet" /> - return( - <div style={{backgroundColor:"#f4f4f4"}}> - <link href="https://fonts.googleapis.com/css?family=Pompiere|Roboto:500,400&display=swap" rel="stylesheet"/> - <Secao> <BreadCrumbsDiv> <StyledBreadCrumbs> <Link to="/" > - Página Inicial + Página Inicial </Link> <Link to="ajuda" > Ajuda - </Link> + </Link> <span> - {tabs[3]} + {tabs[3]} </span> </StyledBreadCrumbs> @@ -72,28 +74,28 @@ export default function TabResoursePub (props) { <Principal> <Menu> <div className="fixo"> - <img src={PublicandoRecursos} alt="Publicando Recursos"/> + <img src={PublicandoRecursos} alt="Publicando Recursos" /> <span>{tabs[3]}</span> </div> - <TabsStyled orientation = "vertical" - variant = "scrollable" - value = {tabValue} - onChange = {handleChangeTab} - TabIndicatorProps = {{style:{display: "none"}}} + <TabsStyled orientation="vertical" + variant="scrollable" + value={tabValue} + onChange={handleChangeTab} + TabIndicatorProps={{ style: { display: "none" } }} > - <TabStyled label={tabs[0]}></TabStyled> - <TabStyled label={tabs[1]}></TabStyled> - <TabStyled label={tabs[2]}></TabStyled> + <TabStyled label={tabs[0]}></TabStyled> + <TabStyled label={tabs[1]}></TabStyled> + <TabStyled label={tabs[2]}></TabStyled> </TabsStyled> - <br/> + <br /> <div className="voltarInicio"> <a href="ajuda">VOLTAR AO ÃNICIO</a> </div> </Menu> - {tabValue === 0 && <Why title={tabs[0]}/>} - {tabValue === 1 && <How title={tabs[1]}/>} - {tabValue === 2 && <Which title={tabs[2]}/>} + {tabValue === 0 && <Why title={tabs[0]} />} + {tabValue === 1 && <How title={tabs[1]} />} + {tabValue === 2 && <Which title={tabs[2]} />} <div className="resultadosProcura"> <span>Não era bem o que você procurava?</span> <div className="subtitulo"> @@ -102,20 +104,20 @@ export default function TabResoursePub (props) { </div> </Principal> - </Grid> - </Grid> - <Grid style={{paddingBottom:"50px"}} container justify={"center"}> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardEncontrando/> </Grid> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardParticipando/> + </Grid> + <Grid style={{ paddingBottom: "50px" }} container justify={"center"}> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardEncontrando /> + </Grid> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardParticipando /> </Grid> - <Grid item xs={12} md={3} style={{margin:5}}> - <CardGerenciando/> + <Grid item xs={12} md={3} style={{ margin: 5 }}> + <CardGerenciando /> </Grid> - </Grid> + </Grid> </Secao> diff --git a/src/Pages/UserPage.js b/src/Pages/UserPage.js index 259522a052527be06359a1f29e9e98b5faa31b9c..2688500eeb48d71df1f3fc1469d744a41d4b71e6 100644 --- a/src/Pages/UserPage.js +++ b/src/Pages/UserPage.js @@ -144,10 +144,10 @@ export default function UserPage(props) { <HeaderContainer> <Cover id={id} /> <ProfileAvatar id={id} /> - {WIDTH <= 501 ? null : <UserInfo />} + {WIDTH <= 600 ? null : <UserInfo />} <EditProfileButton /> </HeaderContainer> - {WIDTH <= 501 ? ( + {WIDTH <= 600 ? ( <Grid style={{ marginTop: "4em" }} container @@ -210,7 +210,7 @@ export default function UserPage(props) { indicatorColor="primary" textColor="primary" variant="scrollable" - scrollButtons="auto" + scrollButtons="on" TabIndicatorProps={{ style: { background: "#00bcd4" }, }} diff --git a/src/Pages/UserTerms.js b/src/Pages/UserTerms.js index d7722bef70cdf003c64d9f8ae743c4f2337c99b1..e6c2e7cb6e9cb8f8583fd3b1d5c34a93c17332ac 100644 --- a/src/Pages/UserTerms.js +++ b/src/Pages/UserTerms.js @@ -15,7 +15,7 @@ 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, {Component} from 'react'; +import React, { useEffect } from 'react'; import SimpleExpansionPanels from '../Components/ExpansionPanels' import Grid from '@material-ui/core/Grid'; import Modal from '../Components/Modal' @@ -32,7 +32,7 @@ import Linha from "../img/termos/linha.svg"; -const BannerStyle=styled.div` +const BannerStyle = styled.div` width: 100%; background-image: url(${Banner1}); background-size: cover; @@ -186,99 +186,98 @@ const Secao4 = styled.div` ` -class UserTerms extends Component { - render() { +export default function UserTerms() { + useEffect(() => { + window.scrollTo(0, 0) + }, []) + return ( + <div style={{ color: "rgba(0,0,0,0.87" }} > - return ( - <div style={{color:"rgba(0,0,0,0.87"}} > + <BannerStyle> + <h2 style={{ width: "100%", textAlign: "center", marginTop: "0px", paddingTop: "6rem", marginBottom: "16px", fontSize: "52px", fontFamily: "'Pompiere', cursive", color: "#fff", fontWeight: "500" }}>TERMOS DE USO</h2> + <Modal /> + </BannerStyle> - <BannerStyle> - <h2 style={{width: "100%",textAlign: "center",marginTop:"0px", paddingTop:"6rem",marginBottom:"16px",fontSize:"52px",fontFamily: "'Pompiere', cursive",color:"#fff",fontWeight:"500"}}>TERMOS DE USO</h2> - <Modal/> - </BannerStyle> + <ImagemSeçao2> + <Grid container > + <Grid item xs={12} md={1}></Grid> + <Grid item xs={12} md={10}> + <div> + <h3><strong style={{ fontWeight: "700" }}>Plataforma Integrada de Recursos Educacionais Digitais,</strong><br />uma iniciativa do Ministério da Educação!</h3> - <ImagemSeçao2> - <Grid container > - <Grid item xs={12} md={1}></Grid> - <Grid item xs={12} md={10}> - <div> - <h3><strong style={{fontWeight:"700"}}>Plataforma Integrada de Recursos Educacionais Digitais,</strong><br/>uma iniciativa do Ministério da Educação!</h3> - - <p>A <strong>Plataforma Integrada de RED do MEC</strong> é parte do processo de implementação do Compromisso 6 do <AColorido href="http://www.governoaberto.cgu.gov.br/noticias/2017/3o-plano-de-acao-nacional-na-parceria-para-governo-aberto" target="_blank">3º Plano de Ação da Parceria Governo Aberto</AColorido> (OGP-Brasil), que tem por objetivo “incorporar na polÃtica educacional o potencial da cultura digital, de modo a fomentar a autonomia para uso, reuso e adaptação de recursos educacionais digitais, valorizando a pluralidade e a diversidade da educação brasileiraâ€. + <p>A <strong>Plataforma Integrada de RED do MEC</strong> é parte do processo de implementação do Compromisso 6 do <AColorido href="http://www.governoaberto.cgu.gov.br/noticias/2017/3o-plano-de-acao-nacional-na-parceria-para-governo-aberto" target="_blank">3º Plano de Ação da Parceria Governo Aberto</AColorido> (OGP-Brasil), que tem por objetivo “incorporar na polÃtica educacional o potencial da cultura digital, de modo a fomentar a autonomia para uso, reuso e adaptação de recursos educacionais digitais, valorizando a pluralidade e a diversidade da educação brasileiraâ€. </p> - <p>Seguindo o compromisso, a <strong>Plataforma Integrada de RED do MEC</strong> visa fortalecer a distribuição de recursos educacionais digitais para o ensino básico brasileiro. Há preferência pela disponibilização de Recursos Educacionais Abertos (REA), ou seja, recursos que “se situem no domiÌnio puÌblico ou que tenham sido divulgados sob licença aberta que permita acesso, uso, adaptação e redistribuição gratuita por terceiros, mediante nenhuma restrição ou poucas restrições.†<AColorido href="http://www.unesco.org/new/fileadmin/MULTIMEDIA/HQ/CI/CI/pdf/Events/Portuguese_Paris_OER_Declaration.pdf" target="_blank">(Declaração REA de Paris, 2012)</AColorido>. + <p>Seguindo o compromisso, a <strong>Plataforma Integrada de RED do MEC</strong> visa fortalecer a distribuição de recursos educacionais digitais para o ensino básico brasileiro. Há preferência pela disponibilização de Recursos Educacionais Abertos (REA), ou seja, recursos que “se situem no domiÌnio puÌblico ou que tenham sido divulgados sob licença aberta que permita acesso, uso, adaptação e redistribuição gratuita por terceiros, mediante nenhuma restrição ou poucas restrições.†<AColorido href="http://www.unesco.org/new/fileadmin/MULTIMEDIA/HQ/CI/CI/pdf/Events/Portuguese_Paris_OER_Declaration.pdf" target="_blank">(Declaração REA de Paris, 2012)</AColorido>. </p> - </div> - </Grid> - <Grid item xs={12} md={1}></Grid> - </Grid> - </ImagemSeçao2> - - <Secao3 > - <Grid container > - <h3>Para melhor compreensão, podemos dividir os recursos em dois tipos:</h3> - <Grid item xs={12} md={1} ></Grid> - <Grid item xs={12} md={5} > - <div class="caixa aberto"> - <div class ="texto"> - <span>Abertos</span> - <p>De acordo com a Declaração de Paris, são recursos que, no mÃnimo, têm uma licença de uso mais flexÃvel, que garante livre redistribuição. Adicionalmente, um recurso aberto deve utilizar um formato aberto, um formato de arquivo que permite a fácil edição por terceiros. Nenhum controle sobre o acesso (como cadastro e senha) deve existir para acesso a recursos abertos. Em sua maioria, são recursos gratuitos.</p> - </div> - </div> - </Grid> - - <Grid item xs={12} md={5}> - <div class="caixa fechado"> - <div class ="texto"> - <span>Fechados</span> - <p>São recursos que criam restrições no seu acesso, uso ou reuso. Como exemplo, podemos mencionar recursos que só são acessÃveis mediante cadastro ou que têm licenças restritivas (como “todos os direitos reservadosâ€, o sÃmbolo ©). Podem ser gratuitos ou pagos.</p> - </div> - </div> - </Grid> - <Grid item xs={12} md={1} ></Grid> - </Grid> - </Secao3> - - - - - <Grid container > - <Grid item xs={12} md={1}></Grid> - <Grid item xs={12} md={10}> - <Secao4> - <div class="texto" style={{paddingTop:"70px"}}> - <p>O <a href="http://www.planalto.gov.br/ccivil_03/_ato2011-2014/2014/lei/l13005.htm" rel="noreferrer" target="_blank">Plano Nacional de Educação</a> (2014-2024) enfatiza nas metas 5 e 7 a importância dos recursos educacionais abertos para fomentar a qualidade da educação baÌsica. A <a href="http://portal.mec.gov.br/index.php?option=com_docman&view=download&alias=35541-res-cne-ces-001-14032016-pdf&category_slug=marco-2016-pdf&Itemid=30192" rel="noreferrer" target="_blank">Resolução CNE/CES nº 1</a>, de 11 de março de 2016, também destaca a importância dos recursos educacionais abertos para as instituições de educação superior e para as atividades de educação a distância.</p> - </div> - <div class="titulo"> - <h3>TERMOS DE USO</h3> - <p>InÃcio da vigência: agosto de 2017</p> - </div> - <div class="texto" style={{paddingBottom:"40px"}}> - <p>Aqui estão os “Termos de Uso†da <strong>Plataforma Integrada de RED do MEC</strong>, isto é, as regras de funcionamento da Plataforma e seus serviços, e o que se espera de seus usuários. Por “usuárioâ€, entende-se qualquer pessoa que acesse o domÃnio portal.mec.gov.br, tanto para pesquisa (acesso) como para a inclusão de dados e informações (participação) mediante cadastro.</p> - <p>Fazem parte dos Termos de Uso as polÃticas de responsabilidade, de privacidade e confidencialidade, a licença de uso do conteúdo e as informações sobre como reportar violações.</p> - <p>Ao utilizar a <strong>Plataforma Integrada de RED do MEC</strong>, o usuário aceita todas as condições aqui estabelecidas. O uso da <strong>Plataforma Integrada de RED do MEC</strong> implica aceite das condições aqui elencadas.</p> - <p>Por “serviçoâ€, entende-se qualquer funcionalidade ou ferramenta que permita a interatividade com o usuário, como, por exemplo, usuário subir um recurso, postar um comentário, criar uma coleção ou enviar uma mensagem.</p> - <p>A aceitação destes "Termos de Uso" é indispensável à utilização da <strong>Plataforma Integrada de RED do MEC</strong>. Todos os usuários deverão ler, certificar-se de tê-los entendido e aceitar todas as condições neles estabelecidas. Dessa forma, deve ficar claro que a utilização desta "<strong>Plataforma Integrada de RED do MEC</strong>" implica aceitação completa deste documento intitulado Termos de Uso. Caso tenha dúvidas sobre os termos, utilize o formulário disponÃvel em “Contato†para saná-las.</p> - </div> - </Secao4> - </Grid> - <Grid item xs={12} md={1}></Grid> + </div> + </Grid> + <Grid item xs={12} md={1}></Grid> + </Grid> + </ImagemSeçao2> + + <Secao3 > + <Grid container > + <h3>Para melhor compreensão, podemos dividir os recursos em dois tipos:</h3> + <Grid item xs={12} md={1} ></Grid> + <Grid item xs={12} md={5} > + <div class="caixa aberto"> + <div class="texto"> + <span>Abertos</span> + <p>De acordo com a Declaração de Paris, são recursos que, no mÃnimo, têm uma licença de uso mais flexÃvel, que garante livre redistribuição. Adicionalmente, um recurso aberto deve utilizar um formato aberto, um formato de arquivo que permite a fácil edição por terceiros. Nenhum controle sobre o acesso (como cadastro e senha) deve existir para acesso a recursos abertos. Em sua maioria, são recursos gratuitos.</p> + </div> + </div> </Grid> - - <Grid container > - <Grid item xs={12} md={1}></Grid> - <Grid item xs={12} md={10}> - <div style={{ marginBottom:"50px",paddingTop: "20px"}}> - <SimpleExpansionPanels/> + <Grid item xs={12} md={5}> + <div class="caixa fechado"> + <div class="texto"> + <span>Fechados</span> + <p>São recursos que criam restrições no seu acesso, uso ou reuso. Como exemplo, podemos mencionar recursos que só são acessÃveis mediante cadastro ou que têm licenças restritivas (como “todos os direitos reservadosâ€, o sÃmbolo ©). Podem ser gratuitos ou pagos.</p> </div> - </Grid> - <Grid item xs={12} md={1}></Grid> - </Grid> - </div> - ); - } - } + </div> + </Grid> + <Grid item xs={12} md={1} ></Grid> + </Grid> + </Secao3> + + + + + <Grid container > + <Grid item xs={12} md={1}></Grid> + <Grid item xs={12} md={10}> + <Secao4> + <div class="texto" style={{ paddingTop: "70px" }}> + <p>O <a href="http://www.planalto.gov.br/ccivil_03/_ato2011-2014/2014/lei/l13005.htm" rel="noreferrer" target="_blank">Plano Nacional de Educação</a> (2014-2024) enfatiza nas metas 5 e 7 a importância dos recursos educacionais abertos para fomentar a qualidade da educação baÌsica. A <a href="http://portal.mec.gov.br/index.php?option=com_docman&view=download&alias=35541-res-cne-ces-001-14032016-pdf&category_slug=marco-2016-pdf&Itemid=30192" rel="noreferrer" target="_blank">Resolução CNE/CES nº 1</a>, de 11 de março de 2016, também destaca a importância dos recursos educacionais abertos para as instituições de educação superior e para as atividades de educação a distância.</p> + </div> + <div class="titulo"> + <h3>TERMOS DE USO</h3> + <p>InÃcio da vigência: agosto de 2017</p> + </div> + <div class="texto" style={{ paddingBottom: "40px" }}> + <p>Aqui estão os “Termos de Uso†da <strong>Plataforma Integrada de RED do MEC</strong>, isto é, as regras de funcionamento da Plataforma e seus serviços, e o que se espera de seus usuários. Por “usuárioâ€, entende-se qualquer pessoa que acesse o domÃnio portal.mec.gov.br, tanto para pesquisa (acesso) como para a inclusão de dados e informações (participação) mediante cadastro.</p> + <p>Fazem parte dos Termos de Uso as polÃticas de responsabilidade, de privacidade e confidencialidade, a licença de uso do conteúdo e as informações sobre como reportar violações.</p> + <p>Ao utilizar a <strong>Plataforma Integrada de RED do MEC</strong>, o usuário aceita todas as condições aqui estabelecidas. O uso da <strong>Plataforma Integrada de RED do MEC</strong> implica aceite das condições aqui elencadas.</p> + <p>Por “serviçoâ€, entende-se qualquer funcionalidade ou ferramenta que permita a interatividade com o usuário, como, por exemplo, usuário subir um recurso, postar um comentário, criar uma coleção ou enviar uma mensagem.</p> + <p>A aceitação destes "Termos de Uso" é indispensável à utilização da <strong>Plataforma Integrada de RED do MEC</strong>. Todos os usuários deverão ler, certificar-se de tê-los entendido e aceitar todas as condições neles estabelecidas. Dessa forma, deve ficar claro que a utilização desta "<strong>Plataforma Integrada de RED do MEC</strong>" implica aceitação completa deste documento intitulado Termos de Uso. Caso tenha dúvidas sobre os termos, utilize o formulário disponÃvel em “Contato†para saná-las.</p> + </div> + </Secao4> + </Grid> + <Grid item xs={12} md={1}></Grid> + </Grid> + + + <Grid container > + <Grid item xs={12} md={1}></Grid> + <Grid item xs={12} md={10}> + <div style={{ marginBottom: "50px", paddingTop: "20px" }}> + <SimpleExpansionPanels /> + </div> + </Grid> + <Grid item xs={12} md={1}></Grid> + </Grid> + </div> + ); +} -export default UserTerms; diff --git a/src/env.js b/src/env.js index 82bf229b11fe78f3cb5ff8a58d096eec156cedf2..b7359157e1c0e9d260976bbe2b2545a2e0ca51b0 100644 --- a/src/env.js +++ b/src/env.js @@ -17,7 +17,7 @@ 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/>.*/ -var apiDomain = 'https://api.portalmectest.c3sl.ufpr.br', +var apiDomain = 'https://api.portalmec.c3sl.ufpr.br', apiVersion = 'v1', apiUrl = apiDomain + '/' + apiVersion;