Skip to content
Snippets Groups Projects
Commit 4ce57507 authored by Raul Almeida's avatar Raul Almeida
Browse files

Finish comment section

parent eb7b2f2a
No related branches found
No related tags found
5 merge requests!57Merge of develop into master,!56Fixed buttons reportar, seguir, compartilhar, guardar and entrar (in comments...,!39Update admin system,!32Homologa,!23Tela de coleção
......@@ -16,9 +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, { useState, useEffect } from 'react';
import React, { useRef, useState, useEffect } from 'react';
import { Grid } from '@material-ui/core';
import Card from '@material-ui/core/Card';
import Button from '@material-ui/core/Button';
import EditIcon from '@material-ui/icons/Edit';
import styled from 'styled-components';
import axios from 'axios';
import { apiUrl } from '../env';
......@@ -26,12 +28,14 @@ import CommentForm from './ResourcePageComponents/CommentForm.js';
import Comment from './Comment.js';
import Snackbar from '@material-ui/core/Snackbar';
import MuiAlert from '@material-ui/lab/Alert';
import Comentario from '../img/comentarios.png';
export default function CollectionCommentSection(props) {
const [post_snack_open, setPostSnackOpen] = useState(false);
const [delete_snack_open, setDeleteSnackOpen] = useState(false);
const [render_state, setRenderState] = useState(false);
const [reviews, setReviews] = useState([]);
const comment_ref = useRef(null);
const forceUpdate = () => { setRenderState(!render_state); }
......@@ -43,25 +47,50 @@ export default function CollectionCommentSection(props) {
setDeleteSnackOpen(!delete_snack_open);
}
const handleScrollToCommentForm = () => {
window.scrollTo(0, comment_ref.current.offsetTop);
}
function Alert(props) {
return <MuiAlert elevation={6} variant="filled" {...props} />;
}
useEffect(() => {
axios.get(apiUrl+'/collections/'+props.id+'/reviews')
.then(res => {
setReviews(res.data);
});
}, [render_state]);
const NoCommentsMessage = () => {
const NoCommentsContainer=styled.div`
text-align: center;
margin-left: 9vw;
margin-right: 9vw;
`
const BlueTitle=styled.h2`
color: #673ab7;
`
const Secondary=styled.h3`
font-weight: 100;
`
const ButtonText=styled.span`
font-weight: 900;
`
const Image=styled.img`
`
return (
<CommentAreaContainer container xs={12} direction="row" justify="center" alignItems="center">
<Grid item xs={12}>
<CommentAreaCard>
<Title>Conte sua experiência com a coleção</Title>
<CommentForm colecao recursoId={props.id}
handleSnackbar={handlePostSnackbar}
rerenderCallback={forceUpdate}/>
<NoCommentsContainer>
<Image src={Comentario} />
<BlueTitle>Compartilhe sua opinião com a rede!</BlueTitle>
<Secondary>Gostou desta coleção? Comente e compartilhe com a rede sua opinião. Interagindo com a rede, você contribui para que mais coleções como esta sejam criadas.</Secondary>
<Button
variant="contained"
color="primary"
startIcon={<EditIcon />}
onClick={handleScrollToCommentForm}
>
<ButtonText>Relatar experiência</ButtonText>
</Button>
</NoCommentsContainer>
);
}
const CollectionComments = () => {
return (
<div>
<Title>{reviews.length} {reviews.length == 1 ? "Relato" : "Relatos"} sobre a Coleção</Title>
{reviews.map(r => {
return (
......@@ -79,8 +108,28 @@ export default function CollectionCommentSection(props) {
handleSnackbar={handleDeleteSnackbar}
recurso={false}
/>
);})}
</div>
);
})}
}
useEffect(() => {
axios.get(apiUrl+'/collections/'+props.id+'/reviews')
.then(res => {
setReviews(res.data);
});
}, [render_state]);
return (
<CommentAreaContainer container xs={12} direction="row" justify="center" alignItems="center">
<Grid item xs={12} ref={comment_ref}>
<CommentAreaCard>
<Title>Conte sua experiência com a coleção</Title>
<CommentForm colecao recursoId={props.id}
handleSnackbar={handlePostSnackbar}
rerenderCallback={forceUpdate}
/>
{reviews.length ? CollectionComments() : NoCommentsMessage()}
</CommentAreaCard>
</Grid>
<Snackbar
......@@ -107,6 +156,7 @@ export default function CollectionCommentSection(props) {
);
}
const CommentAreaContainer=styled(Grid)`
margin-left: 10%;
margin-right: 10%;
......
import React, {useContext} from 'react';
import Modal from '@material-ui/core/Modal';
import Fade from '@material-ui/core/Fade';
import styled from 'styled-components'
import { Button } from '@material-ui/core';
import Backdrop from '@material-ui/core/Backdrop';
import { Store } from '../Store.js';
import axios from 'axios'
import {apiUrl} from '../env';
const StyledModal = styled(Modal)`
margin : 0 !important;
margin-left : 0 !important;
display : flex;
align-items: center;
justify-content : center;
text-align : center;
padding : 10px !important;
border-radius : 4px;
max-width : none;
max-height : none;
min-width: 150px;
min-height: 150px !important;
`
const HeaderDiv = styled.div`
width : 100%;
max-width : 100%;
display : flex;
align-items : center;
align-content : center;
`
const ContentContainer = styled.div`
box-sizing : border-box;
background-color : white;
max-width : none;
min-wdith : 240px;
align : center;
border-radius : 4px;
font-family : 'Roboto', sans serif;
box-shadow : 0 7px 8px -4px rgba(0,0,0,.2),0 13px 19px 2px rgba(0,0,0,.14),0 5px 24px 4px rgba(0,0,0,.12)!important;
`
const ButtonCancelar = styled(Button)`
background-color : rgba(158,158,158,0.2) !important;
color : #666 !important;
text-decoration : none !important;
outline : none !important;
text-align : center !important;
margin : 0 8px !important;
font-weight : 600 !important;
`
const ButtonConfirmar = styled(Button)`
background-color : #ff7f00 !important;
color : #fff !important;
border-radius : 3px !important;
margin : 0 8px !important;
font-weight : 600 !important;
`
export default function ModalExcluir (props) {
const text = {
header : "Tem certeza que deseja excluir este comentário?",
explanation : "A exclusão de um comentário é permanente. Não é possível desfazer."
}
return (
<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}>
<ContentContainer>
<HeaderDiv>
<h3 style={{fontSize : "24px", margin : "20px 15px 10px", fontWeight : "normal"}}>
{text.header}
</h3>
</HeaderDiv>
<div style={{display : "flex", flexDirection : "column", padding : "20px 30px"}}>
<div style={{marginTop : "0", textAlign : "center", marginBottom : "20px"}}>
<span style={{fontSize : "14px", color : "#666"}}>{text.explanation}</span>
</div>
<div style={{display : "flex", flexDirection : "row", justifyContent: "center"}}>
<ButtonCancelar onClick={props.handleClose}>CANCELAR</ButtonCancelar>
<ButtonConfirmar onClick={props.handleConfirm}> EXCLUIR </ButtonConfirmar>
</div>
</div>
</ContentContainer>
</Fade>
</StyledModal>
)
}
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';
import EditIcon from '@material-ui/icons/Edit';
import Grid from '@material-ui/core/Grid';
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
}
]
}
}
let type = props.recurso ? 'learning_objects/' : 'collections/'
console.log(payload)
axios.post( (`${apiUrl}/` + type + 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">
{props.recurso ? "Este recurso foi útil?*" : "Esta coleção 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" }}>{props.recurso ? "Avalie se o recurso foi útil." : "Avalie se esta coleção foi útil."}</div>
<Grid container>
<Grid item xs={10}>
<StyledTextField
colecao={!props.recurso}
value={comment.value}
multiline
rows="5"
error={comment.error}
label={props.recurso ? "Escreva aqui a sua experiência com este Recurso" : "Escreva aqui a sua experiência com esta Coleção"}
onChange={e => handleChange(e)}
required={true}
help = {comment.error ? (props.recurso ? "Escreva aqui a sua experiência com este Recurso" : "Escreva aqui a sua experiência com esta Coleção") : ''}
/>
</Grid>
<Grid item xs={2}>
<div style={{height : "100%", display : "flex", flexDirection : "column", justifyContent : "flex-end"}}>
{
props.recurso ?
(
<OrangeButton type="submit">Publicar</OrangeButton>
)
:
(
<PurpleButton type="submit"><EditIcon/>Enviar</PurpleButton>
)
}
</div>
</Grid>
<div className="campos-obrigatorios">* Campos obrigatórios.</div>
</Grid >
</StyledForm>
)
}
const PurpleButton = styled(Button)`
background-color : #673ab7 !important;
box-shadow : 0 2px 5px 0 rgba(0,0,0,.26) !important;
font-weight : 600 !important;
color : #fff !important;
.icon {
vertical-align : middle !important;
font-weight : normal !important;
font-style : normal !important;
font-size : 24px !important;
line-height : 1 !important;
letter-spacing : normal !important;
text-transform : none !important;
display : inline-block !important;
white-space : nowrap !important;
word-wrap : normal !important;
direction : ltr !important;
padding-right : 2px;
}
`
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 : 5px;
}
label.Mui-focused {
color : ${props => props.colecao ? "#673ab7" : "rgb(255,127,0)"}
}
.MuiInput-underline::after {
border-bottom: ${props => props.colecao ? "2px solid #673ab7" : "2px solid rgb(255,127,0)" };
}
label.Mui-focused.Mui-error {
color : red;
}
width: 95%;
`
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 {
padding-top : 18px;
font-weight : 400;
font-size : 12px;
color :#a5a5a5;
}
`
/*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}
recurso={true}
/>
</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;
}
`
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment