diff --git a/src/Components/CollectionCommentSection.js b/src/Components/CollectionCommentSection.js index 62c0fd5db0ca4fcbd70a202814a1b50de4a521f0..24d4da5ca2c1450154c8a1ea2ae8f30aafd95933 100644 --- a/src/Components/CollectionCommentSection.js +++ b/src/Components/CollectionCommentSection.js @@ -32,6 +32,7 @@ import ExitToAppIcon from '@material-ui/icons/ExitToApp'; import SignUpModal from './SignUpModal.js'; import LoginModal from './LoginModal.js'; import SnackBarComponent from './SnackbarComponent'; +import CircularProgress from '@material-ui/core/CircularProgress'; export default function CollectionCommentSection(props) { @@ -40,6 +41,7 @@ export default function CollectionCommentSection(props) { const [render_state, setRenderState] = useState(false); const [sign_up_open, setSignUpOpen] = useState(false); const [log_in_open, setLoginOpen] = useState(false); + const [is_loading, setIsLoading] = useState(false); const [snackInfo, setSnackInfo] = useState({ open: false, text: '', @@ -137,6 +139,7 @@ export default function CollectionCommentSection(props) { {reviews.map(r => { return ( <Comment + isCollection={false} rerenderCallback={forceUpdate} objectID={props.id} reviewID={r.id} @@ -148,6 +151,7 @@ export default function CollectionCommentSection(props) { description={r.description} createdAt={r.created_at} handleSnackbar={handleDeleteSnackbar} + handlePost={handlePostSnackbar} recurso={false} /> ); @@ -157,7 +161,8 @@ export default function CollectionCommentSection(props) { } useEffect(() => { - getRequest(`/collections/${props.id}/reviews`, (data) => { setReviews(data) }, (error) => { console.log(error) }) + setIsLoading(true) + getRequest(`/collections/${props.id}/reviews`, (data) => { setReviews(data); setIsLoading(false) }, (error) => { console.log(error); setIsLoading(false) }) }, [render_state]); return ( @@ -203,7 +208,14 @@ export default function CollectionCommentSection(props) { </LogInToComment> </Grid> } - {reviews.length ? CollectionComments() : NoCommentsMessage()} + { + is_loading ? + <LoadingDiv> + <CircularProgress className="loading" /> + </LoadingDiv> + : + reviews.length ? CollectionComments() : NoCommentsMessage() + } </CommentAreaCard> </Grid> <Snackbar @@ -230,6 +242,17 @@ export default function CollectionCommentSection(props) { ); } +const LoadingDiv = styled.div` + margin: 1em; + display: flex; + justify-content: center; + align-items: center; + .loading{ + color: #673ab7; + size: 24px; + } +` + const LogInToComment = styled.div` display : flex; flex-direction : column; diff --git a/src/Components/Comment.js b/src/Components/Comment.js index 09b66d5ad2f83e4ad3f10994de899960ca4f1b49..2a77cb0cee1f6e44c0d4d5ba92e7c382ae1cb37c 100644 --- a/src/Components/Comment.js +++ b/src/Components/Comment.js @@ -16,13 +16,13 @@ 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} from 'react' -import {Store} from '../Store.js' +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'; -import {Link} from 'react-router-dom' -import {apiDomain} from '../env'; +import { Link } from 'react-router-dom' +import { apiDomain } from '../env'; import noAvatar from "../img/default_profile.png"; import Rating from '@material-ui/lab/Rating'; import StarBorderIcon from '@material-ui/icons/StarBorder'; @@ -31,9 +31,9 @@ import TextField from "@material-ui/core/TextField"; import Menu from '@material-ui/core/Menu'; import MenuItem from '@material-ui/core/MenuItem'; import ModalExcluir from './ModalExcluirComentario.js' -import {putRequest, deleteRequest} from './HelperFunctions/getAxiosConfig' +import { putRequest, deleteRequest } from './HelperFunctions/getAxiosConfig' -export default function Comment (props) { +export default function Comment(props) { /* Required props: @@ -52,7 +52,7 @@ export default function Comment (props) { */ var moment = require('moment') - const {state} = useContext(Store) + const { state } = useContext(Store) const [displayedComment, setDisplayedComment] = useState(props.description) const [editando, setEditando] = useState(false) const [anchorEl, setAnchorEl] = React.useState(null); @@ -65,47 +65,57 @@ export default function Comment (props) { const [modalOpen, toggleModal] = useState(false) const [comment, setComment] = useState({ - error : false, - value : props.description + error: false, + value: props.description }) const handleChange = (e) => { const userInput = e.target.value const flag = (userInput.length === 0 ? true : false); - setComment({...comment, error : flag, value : userInput}) + setComment({ ...comment, error: flag, value: userInput }) } - function handleOnSuccessfulComment (data) { + function handleOnSuccessfulComment(data) { setDisplayedComment(comment.value) setEditando(false) - props.handleSnackbar(2) + props.handlePost() } const updateComment = () => { const finalComment = comment + let url; + + if (props.isCollection) + url = `/collections/${props.objectID}/reviews/${props.reviewID}` + else + url = `/learning_objects/${props.objectID}/reviews/${props.reviewID}` + if (!finalComment.error) { let payload = { - "review" : { - "name":null, - "description":finalComment.value, - "pros":null, - "cons":null, - "review_ratings_attributes" : props.reviewRatings + "review": { + "description": finalComment.value, + "review_ratings_attributes": props.reviewRatings } } - putRequest(`/learning_objects/${props.objectID}/reviews/`, payload, handleOnSuccessfulComment, (error) => {console.log(error)}) + putRequest(url, payload, handleOnSuccessfulComment, (error) => { console.log(error) }) } } - function handleSuccessDeleteComment (data) { + function handleSuccessDeleteComment(data) { props.rerenderCallback() - props.handleSnackbar(3) + props.handleSnackbar() } const deleteComment = () => { + let url; - deleteRequest(`/learning_objects/${props.objectID}/reviews/${props.reviewID}`, handleSuccessDeleteComment, (error) => {console.log(error)}) + if (props.isCollection) + url = `/collections/${props.objectID}/reviews/${props.reviewID}` + else + url = `/learning_objects/${props.objectID}/reviews/${props.reviewID}` + + deleteRequest(url, handleSuccessDeleteComment, (error) => { console.log(error) }) toggleModal(false) @@ -113,113 +123,112 @@ export default function Comment (props) { return ( <React.Fragment> - <ModalExcluir - open={modalOpen} handleClose={() => {toggleModal(false)}} - handleConfirm={deleteComment} + <ModalExcluir + open={modalOpen} handleClose={() => { toggleModal(false) }} + handleConfirm={deleteComment} /> - <Grid container style={{paddingLeft : "20px"}}> - - <Grid item xs={1}> - { - props.authorID && - <AvatarDiv> - <Link to={'/usuario-publico/' + props.authorID}> - <img src={props.authorAvatar ? apiDomain + props.authorAvatar : noAvatar} alt="author avatar"/> - </Link> - </AvatarDiv> - } - </Grid> - - <Grid item xs={10}> - <Comentario> - <div className="star-rating-container"> - <Rating - name="read-only" - value={props.rating} - readOnly - size="small" - style={{color:"#666"}} - emptyIcon={<StarBorderIcon fontSize="inherit" style={{color : "#a5a5a5"}} />} - /> - </div> + <Grid container style={{ paddingLeft: "20px" }}> + <Grid item xs={1}> { - props.name && - <strong>{props.name}</strong> + props.authorID && + <AvatarDiv> + <Link to={'/usuario-publico/' + props.authorID}> + <img src={props.authorAvatar ? apiDomain + props.authorAvatar : noAvatar} alt="author avatar" /> + </Link> + </AvatarDiv> } + </Grid> + <Grid item xs={10}> + <Comentario> + <div className="star-rating-container"> + <Rating + name="read-only" + value={props.rating} + readOnly + size="small" + style={{ color: "#666" }} + emptyIcon={<StarBorderIcon fontSize="inherit" style={{ color: "#a5a5a5" }} />} + /> + </div> - <div> { - editando ? - ( - <React.Fragment> - <div style={{marginTop : "5%", padding : "2px"}}> - <StyledTextField - colecao={!props.recurso} - id = "input-comentario" - label = {"Editar Comentário"} - margin = "normal" - value = {comment.value} - multiline={true} - rows="5" - onChange = {(e) => {handleChange(e)}} - style={{width:"100%"}} - /> - </div> - <div style={{float : "right"}}> - <StyledButton - style={props.recurso ? {backgroundColor : "#ff7f00"} : {backgroundColor : "#673ab7"}} - onClick={() => {setEditando(false)}} - > - Fechar - </StyledButton> - <StyledButton - style={props.recurso ? {backgroundColor : "#ff7f00"} : {backgroundColor : "#673ab7"}} - onClick={() => updateComment()} - > - Salvar + props.name && + <strong>{props.name}</strong> + } + + <div> + { + editando ? + ( + <React.Fragment> + <div style={{ marginTop: "5%", padding: "2px" }}> + <StyledTextField + colecao={!props.recurso} + id="input-comentario" + label={"Editar Comentário"} + margin="normal" + value={comment.value} + multiline={true} + rows="5" + onChange={(e) => { handleChange(e) }} + style={{ width: "100%" }} + /> + </div> + <div style={{ float: "right" }}> + <StyledButton + style={props.recurso ? { backgroundColor: "#ff7f00" } : { backgroundColor: "#673ab7" }} + onClick={() => { setEditando(false) }} + > + Fechar </StyledButton> - </div> - </React.Fragment> - ) - : - ( - <React.Fragment> - <p> - { - props.authorID && - <Link - to={'/usuario-publico/' + props.authorID} - style={{ - fontWeight : "bolder", - color : props.recurso ? "#ff7f00" : "#673ab7" - }} + <StyledButton + style={props.recurso ? { backgroundColor: "#ff7f00" } : { backgroundColor: "#673ab7" }} + onClick={() => updateComment()} > - {props.authorName} - </Link> - } + Salvar + </StyledButton> + </div> + </React.Fragment> + ) + : + ( + <React.Fragment> + <p> + { + props.authorID && + <Link + to={'/usuario-publico/' + props.authorID} + style={{ + fontWeight: "bolder", + color: props.recurso ? "#ff7f00" : "#673ab7" + }} + > + {props.authorName} + </Link> + } : {displayedComment} - </p> - { - props.authorID !== state.currentUser.id && - <span className="date"> - {moment(props.createdAt).format("DD/MM/YYYY")} - </span> - } - </React.Fragment> - ) - } - </div> - - </Comentario> - </Grid> + </p> + { + props.authorID !== state.currentUser.id && + <span className="date"> + {moment(props.createdAt).format("DD/MM/YYYY")} + </span> + } + </React.Fragment> + ) + } + </div> + + </Comentario> + </Grid> - { - props.authorID === state.currentUser.id && - <Grid item xs={1}> - <StyledDiv> - <Button onClick={handleClick}><EditIcon/></Button> + { + props.authorID === state.currentUser.id && + <Grid item xs={1}> + <StyledDiv> + <Button onClick={handleClick}><EditIcon /></Button> <Menu id="simple-menu" anchorEl={anchorEl} @@ -227,13 +236,13 @@ export default function Comment (props) { open={Boolean(anchorEl)} onClose={handleClose} > - <MenuItem onClick={() => {setEditando(true); handleClose()}}>Editar</MenuItem> - <MenuItem onClick={() => {toggleModal(true);handleClose()}}>Excluir</MenuItem> + <MenuItem onClick={() => { setEditando(true); handleClose() }}>Editar</MenuItem> + <MenuItem onClick={() => { toggleModal(true); handleClose() }}>Excluir</MenuItem> </Menu> - </StyledDiv> - </Grid> - } - </Grid> + </StyledDiv> + </Grid> + } + </Grid> </React.Fragment> ) } diff --git a/src/Components/FollowCollectionButton.js b/src/Components/FollowCollectionButton.js index dd9bf54215b5b23c97e2507680a5473645063526..e89f8901c0e586124c99df453dc70ac627027f63 100644 --- a/src/Components/FollowCollectionButton.js +++ b/src/Components/FollowCollectionButton.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, useEffect, useContext } from 'react'; +import React, { useState, useEffect } from 'react'; import Button from '@material-ui/core/Button'; import CheckIcon from '@material-ui/icons/Check'; import AddIcon from '@material-ui/icons/Add'; diff --git a/src/Components/ResourcePageComponents/CommentsArea.js b/src/Components/ResourcePageComponents/CommentsArea.js index 946ce4d4fc3e276b95e673a742b58a973f6fe065..37db3024dfaf7c41c6d0f54976d9e74bef267cca 100644 --- a/src/Components/ResourcePageComponents/CommentsArea.js +++ b/src/Components/ResourcePageComponents/CommentsArea.js @@ -16,34 +16,36 @@ 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 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 {apiDomain} from '../../env'; +import { apiDomain } from '../../env'; import CommentForm from './CommentForm.js' import Comment from '../Comment.js' -import {getRequest} from '../HelperFunctions/getAxiosConfig' +import { getRequest } from '../HelperFunctions/getAxiosConfig' import LoginModal from './../LoginModal.js' import Snackbar from '@material-ui/core/Snackbar'; import SignUpModal from './../SignUpModal' import MuiAlert from '@material-ui/lab/Alert'; +import CircularProgress from '@material-ui/core/CircularProgress'; function Alert(props) { return <MuiAlert elevation={6} variant="filled" {...props} />; } -export default function CommentsArea (props) { - const {state} = useContext(Store) +export default function CommentsArea(props) { + const { state } = useContext(Store) const [comentarios, setComentarios] = useState([]) const [gambiarra, setState] = useState(0) - const forceUpdate = () => {setState(gambiarra + 1)} + const forceUpdate = () => { setState(gambiarra + 1) } const [loginOpen, setLogin] = useState(false) const [successfulLoginOpen, handleSuccessfulLogin] = useState(false) const [signUpOpen, setSignUp] = useState(false) + const [isLoading, setIsLoading] = useState(false) const handleSignUp = () => { setSignUp(!signUpOpen) @@ -57,18 +59,19 @@ export default function CommentsArea (props) { if (reason === 'clickaway') { return; } - - handleSuccessfulLogin(false); + + handleSuccessfulLogin(false); } - function handleSuccess (data) { + function handleSuccess(data) { + setIsLoading(false) setComentarios(data.sort((a, b) => a.updated_at > b.updated_at ? -1 : 1)) } - useEffect( () => { + useEffect(() => { + setIsLoading(true) const url = `/learning_objects/${props.recursoId}/reviews` - - getRequest(url, handleSuccess, (error) => {console.log(error)}) + getRequest(url, handleSuccess, (error) => { console.log(error); setIsLoading(false) }) }, [gambiarra]) return ( @@ -83,17 +86,17 @@ export default function CommentsArea (props) { openSnackbar={() => { handleSuccessfulLogin(true) }} /> <SignUpModal open={signUpOpen} handleClose={handleSignUp} openLogin={handleLogin} /> - {/*----------------------------------------------------------------------------*/} - <Grid container spacing={2} style={{padding : "10px"}}> + {/*----------------------------------------------------------------------------*/} + <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.avatar} className="minha-imagem" alt="user avatar"/> + <Grid container style={{ paddingTop: "20px" }}> + <Grid item xs={2} style={{ paddingLeft: "15px", paddingRight: "15px" }}> + <img src={apiDomain + state.currentUser.avatar} className="minha-imagem" alt="user avatar" /> </Grid> <Grid item xs={10}> <CommentForm @@ -101,70 +104,86 @@ export default function CommentsArea (props) { handleSnackbar={props.handleSnackbar} rerenderCallback={forceUpdate} recurso={props.recurso} - /> + /> </Grid> </Grid> </GrayContainer> </Grid> - ) - : - ( + ) + : + ( <Grid item xs={12}> <LogInToComment> <span className="span-laranja">Você precisa entrar para comentar</span> - <Button onClick={() => handleLogin(true)} style={{textTransform : "uppercase", color : "#666", fontWeight : "700"}}> - <ExitToAppIcon/>ENTRAR + <Button onClick={() => handleLogin(true)} style={{ textTransform: "uppercase", color: "#666", fontWeight: "700" }}> + <ExitToAppIcon />ENTRAR </Button> </LogInToComment> </Grid> - ) + ) } { - comentarios.length !== 0 ? - ( + isLoading ? + <LoadingDiv> + <CircularProgress className="loading" /> + </LoadingDiv> + : + 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> + comentarios.map(comentario => + <div className="comentario-template" key={comentario.id}> + <Comment + isCollection={false} + 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 alt="" 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. + ) + : + ( + <Grid item xs={12}> + <LogInToComment> + <img alt="" 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> - ) + </LogInToComment> + </Grid> + ) } </Grid> </React.Fragment> ) } +const LoadingDiv = styled.div` + margin: 1em; + display: flex; + justify-content: center; + align-items: center; + .loading{ + color: #ff7f00; + size: 24px; + } +` const ComentariosBox = styled.div` display : flex; @@ -221,18 +240,15 @@ const GrayContainer = styled.div` display : flex; flex-direction : column; justify-content : space-between; -<<<<<<< HEAD font-size : 14px; padding-bottom : 20px; @media screen and (min-width : 990px) { padding-right : 15px; padding-left : 15px; } -======= padding-right : 15px; padding-left : 15px; padding-bottom : 20px; ->>>>>>> fead909286087ce07b01b25f6d8f46f74dc494c8 h3 { font-family : 'Roboto Light','Roboto Regular',Roboto;