diff --git a/src/Admin/Pages/Pages/SubPages/Activity.js b/src/Admin/Pages/Pages/SubPages/Activity.js new file mode 100644 index 0000000000000000000000000000000000000000..a4d5149e9d274af05134fffdb7e2192310dd556c --- /dev/null +++ b/src/Admin/Pages/Pages/SubPages/Activity.js @@ -0,0 +1,408 @@ +/*Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana + +This file is part of Plataforma Integrada MEC. + +Plataforma Integrada MEC is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Plataforma Integrada MEC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with Plataforma Integrada MEC. If not, see <http://www.gnu.org/licenses/>.*/ + +import React, { useEffect, useState } from "react"; +//imports from local files +import TableData from "../../../Components/Components/Table"; +import SnackBar from "../../../../Components/SnackbarComponent"; +import EditLanguage from "../../../Components/Components/Inputs/EditLanguage"; +import { Url } from "../../../Filters"; +import { GetFullList } from "../../../Services"; +//imports from material ui +import { withStyles } from "@material-ui/core/styles"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import 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"; + +let currPage = 0; +let viewItem = {}; + +const StyledTableCell = withStyles((theme) => ({ + head: { + backgroundColor: theme.palette.common.black, + color: theme.palette.common.white, + }, + body: { + fontSize: 14, + }, +}))(TableCell); + +const StyledTableRow = withStyles((theme) => ({ + root: { + "&:nth-of-type(odd)": { + backgroundColor: theme.palette.action.hover, + }, + }, +}))(TableRow); + +const Activity = () => { + const ADD_ONE_LENGHT = [""]; + const TOP_LABELS = [ + "CRIADO EM", + "DONO(A)", + "ATIVIDADE", + "PRIVACIDADE", + "VISUALIZAR", + ]; //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 [showDataActivity, setShowDataActivity] = useState(false); + 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 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); + const headers = { + Accept: "application/json", + "Content-Type": "application/json; charset=utf-8", + "access-token": sessionStorage.getItem("@portalmec/accessToken"), + client: sessionStorage.getItem("@portalmec/clientToken"), + uid: sessionStorage.getItem("@portalmec/uid"), + 'If-None-Match': null + }; + + GetFullList(api, headers).then((res) => { + if (res.state) { + const arrData = [...res.data]; + if (arrData.length === 0) { + HandleSnack( + "Não há mais dados para serem carregados", + true, + "warning", + "#FFC125" + ); + } else { + const arrItems = [...items]; + arrItems.pop(); //Deleting the last position, that was used to display the button of load more items + const arrResult = arrItems.concat(arrData); + setItems(arrResult.concat(ADD_ONE_LENGHT)); + } + } else { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + } + setIsLoadingMoreItems(false); + }); + }; + + // handle update list data + const UpdateHandler = async (api) => { + setIsUpdating(true); + const headers = { + Accept: "application/json", + "Content-Type": "application/json; charset=utf-8", + "access-token": sessionStorage.getItem("@portalmec/accessToken"), + client: sessionStorage.getItem("@portalmec/clientToken"), + uid: sessionStorage.getItem("@portalmec/uid"), + 'If-None-Match': null + }; + + GetFullList(api, headers).then((res) => { + console.log(res); + if (res.state) { + HandleSnack( + "A lista de dados foi atualizada", + true, + "success", + "#228B22" + ); + const arrData = [...res.data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + } else { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + } + setIsUpdating(false); + }); + }; + + const HandleButtonViewClicked = (i) => { + viewItem = { ...items[i] }; + setShowDataActivity(true); + }; + + const handleChange = (e) => { + const value = e.target.value; + console.log(value); + currPage = 0; + setOption(value); + + const headers = { + Accept: "application/json", + "Content-Type": "application/json; charset=utf-8", + "access-token": sessionStorage.getItem("@portalmec/accessToken"), + client: sessionStorage.getItem("@portalmec/clientToken"), + uid: sessionStorage.getItem("@portalmec/uid"), + }; + + GetFullList( + Url("activities", `"privacy" : "${value}"`, `${currPage}`, "DESC"), + headers + ).then((res) => { + if (res.state) { + const arrData = [...res.data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); + setIsLoaded(true); + } else { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + setIsLoaded(true); + } + }); + }; + + //getting data from server + useEffect(() => { + const headers = { + Accept: "application/json", + "Content-Type": "application/json; charset=utf-8", + "access-token": sessionStorage.getItem("@portalmec/accessToken"), + client: sessionStorage.getItem("@portalmec/clientToken"), + uid: sessionStorage.getItem("@portalmec/uid"), + }; + + GetFullList(Url("activities", "", `${currPage}`, "DESC"), headers).then( + (res) => { + if (res.state) { + const arrData = [...res.data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + setIsLoaded(true); + setError(false); + } else { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + setIsLoaded(true); + setError(true); + } + } + ); + }, []); + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <div>Loading...</div>; + } else { + return showDataActivity ? ( + <EditLanguage + editInfo={viewItem} + UpdateList={UpdateHandler} + BackToList={() => setShowDataActivity(false)} + /> + ) : ( + <> + <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">Atividades</Typography> + </Grid> + <Grid + item + xs={6} + alignItems="center" + justify="center" + direction="row" + > + <Grid container justify="flex-end" spacing={3}> + <Grid item> + <Button + variant="contained" + color="secondary" + disabled={isUpdating} + onClick={() => { + currPage = 0; + UpdateHandler( + Url("activities", "", `${currPage}`, "DESC") + ); + }} + startIcon={<UpdateRoundedIcon />} + > + {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} + </Button> + </Grid> + <Grid item> + <Button + variant="contained" + color="secondary" + onClick={() => { + currPage = 0; + UpdateHandler( + Url("activities", "", `${currPage}`, "DESC") + ); + setShowFilter(!showFilter); + }} + startIcon={<FilterListRoundedIcon />} + > + Filtrar + </Button> + </Grid> + </Grid> + </Grid> + </Grid> + + {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} + </Paper> + + <div style={{ height: "2em" }}></div> + + <TableData top={TOP_LABELS}> + <TableBody> + {items.map((row, index) => + index === items.length - 1 ? ( + <div style={{ padding: "1em" }}> + {/* Button to load more data */} + <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> + </div> + ) : ( + <StyledTableRow key={index}> + <StyledTableCell component="th" scope="row"> + {row.created_at} + </StyledTableCell> + <StyledTableCell align="right"> + { + row.owner.name === null ? '' : row.owner.name + } + </StyledTableCell> + <StyledTableCell align="right"> + {row.activity} + </StyledTableCell> + <StyledTableCell align="right">{row.privacy}</StyledTableCell> + <StyledTableCell align="right"> + <IconButton + onClick={() => { + currPage = 0; + HandleButtonViewClicked(index); + }} + > + <VisibilityIcon style={{ fill: "#00bcd4" }} /> + </IconButton> + </StyledTableCell> + </StyledTableRow> + ) + )} + </TableBody> + </TableData> + </> + ); + } +}; +export default Activity;