diff --git a/src/Components/AreasSubPagesFunction.js b/src/Components/AreasSubPagesFunction.js index dda8cf98d425f8b15121dd020f070b39291edfb3..5a2aa3b94c81a92f99c949b5474703a724519d8d 100644 --- a/src/Components/AreasSubPagesFunction.js +++ b/src/Components/AreasSubPagesFunction.js @@ -187,7 +187,7 @@ function ReqCollections(props) { function TabRecurso() { const text = "Nesta área, você tem acesso a Recursos Educacionais Digitais, isto é, a vídeos, animações e a outros recursos destinados à educação. São Recursos de portais parceiros do MEC e de professores que, como você, atuam na Educação Básica!" - const [currOrder, setCurrOrder] = useState("Mais Recentes"); + const [currOrder, setCurrOrder] = useState("Mais Relevante"); const [currValue, setCurrValue] = useState("score"); const [ordenar] = useState([ { label: "Mais Estrelas", value: "review_average" }, @@ -284,8 +284,8 @@ function TabRecurso() { function TabColecoes() { const text = "Nesta área, você tem acesso às coleções criadas e organizadas pelos usuários da plataforma. É mais uma possibilidade de buscar recursos educacionais para sua aula!" - const [currOrder, setCurrOrder] = useState("Mais Recentes"); - const [currValue, setCurrValue] = useState("publicationdesc"); + const [currOrder, setCurrOrder] = useState("Mais Relevante"); + const [currValue, setCurrValue] = useState("score"); const [ordenar] = useState([ { label: "Mais Estrelas", value: "review_average" }, { label: "Mais Relevante", value: "score" }, diff --git a/src/Components/CollectionCardFunction.js b/src/Components/CollectionCardFunction.js index ced5cb77028a259d4aa39136ff48f18f696ec114..85f59e03ce1471a18330239ee2480e0ef1b41d99 100644 --- a/src/Components/CollectionCardFunction.js +++ b/src/Components/CollectionCardFunction.js @@ -242,8 +242,8 @@ export default function CollectionCardFunction(props) { <Footer> <Type> <FolderIcon /> - <span style={{ fontWeight: "bold" }}>{props.collections.length} </span> - <span>{props.collections.length !== 1 ? "Recursos" : "Recurso"}</span> + <span style={{ fontWeight: "bold" }}>{props.collections ? props.collections.length : 0} </span> + <span>{props.collections ? props.collections.length !== 1 ? "Recursos" : "Recurso" : 0}</span> </Type> <LikeCounter> <span>{likesCount}</span> diff --git a/src/Components/ModalAvaliarRecurso.js b/src/Components/ModalAvaliarRecurso.js index 8604461a878c3b4e781d23ef9bc6f779bea276b6..71e0a37d95053eb414256d80cf4434448520b0ef 100644 --- a/src/Components/ModalAvaliarRecurso.js +++ b/src/Components/ModalAvaliarRecurso.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 { Button } from '@material-ui/core'; import Modal from '@material-ui/core/Modal'; import Backdrop from '@material-ui/core/Backdrop'; @@ -31,42 +31,31 @@ import CloseModalButton from './CloseModalButton' import Snackbar from '@material-ui/core/Snackbar'; import TextField from '@material-ui/core/TextField'; import { withStyles } from '@material-ui/core/styles'; +import { getRequest } from './HelperFunctions/getAxiosConfig' +import LoadingSpinner from '../Components/LoadingSpinner' const StyledRadio = withStyles({ - root: { - color: '#666', - '&$checked': { - color: '#ff7f00', + root: { + color: '#666', + '&$checked': { + color: '#ff7f00', + }, }, - }, - checked: {}, + checked: {}, })((props) => <Radio color="default" {...props} />); -export default function ModalAvaliarRecurso (props) { +export default function ModalAvaliarRecurso(props) { - const options = [ - { - text : "O recurso apresenta conteúdo de cunho político-partidário? (Ex: o conteúdo expressa qualquer forma de manifestação que se caracterize como propaganda política)?", id : 1 - }, - { - text : "O recurso apresenta conteúdo ofensivo? (Ex: material pornográfico e/ou que invada a privacidade de terceiros, viole os Direitos Humanos ou seja ilegal, ofensivo, e que incite a violência)?", id : 2 - }, - { - text : "O recurso apresenta algum tipo de propaganda ou marca? (Ex: o conteúdo tem cunho comercial)?", id : 3 - }, - { - text : "Outro motivo para rejeição (falta de descrição, autor, objeto, erros)? Indicar na justificativa se for o caso?", id : 4 - } - ] + const [options, setOptions] = useState([]) - const [avaliacao, setAvaliacao] = useState([null,null,null,null]) + const [avaliacao, setAvaliacao] = useState([null, null, null, null]) const handleRadios = (event, id) => { let newValue = avaliacao newValue[id - 1] = (event.target.value === "Sim" ? true : false) setAvaliacao(newValue) - if(avaliacao.indexOf(null) === -1) { + if (avaliacao.indexOf(null) === -1) { toggleDisableButton(false) } } @@ -90,100 +79,129 @@ export default function ModalAvaliarRecurso (props) { const handleAvaliar = () => { let criteria = options avaliacao.map((criterium, index) => - criteria[index]['accepted'] = !criterium + criteria[index]['accepted'] = !criterium ) props.confirm(criteria, justificativa, avaliacao.filter((item) => item === true).length > 0 ? false : true) returnToDefault() } const returnToDefault = () => { - setAvaliacao([null,null,null,null]) + setAvaliacao([null, null, null, null]) setJustificativa('') toggleDisableButton(true) } + useEffect(() => { + getRequest( + "/questions", + (data, header) => { + const cpyOption = [] + const cpyAvaliacao = [] + for (let index = 0; index < data.length; index++) { + const option = data[index]; + cpyOption.push({ + text: option.description, + id: option.id + }) + cpyAvaliacao.push(null) + } + setOptions(cpyOption) + setAvaliacao(cpyAvaliacao) + }, + (error) => { + + } + ) + }, []) + return ( <> - <Snackbar open={snackbarCancelar} autoHideDuration={1000} onClose={toggleSnackbarCancelar} - anchorOrigin = {{ vertical:'top', horizontal:'right' }} - message="Você cancelou a avaliação deste recurso." + <Snackbar open={snackbarCancelar} autoHideDuration={1000} onClose={toggleSnackbarCancelar} + anchorOrigin={{ vertical: 'top', horizontal: 'right' }} + message="Você cancelou a avaliação deste recurso." /> - <StyledModal - aria-labelledby="transition-modal-title" - aria-describedby="transition-modal-description" - open={props.open} - centered="true" - onClose={props.handleClose} - closeAfterTransition - BackdropComponent={Backdrop} - BackdropProps={{ - timeout: 500, - }} - > - <Fade in={props.open}> - <Container> - <Header> - <h2>Você está avaliando o recurso - <span style={{fontWeight : "bolder"}}> {props.title}</span> - </h2> - <CloseModalButton handleClose={props.handleClose}/> - </Header> - - <Content> - <Grid container> - <Grid item xs={12}> - <p>Esse recurso está em conformidade com os critérios? Marque as opções e justifique aquela(s) que não estiverem em conformidade.</p> - </Grid> - - <FormControl component="fieldset" style={{display:"BlockRuby"}} fullWidth={true}> - { - options.map( (option) => - <Grid item xs={12} key={option.id} style={{paddingTop : "10px"}}> + { + options ? + <StyledModal + aria-labelledby="transition-modal-title" + aria-describedby="transition-modal-description" + open={props.open} + centered="true" + onClose={props.handleClose} + closeAfterTransition + BackdropComponent={Backdrop} + BackdropProps={{ + timeout: 500, + }} + > + + <Fade in={props.open}> + <Container> + <Header> + <h2>Você está avaliando o recurso + <span style={{ fontWeight: "bolder" }}> {props.title}</span> + </h2> + <CloseModalButton handleClose={props.handleClose} /> + </Header> + + <Content> <Grid container> - <Grid item xs={10}> - <div style={{height : "100%", display : "flex", alignItems : "center"}}> - <p>{option.text}</p> - </div> - </Grid> - <Grid item xs={2}> - <RadioGroup row onChange={(e) => {handleRadios(e, option.id)}}> - <FormControlLabel value={"Sim"} control={<StyledRadio/>} label="Sim"/> - <FormControlLabel value={"Não"} control={<StyledRadio/>} label="Não"/> - </RadioGroup> - </Grid> + <Grid item xs={12}> + <p>Esse recurso está em conformidade com os critérios? Marque as opções e justifique aquela(s) que não estiverem em conformidade.</p> + </Grid> + + <FormControl component="fieldset" style={{ display: "BlockRuby" }} fullWidth={true}> + { + options.map((option) => + <Grid item xs={12} key={option.id} style={{ paddingTop: "10px" }}> + <Grid container> + <Grid item xs={10}> + <div style={{ height: "100%", display: "flex", alignItems: "center" }}> + <p>{option.text}</p> + </div> + </Grid> + <Grid item xs={2}> + <RadioGroup row onChange={(e) => { handleRadios(e, option.id) }}> + <FormControlLabel value={"Sim"} control={<StyledRadio />} label="Sim" /> + <FormControlLabel value={"Não"} control={<StyledRadio />} label="Não" /> + </RadioGroup> + </Grid> + </Grid> + </Grid> + ) + } + </FormControl> + + <Grid item xs={12}> + <FormControl style={{ width: "100%", height: "100px" }}> + <StyledTextField + id={"title-form"} + label={"Justificativa (opcional)"} + type={"text"} + value={justificativa} + onChange={e => { handleChangeJustificativa(e) }} + multiline + fullWidth + /> + </FormControl> + </Grid> + + <Grid item xs={12}> + <ButtonsDiv> + <ButtonEnviarAvaliar disabled={buttonDisabled} onClick={() => { handleAvaliar() }}>ENVIAR AVALIAÇÂO</ButtonEnviarAvaliar> + <GreyButton onClick={() => { handleCancel() }}>CANCELAR</GreyButton> + </ButtonsDiv> + </Grid> </Grid> - </Grid> - ) - } - </FormControl> - - <Grid item xs={12}> - <FormControl style={{width : "100%", height : "100px"}}> - <StyledTextField - id = {"title-form"} - label={"Justificativa (opcional)"} - type = {"text"} - value = {justificativa} - onChange = {e => {handleChangeJustificativa(e)}} - multiline - fullWidth - /> - </FormControl> - </Grid> - - <Grid item xs={12}> - <ButtonsDiv> - <ButtonEnviarAvaliar disabled={buttonDisabled} onClick={() => {handleAvaliar()}}>ENVIAR AVALIAÇÂO</ButtonEnviarAvaliar> - <GreyButton onClick={ () => {handleCancel()}}>CANCELAR</GreyButton> - </ButtonsDiv> - </Grid> - </Grid> - </Content> - - </Container> - </Fade> - </StyledModal> - </> + </Content> + + </Container> + </Fade> + </StyledModal> + : + <LoadingSpinner /> + } + </> ) } diff --git a/src/Components/ModalConfirmarCuradoria.js b/src/Components/ModalConfirmarCuradoria.js index 4687b1876be5b3ae5376901a97eb2e00aca3df66..046106be576a7eea000031277db1c74a2f74df55 100644 --- a/src/Components/ModalConfirmarCuradoria.js +++ b/src/Components/ModalConfirmarCuradoria.js @@ -23,9 +23,9 @@ import Backdrop from '@material-ui/core/Backdrop'; import Fade from '@material-ui/core/Fade'; import styled from 'styled-components' import CloseModalButton from './CloseModalButton' -import {postRequest} from './HelperFunctions/getAxiosConfig' +import { postRequest } from './HelperFunctions/getAxiosConfig' -export default function ModalConfirmarCuradoriaOpen (props) { +export default function ModalConfirmarCuradoriaOpen(props) { const handleCancel = () => { props.handleClose() @@ -35,24 +35,31 @@ export default function ModalConfirmarCuradoriaOpen (props) { const transformReportCriteria = (criteria) => { let newArr = [] criteria.map((criterium) => - newArr.push({"question_id" : criterium.id, "accepted" : criterium.accepted}) + newArr.push({ "question_id": criterium.id, "accepted": criterium.accepted }) ) return newArr } - function handleSuccess (data) { + function handleSuccess(data) { props.finalizeCuratorshipFlow() } const handleConfirmation = () => { const url = `/submissions/${props.recursoId}/answer` let payload = { - "submission" : { - "justification" : props.justificativa, - "answers" : transformReportCriteria(props.reportCriteria) + "submission": { + "justification": props.justificativa, + "answers": transformReportCriteria(props.reportCriteria) } } - postRequest(url, payload, handleSuccess, (error) => {console.log(error)}) + postRequest( + url, + payload, + handleSuccess, + (error) => { + props.handleErrorAprove() + } + ) } return ( @@ -71,44 +78,44 @@ export default function ModalConfirmarCuradoriaOpen (props) { <Fade in={props.open}> <Container recusado={!props.aceito}> <Header> - <span style={{width:"32px"}}/> + <span style={{ width: "32px" }} /> <h2>Recurso a ser {props.aceito ? 'aprovado' : 'recusado'}</h2> - <CloseModalButton handleClose={props.handleClose}/> + <CloseModalButton handleClose={props.handleClose} /> </Header> <Content> { props.aceito ? - ( - <p>Este recurso será publicado na plataforma. Você confirma essa avaliação? + ( + <p>Este recurso será publicado na plataforma. Você confirma essa avaliação? + </p> + ) + : + ( + <> + <p>Agradecemos a sua contribuição. Você avaliou que o recurso não está em conformidade com o(s) seguinte(s) critério(s): </p> - ) - : - ( - <> - <p>Agradecemos a sua contribuição. Você avaliou que o recurso não está em conformidade com o(s) seguinte(s) critério(s): - </p> - { - props.reportCriteria.filter((criterium) => criterium.accepted === false).map( (criterium) => - <p key={criterium.id} className="reason-offensive">{criterium.text}</p> - ) - } - <p>Você confirma essa avaliação? Ao confirmar, o recurso não será publicado na plataforma.</p> - </> - ) + { + props.reportCriteria.filter((criterium) => criterium.accepted === false).map((criterium) => + <p key={criterium.id} className="reason-offensive">{criterium.text}</p> + ) + } + <p>Você confirma essa avaliação? Ao confirmar, o recurso não será publicado na plataforma.</p> + </> + ) } - <ButtonsDiv> - { - props.aceito ? + <ButtonsDiv> + { + props.aceito ? ( - <ButtonEnviarAvaliar onClick={() => {handleConfirmation()}}>SIM, CONFIRMAR</ButtonEnviarAvaliar> + <ButtonEnviarAvaliar onClick={() => { handleConfirmation() }}>SIM, CONFIRMAR</ButtonEnviarAvaliar> ) : ( - <ButtonEnviarAvaliar onClick={() => {handleConfirmation()}}>SIM, CONFIRMAR</ButtonEnviarAvaliar> + <ButtonEnviarAvaliar onClick={() => { handleConfirmation() }}>SIM, CONFIRMAR</ButtonEnviarAvaliar> ) - } - <GreyButton onClick={handleCancel}>NÃO, ALTERAR AVALIAÇÃO</GreyButton> - </ButtonsDiv> + } + <GreyButton onClick={handleCancel}>NÃO, ALTERAR AVALIAÇÃO</GreyButton> + </ButtonsDiv> </Content> </Container> </Fade> diff --git a/src/Components/Notifications.js b/src/Components/Notifications.js index e1ff9f1747522091694fc7e0b416dfbc2de9704b..b452b2157622560976cd9af179cabb1bd87e9d45 100644 --- a/src/Components/Notifications.js +++ b/src/Components/Notifications.js @@ -15,20 +15,21 @@ 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, useEffect} from 'react'; +import React, { useState, useEffect } from 'react'; import NotificationsIcon from '@material-ui/icons/Notifications'; import { Button } from '@material-ui/core'; import Badge from '@material-ui/core/Badge'; import styled from 'styled-components' import Menu from '@material-ui/core/Menu'; -import {apiDomain} from '../env.js' +import { apiDomain } from '../env.js' import ActivityListItem from './ActivityListItem.js' -import {getRequest} from './HelperFunctions/getAxiosConfig.js' +import { getRequest, postRequest } from './HelperFunctions/getAxiosConfig.js' import { withStyles } from '@material-ui/core/styles'; -import {Link} from 'react-router-dom' -import {getRecipientHref} from './Activities/getRecipientHref.js' +import { Link } from 'react-router-dom' +import { getRecipientHref } from './Activities/getRecipientHref.js' +import SnackBar from '../Components/SnackbarComponent' -const StyledBadge = styled(Badge) ` +const StyledBadge = styled(Badge)` .MuiBadge-dot-45{ height : 9px ; width : 9px ; @@ -53,39 +54,58 @@ const StyledNotificationButton = styled(Button)` ` const StyledMenu = withStyles({ - paper: { - border: '1px solid #d3d4d5', - }, + paper: { + border: '1px solid #d3d4d5', + }, })((props) => ( - <Menu - elevation={0} - getContentAnchorEl={null} - anchorOrigin={{ - horizontal: 'center', - vertical: "bottom", - }} - transformOrigin={{ - vertical: 'top', - horizontal: 'center', - }} - {...props} - /> + <Menu + elevation={0} + getContentAnchorEl={null} + anchorOrigin={{ + horizontal: 'center', + vertical: "bottom", + }} + transformOrigin={{ + vertical: 'top', + horizontal: 'center', + }} + {...props} + /> )); -export default function Notification (props) { +export default function Notification(props) { const [anchorEl, setAnchorEl] = React.useState(null); const [notifications, setNotifications] = useState([]); + const [snack, setSnack] = useState({ + open: false, + text: "", + severity: "", + color: "" + }); // eslint-disable-next-line const [notificatonsLength, setLength] = useState(0); - function handleAxiosSuccess (data) { - setNotifications(data) - setLength(data.length) + function handleAxiosSuccess(data) { + if (data.errors) + setSnack({ + open: true, + text: "Erro ao buscar suas notificações", + severity: "error", + color: "red" + }) + else { + setNotifications(data) + setLength(data.length) + } } - function handleAxiosError (error) { - console.log('error getNotifications') - console.log(error) + function handleAxiosError(error) { + setSnack({ + open: true, + text: "Erro ao buscar suas notificações", + severity: "error", + color: "red" + }) } @@ -102,50 +122,111 @@ export default function Notification (props) { function handleClose() { setAnchorEl(null); } + + function handleClickNotification() { + const payload = { + "activities": { + "ids": [] + } + } + + for (let index = 0; index < notifications.length; index++) { + const notification = notifications[index]; + payload.activities.ids.push(notification.id) + } + + postRequest( + '/activities/view', + payload, + (data) => { + if (data.errors) + setSnack({ + open: true, + text: "Erro ao marcar as notificações como lidas!", + severity: "error", + color: "red" + }) + else { + setSnack({ + open: true, + text: "Todas as notificações foram marcadas como lidas!", + severity: "success", + color: "green" + }) + setNotifications([]) + } + }, + (error) => { + setSnack({ + open: true, + text: "Erro ao marcar as notificações como lidas!", + severity: "error", + color: "red" + }) + }, + ) + + + } + return ( <React.Fragment> - <StyledNotificationButton onClick={handleClick}> - <StyledBadge badgeContent={1} color="secondary" variant="dot" overlap="circle" className="badge"> - <StyledNotificationsIcon/> - </StyledBadge> - </StyledNotificationButton> - <StyledMenu - id="simple-menu" - anchorEl={anchorEl} - keepMounted - open={Boolean(anchorEl)} - onClose={handleClose} - > - <ContainerDiv> - <div className="cabecalho"> - <span style={{fontSize : "15px"}}>NOTIFICAÇÕES •</span> - <span className="cabecalho-marcar">Marcar todas como lidas</span> - </div> - { - notifications.map( (notification) => - <ActivityListItem - onMenuBar={true} - avatar = {notification.owner.avatar ? apiDomain + notification.owner.avatar : null} - activity = {notification.activity} - actionType = {notification.trackable_type} - objectType = {notification.recipient_type} - createdAt = {notification.created_at} - ownerName = {notification.owner.name} - ownerHref = {'/perfil'} - recipientName = {notification.recipient.name} - recipientHref = {getRecipientHref(notification)} - /> - ) - } - <div style={{padding : "0 15px", borderTop : "1px solid #dadada"}}> - <Link to="/perfil"> - <NoPadButton> - MOSTRAR TODAS + <SnackBar + snackbarOpen={snack.open} + handleClose={() => { + setSnack({ + open: false, + text: "", + severity: "", + color: "" + }) + }} + severity={snack.severity} + color={snack.color} + text={snack.text} + /> + <StyledNotificationButton onClick={handleClick}> + <StyledBadge badgeContent={1} color="secondary" variant="dot" overlap="circle" className="badge"> + <StyledNotificationsIcon /> + </StyledBadge> + </StyledNotificationButton> + <StyledMenu + id="simple-menu" + anchorEl={anchorEl} + keepMounted + open={Boolean(anchorEl)} + onClose={handleClose} + > + <ContainerDiv> + <div className="cabecalho"> + <span style={{ fontSize: "15px" }}>NOTIFICAÇÕES •</span> + <span className="cabecalho-marcar" onClick={handleClickNotification}>Marcar todas como lidas</span> + </div> + { + notifications.map((notification) => + <ActivityListItem + onMenuBar={true} + avatar={notification.owner.avatar ? apiDomain + notification.owner.avatar : null} + activity={notification.activity} + actionType={notification.trackable_type} + objectType={notification.recipient_type} + createdAt={notification.created_at} + ownerName={notification.owner.name} + ownerHref={'/perfil'} + recipientName={notification.recipient.name} + recipientHref={getRecipientHref(notification)} + /> + ) + } + <div style={{ padding: "0 15px", borderTop: "1px solid #dadada" }}> + <Link to="/perfil"> + <NoPadButton> + MOSTRAR TODAS </NoPadButton> - </Link> - </div> - </ContainerDiv> - </StyledMenu> + </Link> + </div> + </ContainerDiv> + </StyledMenu> </React.Fragment> ) @@ -177,6 +258,7 @@ const ContainerDiv = styled.div` -webkit-text-decoration-line: underline; text-decoration-line: underline; float: right; + cursor: pointer;s } } ` diff --git a/src/Pages/ResourcePage.js b/src/Pages/ResourcePage.js index 0c2346800c1fb04252d7ce81f2b58f0f1a3d87bb..834a2c13e37779d62476666f5f5f64a8c5138b21 100644 --- a/src/Pages/ResourcePage.js +++ b/src/Pages/ResourcePage.js @@ -16,257 +16,307 @@ 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 {Store} from '../Store.js' -import styled from 'styled-components' -import {apiDomain} from '../env'; -import Grid from '@material-ui/core/Grid'; -import TextoObjeto from '../Components/ResourcePageComponents/TextoObjeto.js' -import Footer from '../Components/ResourcePageComponents/Footer.js' -import Sobre from '../Components/ResourcePageComponents/Sobre.js' -import CommentsArea from '../Components/ResourcePageComponents/CommentsArea.js' +import React, { useEffect, useState, useContext } from "react"; +import { Store } from "../Store.js"; +import styled from "styled-components"; +import { apiDomain } from "../env"; +import Grid from "@material-ui/core/Grid"; +import TextoObjeto from "../Components/ResourcePageComponents/TextoObjeto.js"; +import Footer from "../Components/ResourcePageComponents/Footer.js"; +import Sobre from "../Components/ResourcePageComponents/Sobre.js"; +import CommentsArea from "../Components/ResourcePageComponents/CommentsArea.js"; import noAvatar from "../img/default_profile.png"; -import Snackbar from '@material-ui/core/Snackbar'; -import Alert from '../Components/Alert.js'; -import VideoPlayer from '../Components/ResourcePageComponents/VideoPlayer.js' -import LoadingSpinner from '../Components/LoadingSpinner.js' -import { makeStyles } from '@material-ui/core/styles'; -import AppBar from '@material-ui/core/AppBar'; -import ButtonAvaliarRecurso from '../Components/ButtonAvaliarRecurso' -import ModalAvaliarRecurso from '../Components/ModalAvaliarRecurso' -import ModalConfirmarCuradoria from '../Components/ModalConfirmarCuradoria' -import {getRequest} from '../Components/HelperFunctions/getAxiosConfig' - -function urlVerify (url) { - return (url ? url.indexOf("youtu") !== -1 || url.indexOf("vimeo") !== -1 : false) +import Snackbar from "@material-ui/core/Snackbar"; +import Alert from "../Components/Alert.js"; +import VideoPlayer from "../Components/ResourcePageComponents/VideoPlayer.js"; +import LoadingSpinner from "../Components/LoadingSpinner.js"; +import { makeStyles } from "@material-ui/core/styles"; +import AppBar from "@material-ui/core/AppBar"; +import ButtonAvaliarRecurso from "../Components/ButtonAvaliarRecurso"; +import ModalAvaliarRecurso from "../Components/ModalAvaliarRecurso"; +import ModalConfirmarCuradoria from "../Components/ModalConfirmarCuradoria"; +import { getRequest } from "../Components/HelperFunctions/getAxiosConfig"; + +function urlVerify(url) { + return url + ? url.indexOf("youtu") !== -1 || url.indexOf("vimeo") !== -1 + : false; } -export default function LearningObjectPage (props){ - const {state} = useContext(Store) - const id = props.match.params.recursoId - const [carregando, toggle] = useState(true) - const [recurso, setRecurso] = useState({}) - - function handleSuccessfulGet (data) { - setRecurso(data) - toggle(false) - } - useEffect( () => { - const url = `/learning_objects/${id}` - - getRequest(url, handleSuccessfulGet, (error) => {console.log(error)}) - - }, []) - - - const [snackbarOpen, toggleSnackbar] = useState(false) - const handleSnackbar = (index) => {setIndex(index); toggleSnackbar(true)} - const snackbarText = [ - "Baixando o Recurso... Lembre-se de relatar sua experiência após o uso do Recurso!", - "Seu comentário foi publicado com sucesso!", - "Comentário editado com sucesso.", - "Comentário deletado com sucesso.", - "O Recurso foi guardado na coleção!" - ] - const [snackbarIndex, setIndex] = useState(0) - const classes = useStyles() - const [modalCuradoriaOpen, toggleModalCuradoria] = useState(false) - const handleModalCuradoria = (value) => {toggleModalCuradoria(value)} - - const checkAccessLevel = (levelToCheck) => { - if (state.currentUser.id !== '') { - return(checkUserRole(levelToCheck)) - } - else { - return(false) - } - } - - const checkUserRole = (userRole) => { - return(state.currentUser.roles.filter((role) => role.name === userRole).length > 0) - } - - const [modalConfirmarCuradoriaOpen, toggleModalConfirmarCuradoria] = useState(false) - const handleModalConfirmarCuradoria = (value) => {toggleModalConfirmarCuradoria(value)} - const [reportCriteria, setReportCriteria] = useState([]) - const [justificativa, setJustificativa] = useState('') - const [submissionAccepted, setSubmissionAccepted] = useState('') - - const handleConfirm = (criteria, justification, accepted) => { - console.log('criteria: ', criteria) - console.log('justification: ', justification) - setReportCriteria(criteria) - setJustificativa(justification) - setSubmissionAccepted(accepted) - handleModalCuradoria(false) - handleModalConfirmarCuradoria(true) - } - - const finalizeCuratorshipFlow = () => { - handleModalConfirmarCuradoria(false) - const url = `/learning_objects/${id}` - getRequest(url, (data) => {setRecurso(data)}, (error) => {console.log(error)}) +export default function LearningObjectPage(props) { + const { state } = useContext(Store); + const id = props.match.params.recursoId; + const [carregando, toggle] = useState(true); + const [recurso, setRecurso] = useState({}); + + function handleSuccessfulGet(data) { + setRecurso(data); + toggle(false); + } + useEffect(() => { + const url = `/learning_objects/${id}`; + + getRequest( + url, + handleSuccessfulGet, + (error) => { + toggle(false); + handleSnackbar(7) + } + ); + }, []); + + const [snackbarOpen, toggleSnackbar] = useState(false); + const handleSnackbar = (index) => { + setIndex(index); + toggleSnackbar(true); + }; + const snackbarText = [ + "Baixando o Recurso... Lembre-se de relatar sua experiência após o uso do Recurso!", + "Seu comentário foi publicado com sucesso!", + "Comentário editado com sucesso.", + "Comentário deletado com sucesso.", + "O Recurso foi guardado na coleção!", + "O recurso foi aprovado com sucesso!", + "Erro ao aprovar o recurso!", + "Erro ao carregar a página" + ]; + const [snackbarIndex, setIndex] = useState(0); + const classes = useStyles(); + const [modalCuradoriaOpen, toggleModalCuradoria] = useState(false); + const handleModalCuradoria = (value) => { + toggleModalCuradoria(value); + }; + + const checkAccessLevel = (levelToCheck) => { + if (state.currentUser.id !== "") { + return checkUserRole(levelToCheck); + } else { + return false; } + }; + const checkUserRole = (userRole) => { return ( - <React.Fragment> - <Snackbar open={snackbarOpen} autoHideDuration={1000} onClose={toggleSnackbar} - anchorOrigin = {{ vertical:'top', horizontal:'right' }} - > - <Alert severity="info" style={{backgroundColor:"#00acc1"}}> - {snackbarText[snackbarIndex]} - </Alert> - </Snackbar> - - <ModalAvaliarRecurso open={modalCuradoriaOpen} handleClose={() => {handleModalCuradoria(false)}} - title={recurso.name} confirm={handleConfirm} setCriteria={setReportCriteria} - /> - <ModalConfirmarCuradoria aceito={submissionAccepted} reportCriteria={reportCriteria} justificativa={justificativa} open={modalConfirmarCuradoriaOpen} handleClose={() => {handleModalConfirmarCuradoria(false)}} cancel={() => {handleModalCuradoria(true)}} recursoId={id} - finalizeCuratorshipFlow={finalizeCuratorshipFlow} - /> - <Background> - { - carregando ? - ( - <LoadingSpinner text={"Carregando Recurso"}/> - ) - : - ( - <> - <Grid container spacing={2}> - { - recurso.object_type === "Vídeo" && - !recurso.link ? - ( - <Grid item xs={12}><Card> - <VideoPlayer - link={recurso.link} - urlVerified={false} - videoUrl = {recurso.default_attachment_location} - /> - </Card></Grid> - - ) - : - ( - urlVerify(recurso.link) && - <Grid item xs={12}><Card> - <VideoPlayer - link={recurso.link} - urlVerified={true} - /> - </Card></Grid> - ) - } - - - <Grid item xs={12}> - <Card> - <div> - {recurso.thumbnail && - <img alt="" src={apiDomain + recurso.thumbnail}/> - } - - - - - <TextoObjeto - name={recurso.name} - rating={recurso.review_average} - recursoId={id} - likesCount={recurso.likes_count} - likedBool={recurso.liked} - objType={recurso.object_type} - subjects={recurso.subjects} - educationalStages={recurso.educational_stages} - viewCount={recurso.views_count} - downloadCount={recurso.downloads_count} - id={recurso.publisher ? recurso.publisher.id : undefined} - stateRecurso={recurso.state} - attachments={recurso.attachments} - audioUrl={recurso.default_attachment_location} - /> - </div> - - - <Footer - recursoId={id} - downloadableLink = {recurso.default_attachment_location} - handleSnackbar={handleSnackbar} - link={recurso.link} - title={recurso.name} - thumb={recurso.thumbnail} - currPageLink={window.location.href} - complained={recurso.complained} - /> - </Card> - </Grid> - - <Grid item xs={12}> - <Card> - {/*todo: change render method on additional item info*/} - <Sobre - avatar={recurso.publisher ? (recurso.publisher.avatar ? (apiDomain + recurso.publisher.avatar) : noAvatar) : noAvatar} - publisher={recurso.publisher ? recurso.publisher.name : undefined} - id={recurso.publisher ? recurso.publisher.id : undefined} - description={recurso.description} - author={recurso.author} - tags={recurso.tags} - attachments={recurso.attachments} - language={recurso.language} - mimeType={recurso.default_mime_type} - createdAt={recurso.created_at} - updatedAt={recurso.updated_at} - license={recurso.license} - followed={recurso.publisher.followed} - /> - </Card> - </Grid> - - { - recurso.state !== "submitted" && - <Grid item xs={12}> - <Card> - {/*adicionar funcionalidade ao botao de entrar*/} - <CommentsArea - recursoId = {id} - handleSnackbar={handleSnackbar} - objType={recurso.object_type} - recurso={true} - /> - </Card> - </Grid> - } - </Grid> - - { - recurso.state === 'submitted' && checkAccessLevel('curator') && - <AppBar position="fixed" color="primary" className={classes.appBar}> - <StyledAppBarContainer> - <div className="container"> - <div className="botoes"> - <ButtonAvaliarRecurso callback={() => {handleModalCuradoria(true)}}/> - </div> - </div> - </StyledAppBarContainer> - </AppBar> - } - </> - ) - } - - </Background> - </React.Fragment> - ) + state.currentUser.roles.filter((role) => role.name === userRole).length > + 0 + ); + }; + + const [modalConfirmarCuradoriaOpen, toggleModalConfirmarCuradoria] = useState( + false + ); + const handleModalConfirmarCuradoria = (value) => { + toggleModalConfirmarCuradoria(value); + }; + const [reportCriteria, setReportCriteria] = useState([]); + const [justificativa, setJustificativa] = useState(""); + const [submissionAccepted, setSubmissionAccepted] = useState(""); + + const handleConfirm = (criteria, justification, accepted) => { + setReportCriteria(criteria); + setJustificativa(justification); + setSubmissionAccepted(accepted); + handleModalCuradoria(false); + handleModalConfirmarCuradoria(true); + }; + + const finalizeCuratorshipFlow = () => { + handleSnackbar(5); + handleModalConfirmarCuradoria(false); + const url = `/learning_objects/${id}`; + getRequest( + url, + (data) => { + setRecurso(data); + }, + (error) => { + handleSnackbar(7) + } + ); + }; + + return ( + <React.Fragment> + <Snackbar + open={snackbarOpen} + autoHideDuration={6000} + onClose={toggleSnackbar} + anchorOrigin={{ vertical: "top", horizontal: "right" }} + > + <Alert severity="info" + style={{ backgroundColor: "#00acc1" }}> + {snackbarText[snackbarIndex]} + </Alert> + </Snackbar> + + <ModalAvaliarRecurso + open={modalCuradoriaOpen} + handleClose={() => { + handleModalCuradoria(false); + }} + title={recurso.name} + confirm={handleConfirm} + setCriteria={setReportCriteria} + /> + <ModalConfirmarCuradoria + aceito={submissionAccepted} + reportCriteria={reportCriteria} + justificativa={justificativa} + open={modalConfirmarCuradoriaOpen} + handleClose={() => { + handleModalConfirmarCuradoria(false); + }} + cancel={() => { + handleModalCuradoria(true); + }} + recursoId={recurso.submission_id} + finalizeCuratorshipFlow={finalizeCuratorshipFlow} + handleErrorAprove={() => { + handleSnackbar(6) + }} + /> + <Background> + {carregando ? ( + <LoadingSpinner text={"Carregando Recurso"} /> + ) : ( + <> + <Grid container spacing={2}> + {recurso.object_type === "Vídeo" && !recurso.link ? ( + <Grid item xs={12}> + <Card> + <VideoPlayer + link={recurso.link} + urlVerified={false} + videoUrl={recurso.default_attachment_location} + /> + </Card> + </Grid> + ) : ( + urlVerify(recurso.link) && ( + <Grid item xs={12}> + <Card> + <VideoPlayer link={recurso.link} urlVerified={true} /> + </Card> + </Grid> + ) + )} + + <Grid item xs={12}> + <Card> + <div> + {recurso.thumbnail && ( + <img alt="" src={apiDomain + recurso.thumbnail} /> + )} + + <TextoObjeto + name={recurso.name} + rating={recurso.review_average} + recursoId={id} + likesCount={recurso.likes_count} + likedBool={recurso.liked} + objType={recurso.object_type} + subjects={recurso.subjects} + educationalStages={recurso.educational_stages} + viewCount={recurso.views_count} + downloadCount={recurso.downloads_count} + id={recurso.publisher ? recurso.publisher.id : undefined} + stateRecurso={recurso.state} + attachments={recurso.attachments} + audioUrl={recurso.default_attachment_location} + /> + </div> + + <Footer + recursoId={id} + downloadableLink={recurso.default_attachment_location} + handleSnackbar={handleSnackbar} + link={recurso.link} + title={recurso.name} + thumb={recurso.thumbnail} + currPageLink={window.location.href} + complained={recurso.complained} + /> + </Card> + </Grid> + + <Grid item xs={12}> + <Card> + {/*todo: change render method on additional item info*/} + <Sobre + avatar={ + recurso.publisher + ? recurso.publisher.avatar + ? apiDomain + recurso.publisher.avatar + : noAvatar + : noAvatar + } + publisher={ + recurso.publisher ? recurso.publisher.name : undefined + } + id={recurso.publisher ? recurso.publisher.id : undefined} + description={recurso.description} + author={recurso.author} + tags={recurso.tags} + attachments={recurso.attachments} + language={recurso.language} + mimeType={recurso.default_mime_type} + createdAt={recurso.created_at} + updatedAt={recurso.updated_at} + license={recurso.license} + followed={recurso.publisher.followed} + /> + </Card> + </Grid> + + {recurso.state !== "submitted" && ( + <Grid item xs={12}> + <Card> + {/*adicionar funcionalidade ao botao de entrar*/} + <CommentsArea + recursoId={id} + handleSnackbar={handleSnackbar} + objType={recurso.object_type} + recurso={true} + /> + </Card> + </Grid> + )} + </Grid> + + {recurso.state === "submitted" && checkAccessLevel("curator") && ( + <AppBar + position="fixed" + color="primary" + className={classes.appBar} + > + <StyledAppBarContainer> + <div className="container"> + <div className="botoes"> + <ButtonAvaliarRecurso + callback={() => { + handleModalCuradoria(true); + }} + /> + </div> + </div> + </StyledAppBarContainer> + </AppBar> + )} + </> + )} + </Background> + </React.Fragment> + ); } const useStyles = makeStyles((theme) => ({ appBar: { - top: 'auto', + top: "auto", bottom: 0, - height : '100px', - backgroundColor : '#fff', - boxShadow : '0 1px 3px rgba(0,0,0,.52),0 1px 2px rgba(0,0,0,.24)' + height: "100px", + backgroundColor: "#fff", + boxShadow: "0 1px 3px rgba(0,0,0,.52),0 1px 2px rgba(0,0,0,.24)", }, })); @@ -293,43 +343,43 @@ const StyledAppBarContainer = styled.div` align-items : center; } } -` +`; const Background = styled.div` - background-color : #f4f4f4; - color : #666; - font-family : 'Roboto', sans serif; - padding-top : 30px; -` + background-color: #f4f4f4; + color: #666; + font-family: "Roboto", sans serif; + padding-top: 30px; +`; const Card = styled.div` - background-color : #fff; - box-shadow : 0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24); - margin-bottom : 30px; - margin-right : auto; - margin-left : auto; - display : flex; - flex-direction : column; - @media screen and (min-width: 1200px) { - width : 1170px; - } - @media screen and (min-width: 992px) and (max-width : 1199px){ - width : 970px; - } - @media screen and (min-width: 768px) and (max-width : 991px) { - width : 750px; - } - - img { - background-color : #e5e5e5; - height : 270px; - width : 400px; - float : left; - padding : 0; - object-fit : cover; - @media screen and (max-width: 768px) { - height : auto; - width : 100%; - } + background-color: #fff; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); + margin-bottom: 30px; + margin-right: auto; + margin-left: auto; + display: flex; + flex-direction: column; + @media screen and (min-width: 1200px) { + width: 1170px; + } + @media screen and (min-width: 992px) and (max-width: 1199px) { + width: 970px; + } + @media screen and (min-width: 768px) and (max-width: 991px) { + width: 750px; + } + + img { + background-color: #e5e5e5; + height: 270px; + width: 400px; + float: left; + padding: 0; + object-fit: cover; + @media screen and (max-width: 768px) { + height: auto; + width: 100%; } -` + } +`; diff --git a/src/Pages/Search.js b/src/Pages/Search.js index 59c24ee39f9e043c024923372cf32ac141889bf3..4180c2328f6cbab7a0c073f360094b85ab3185ae 100644 --- a/src/Pages/Search.js +++ b/src/Pages/Search.js @@ -98,11 +98,16 @@ export default function Search(props) { } const collectStuff = (tipoBusca, filtro) => { + + const urlParams = new URLSearchParams(window.location.search); + const query = urlParams.get("query"); + const searchClass = urlParams.get("search_class"); + if (!loadingMoreData) // this line prevents resetting filter when loading more data currFilter = filtro; if (filtro) setIsFiltering(true); - const url = `/search?page=${page}&results_per_page=${resultsPerPage}&order=${order}&query=${state.search.query}${currFilter ? currFilter : ""}&search_class=${tipoBusca}` + const url = `/search?page=${page}&results_per_page=${resultsPerPage}&order=${order}&query=${query}${currFilter ? currFilter : ""}&search_class=${searchClass}` getRequest(url, handleSuccessfulGet, (error) => { console.log(error) }) }; @@ -113,9 +118,6 @@ export default function Search(props) { const query = urlParams.get("query"); const searchClass = urlParams.get("search_class"); - console.log(query) - console.log(searchClass) - if (state.search.query !== query || state.search.class !== searchClass) { dispatch({ type: "SAVE_SEARCH",