diff --git a/src/Components/ResourcePageComponents/CommentForm.js b/src/Components/ResourcePageComponents/CommentForm.js new file mode 100644 index 0000000000000000000000000000000000000000..1c0b048a0fc6a65d594bafa8a99cbf00d25e3c34 --- /dev/null +++ b/src/Components/ResourcePageComponents/CommentForm.js @@ -0,0 +1,171 @@ +import React, {useState} from 'react' +import styled from 'styled-components' +import Rating from '@material-ui/lab/Rating'; +import StarBorderIcon from '@material-ui/icons/StarBorder'; +import StarIcon from '@material-ui/icons/Star'; +import TextField from "@material-ui/core/TextField"; +import { Button } from '@material-ui/core'; +import axios from 'axios' +import {apiUrl} from '../../env'; + +export default function CommentForm (props) { + const [rating, setRating] = useState({ + error : true, + value : 0 + }) + const [comment, setComment] = useState({ + error : false, + value : '' + }) + + const handleChange = (e) => { + const userInput = e.target.value + const flag = (userInput.length === 0 ? true : false); + setComment({...comment, error : flag, value : userInput}) + } + + const [attemptedSubmit, setAttempt] = useState(false) + + const handleSubmit = (e) => { + e.preventDefault() + const finalRating = rating + const finalComment = comment + + + if (!(finalRating.error || finalComment.error)) { + let config = { + headers : { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Access-Token': sessionStorage.getItem('@portalmec/accessToken'), + 'Client': sessionStorage.getItem('@portalmec/clientToken'), + 'Uid': sessionStorage.getItem('@portalmec/uid'), + } + } + let payload = { + "review" : { + "description" : finalComment.value, + "review_ratings_attributes" : [ + { + "rating_id" : 1, + "value" : finalRating.value + } + ] + } + } + console.log(payload) + axios.post( (`${apiUrl}/learning_objects/` + props.recursoId + '/reviews'), payload, config + ).then((response) => { + if ( response.headers['access-token'] ) { + sessionStorage.setItem('@portalmec/accessToken', response.headers['access-token']) + } + console.log(response.data); + props.handleSnackbar(1); + props.rerenderCallback()}, + (error) => {console.log(error)}) + } + else { + setAttempt(true) + } + } + + return ( + <StyledForm onSubmit={handleSubmit}> + <label htmlFor="avaliacao-estrelas" className="start-label"> + Este recurso foi útil?* + </label> + <div className="stars-container"> + <Rating + name="avaliacao-estrelas" + value={rating.value} + precision={0.5} + style={{color:"#ff9226"}} + onChange = {(e, newValue) => {setRating({...rating, error : newValue === null ? true : false, value : newValue})}} + emptyIcon={<StarIcon fontSize="inherit" style={{color : "#666"}} />} + getLabelText={(value) => {return(value + ' Estrela' + (value !== 1 ? 's' : ''))}} + /> + </div> + <div className="star-alert" style={attemptedSubmit ? {visibility : "visible"} : {visibility : "hidden" }}>Avalie se o recurso foi útil.</div> + + <span> + <StyledTextField + value={comment.value} + multiline + rows="5" + error={comment.error} + label={"Escreva aqui a sua experiência com este Recurso"} + onChange={e => handleChange(e)} + required={true} + help = {comment.error ? 'Escreva aqui seu comentário sobre o Recurso.' : ''} + /> + <OrangeButton type="submit">Publicar</OrangeButton> + <div className="campos-obrigatorios">* Campos obrigatórios.</div> + </span> + </StyledForm> + ) +} + +const OrangeButton = styled(Button)` + color : rgba(255,255,255,0.87) !important; + box-shadow : 0 2px 5px 0 rgba(0,0,0,.26) !important; + font-weight : 600 !important; + background-color : #ff7f00 !important; +` + +const StyledTextField = styled(TextField)` + .MuiInputBase-root { + margin-bottom : 42px; + } + + label.Mui-focused { + color : rgb(255,127,0); + } + + .MuiInput-underline::after { + border-bottom: 2px solid rgb(255,127,0); + } + + label.Mui-focused.Mui-error { + color : red; + } + + max-width: 80%; + width : 80% !important; + full-width : 80% !important; +` + +const StyledForm = styled.form` + display : flex; + flex-direction : column; + text-align : start; + + .start-label { + font-size : 14px; + max-width : 100%; + display : inline-block; + margin-bottom : 0; + color : #a5a5a5; + font-weight : 400; + } + + .stars-container { + padding-top : 10px; + padding-bottom : 5px; + display : flex; + flex-direction : row; + align-self : flex-start; + margin-bottom : 5px; + color : #a5a5a5; + } + + .star-alert { + color : #666; + text-align : start; + } + + .campos-obrigatorios { + font-weight : 400; + font-size : 12px; + color :#a5a5a5; + } +` diff --git a/src/Components/ResourcePageComponents/CommentsArea.js b/src/Components/ResourcePageComponents/CommentsArea.js new file mode 100644 index 0000000000000000000000000000000000000000..27258099ed9c07e761005b253c576522587ca605 --- /dev/null +++ b/src/Components/ResourcePageComponents/CommentsArea.js @@ -0,0 +1,218 @@ +/*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, {useState, useContext, useEffect} from 'react' +import {Store} from '../../Store.js' +import styled from 'styled-components' +import Grid from '@material-ui/core/Grid'; +import { Button } from '@material-ui/core'; +import ExitToAppIcon from '@material-ui/icons/ExitToApp'; +import Comentarios from '../../img/comentarios.png' +import {apiUrl, apiDomain} from '../../env'; +import CommentForm from './CommentForm.js' +import axios from 'axios' +import Comment from '../Comment.js' + +export default function CommentsArea (props) { + const {state} = useContext(Store) + const [comentarios, setComentarios] = useState([]) + const [gambiarra, setState] = useState(0) + const forceUpdate = () => {setState(gambiarra + 1)} + + useEffect( () => { + axios.get( (`${apiUrl}/learning_objects/` + props.recursoId + '/reviews') + ).then( (response) => { + if ( response.headers['access-token'] ) { + sessionStorage.setItem('@portalmec/accessToken', response.headers['access-token']) + } + console.log(response) + setComentarios(response.data.sort((a, b) => a.updated_at > b.updated_at ? -1 : 1)) + }, (error) => {console.log(error)}) + }, [gambiarra]) + + return ( + <Grid container spacing={2} style={{padding : "10px"}}> + { + (state.currentUser.id !== '') ? + ( + [ + <Grid item xs={12} > + <GrayContainer> + <h3>Conte sua experiência com o Recurso</h3> + <Grid container style={{paddingTop : "20px"}}> + <Grid item xs={2} style={{paddingLeft : "15px", paddingRight : "15px"}}> + <img src={apiDomain + state.currentUser.userAvatar} className="minha-imagem" alt="user avatar"/> + </Grid> + <Grid item xs={10}> + <CommentForm + recursoId={props.recursoId} + handleSnackbar={props.handleSnackbar} + rerenderCallback={forceUpdate} + /> + </Grid> + </Grid> + </GrayContainer> + </Grid> + ] + ) + : + ( + [ + <Grid item xs={12}> + <LogInToComment> + <span className="span-laranja">Você precisa entrar para comentar</span> + {/*adicionar funcionalidade ao botao de entrar*/} + <Button style={{textTransform : "uppercase", color : "#666", fontWeight : "700"}}> + <ExitToAppIcon/>ENTRAR + </Button> + </LogInToComment> + </Grid> + ] + ) + } + { + comentarios.length !== 0 ? + ( + [ + <ComentariosBox> + <h3>{comentarios.length} {comentarios.length != 1 ? 'Relatos' : 'Relato'} sobre o uso do Recurso</h3> + { + comentarios.map( comentario => + <div className="comentario-template" key={comentario.id}> + <Comment + authorID={comentario.user ? comentario.user.id : null} + authorAvatar={comentario.user ? comentario.user.avatar : null} + authorName={comentario.user ? comentario.user.name : null} + name={comentario.name} + rating={comentario.rating_average} + reviewRatings = {comentario.review_ratings} + description={comentario.description} + createdAt={comentario.created_at} + recurso={true} + reviewID={comentario.id} + objectID={props.recursoId} + rerenderCallback={forceUpdate} + handleSnackbar={props.handleSnackbar} + /> + </div> + ) + } + </ComentariosBox> + ] + ) + : + ( + [ + <Grid item xs={12}> + <LogInToComment> + <img src={Comentarios} /> + <span className="span-laranja">Compartilhe sua experiência com a Rede!</span> + <AoRelatar> + Ao relatar sua experiência de uso do Recurso você estará auxiliando professores de todo paÃs. + </AoRelatar> + </LogInToComment> + </Grid> + ] + ) + } + </Grid> + ) +} + + +const ComentariosBox = styled.div` + display : flex; + flex-direction : column; + padding : 20px; + width : 100%; + + h3 { + font-family: 'Roboto Light','Roboto Regular',Roboto; + font-weight: 300; + font-style: normal; + color:#666; + font-size: 1.857em; + margin: 15px 2%; + text-align : flex-start; + } + + .comentario-template { + padding : 20px 0; + border-bottom : 1px solid #f4f4f4; + } +` +const AoRelatar = styled.div` + width : 70%; + font-size : 20px; + font-weight : 300; + text-align : center; + padding-bottom : 20px; +` + +const LogInToComment = styled.div` + display : flex; + flex-direction : column; + text-align : center; + padding : 20px; + align-items : center; + + .span-laranja { + font-size : 24px; + font-weight : 700; + padding-bottom : 5px; + color : #ff7f00; + } + + img { + object-fit : contain !important; + background-color : transparent !important; + } +` + +const GrayContainer = styled.div` + background-color : #fafafa; + font-weight : 400; + display : flex; + flex-direction : column; + justify-content : space-between; + padding-right : 15px; + padding-left : 15px; + padding-bottom : 20px; + + h3 { + font-family : 'Roboto Light','Roboto Regular',Roboto; + font-weight: 300; + font-style: normal; + color: #666; + font-size: 1.857em; + margin-bottom : 10px; + margin-left : 2%; + margin-top : 2%; + } + + .minha-imagem { + height: 60px; + width: 60px; + border-radius: 50%; + margin-left: 2%; + margin-top: 5%; + } + img { + vertical-align :middle; + } +` diff --git a/src/Components/ResourcePageComponents/Footer.js b/src/Components/ResourcePageComponents/Footer.js index d06909950255ebc75160f24dcce6d46341259fb8..b05799a8d12d3e5f573c3458d0e46caab474a107 100644 --- a/src/Components/ResourcePageComponents/Footer.js +++ b/src/Components/ResourcePageComponents/Footer.js @@ -1,4 +1,5 @@ -import React from 'react' +import React, {useState, useContext} from 'react' +import {Store} from '../../Store.js' import styled from 'styled-components' import Grid from '@material-ui/core/Grid'; import { Button } from '@material-ui/core'; @@ -7,46 +8,73 @@ import ShareIcon from '@material-ui/icons/Share'; import FolderIcon from '@material-ui/icons/Folder'; import GetAppIcon from '@material-ui/icons/GetApp'; import CallMadeIcon from '@material-ui/icons/CallMade'; +import {Link} from 'react-router-dom' +import ReportModal from '../ReportModal.js' +import ReportRecursoForm from '../ReportRecursoForm.js' +import ShareModal from '../ShareModal.js' export default function Footer (props) { + const {state} = useContext(Store) + const enableDownload = () => { + const url = props.downloadableLink + window.open(url, '_blank'); + props.handleSnackbar(0) + } + + const [reportOpen, toggleReport] = useState(false) + const [shareOpen, toggleShare] = useState(false) return ( - <OpcoesDiv> - <StyledGrid container> - <Grid item xs={3}> - <ButtonGrey> - <span className="button-text"> - <ErrorIcon className="icon"/> Reportar abuso ou erro - </span> - </ButtonGrey> - </Grid> - - <Grid item xs={3}> - <ButtonGrey> - <span className="button-text"> - <ShareIcon className="icon"/> Compartilhar - </span> - </ButtonGrey> - </Grid> - - <Grid item xs={3}> - <ButtonGrey> - <span className="button-text"> - <FolderIcon className="icon"/>Guardar - </span> - </ButtonGrey> - </Grid> - - <Grid item xs={3} style={{justifyContent : "right !important"}}> - <ButtonOrange> - <span className="text"> - <GetAppIcon className="icon"/> Baixar Recurso - </span> - </ButtonOrange> - </Grid> - - </StyledGrid> - </OpcoesDiv> + <React.Fragment> + <ReportModal open={reportOpen} handleClose={() => {toggleReport(false)}} + form="recurso" + complainableId={props.recursoId} + complainableType={"LearningObject"} + /> + <ShareModal open={shareOpen} handleClose={() => {toggleShare(false)}} + thumb={props.thumb} title={props.title} link={props.link} + /> + + <OpcoesDiv> + <StyledGrid container> + + {/*Botao Reportar*/} + <Grid item xs={3}> + <ButtonGrey onClick={state.currentUser.id === '' ? () => console.log('abrir login modal') : () => toggleReport(true)}> + <span className="button-text"> + <ErrorIcon className="icon"/> Reportar abuso ou erro + </span> + </ButtonGrey> + </Grid> + + {/*Botao Compartilhar*/} + <Grid item xs={3}> + <ButtonGrey onClick={state.currentUser.id === '' ? () => console.log('abrir login modal') : () => toggleShare(true)}> + <span className="button-text"> + <ShareIcon className="icon"/> Compartilhar + </span> + </ButtonGrey> + </Grid> + + <Grid item xs={3}> + <ButtonGrey> + <span className="button-text"> + <FolderIcon className="icon"/>Guardar + </span> + </ButtonGrey> + </Grid> + + <Grid item xs={3} style={{justifyContent : "right !important"}}> + <ButtonOrange onClick={() => {enableDownload()}}> + <span className="text"> + <GetAppIcon className="icon"/> Baixar Recurso + </span> + </ButtonOrange> + </Grid> + + </StyledGrid> + </OpcoesDiv> + </React.Fragment> ) } @@ -118,7 +146,7 @@ const ButtonOrange = styled(Button)` text-align : center !important; max-height : 36px; margin-top : 5px !important; - + .icon { vertical-align : middle !important; font-weight : normal !important; @@ -137,6 +165,5 @@ const ButtonOrange = styled(Button)` .text { font-size : 14px; font-weight : 600; - } ` diff --git a/src/Components/ResourcePageComponents/Sobre.js b/src/Components/ResourcePageComponents/Sobre.js index 4da1a019e66bae42f4c5d63160f8307da3383806..d130368afd5db70a6c213e826a8cb2cb964fc504 100644 --- a/src/Components/ResourcePageComponents/Sobre.js +++ b/src/Components/ResourcePageComponents/Sobre.js @@ -60,7 +60,7 @@ export default function Sobre (props) { aux.push(<AdditionalInfoItem icon={<SdCardIcon/>} label={'Tamanho: '} - value={props.attachments[0].size} + value={(props.attachments[0].size / 1000000).toFixed(2) + ' Mb'} />) } props.language.map( (lang) => @@ -107,7 +107,18 @@ export default function Sobre (props) { </div> }/>) } - console.log(aux) + else { + aux.push(<AdditionalInfoItem + icon={<AssignmentIcon/>} + label={'Tipo de licença: '} + value={ + <div className="license-link"> + <p> + Informação não disponÃvel. + </p> + </div> + }/>) + } setAdditionalInfo(aux) }, []) @@ -218,6 +229,7 @@ const CollapseControl = styled.div` border-top : 1px solid #e5e5e5; color : #666; font-weight : 700; + cursor : pointer; .MuiSvgIcon-root { vertical-align : middle diff --git a/src/Components/ResourcePageComponents/TextoObjeto.js b/src/Components/ResourcePageComponents/TextoObjeto.js index daad075a9641c3f8a826af6ce76c36245032dc93..a9e25cfde32dac52ff39d0c385f41d74002dc1b9 100644 --- a/src/Components/ResourcePageComponents/TextoObjeto.js +++ b/src/Components/ResourcePageComponents/TextoObjeto.js @@ -16,14 +16,20 @@ 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, {useEffect, useState, useContext} from 'react' +import {Store} from '../../Store.js' import styled from 'styled-components' import Firulas from '../Firulas.js' import Grid from '@material-ui/core/Grid'; import VisibilityIcon from '@material-ui/icons/Visibility'; import GetAppIcon from '@material-ui/icons/GetApp'; +import EditIcon from '@material-ui/icons/Edit'; +import DeleteForeverIcon from '@material-ui/icons/DeleteForever'; +import Button from '@material-ui/core/Button'; export default function TextoObjeto (props) { + const {state} = useContext(Store) + const [outrasTematicas, setOutrasTem] = useState('') const [componentesCurriculares, setCompCurr] = useState('') const [eduStages, setEduStages] = useState('') @@ -64,7 +70,7 @@ export default function TextoObjeto (props) { return ( <TextoObjetoDiv> - <Grid container style={{paddingRight : "15px", paddingLeft : "15px"}}> + <Grid container style={{paddingLeft : "15px"}}> <Grid item xs={11}> <h3>{props.name}</h3> <Firulas @@ -96,7 +102,14 @@ export default function TextoObjeto (props) { </Grid> <Grid item xs={1}> - <span>(WIP)botoes caso usuario visualizando seja o publisher</span> + {/*|| checkUserRole('publisher')*/} + {(props.id === state.currentUser.id && (props.stateRecurso === 'draft' )) && + <React.Fragment> + <Button style={{color : "#666"}}><EditIcon/></Button> + <Button style={{color : "#666"}}><DeleteForeverIcon/></Button> + </React.Fragment> + } + </Grid> </Grid> </TextoObjetoDiv>