Add Front-End for Comments/Ratings and half Subjects
commit
21c6bffdeb
|
|
@ -0,0 +1,18 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
|
import '../../styles/index.scss'
|
||||||
|
|
||||||
|
const AdminPanel = ({ user }) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
user: state.user,
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, null)(AdminPanel)
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
|
import '../../styles/index.scss'
|
||||||
|
|
||||||
|
const IndexExchange = ({ user }) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
user: state.user,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
export default connect(mapStateToProps,null)(IndexExchange)
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
|
import { getCommentRatings, updateComment } from '../../stores/comments/duck/operations'
|
||||||
|
import { refreshSubjectComments } from '../../stores/subjects/duck/operations'
|
||||||
|
|
||||||
|
import actions from '../../stores/subjects/duck/actions'
|
||||||
|
|
||||||
|
import '../../styles/indexForum.scss'
|
||||||
|
|
||||||
|
const ForumCommentUpdate = ({
|
||||||
|
user,
|
||||||
|
subjects, refreshSubjectComments, deactivate,
|
||||||
|
comment, comments, updateComment, getCommentRatings,
|
||||||
|
thisComment }) => {
|
||||||
|
|
||||||
|
const updateCommentTextArea = React.createRef()
|
||||||
|
|
||||||
|
const updateOldComment = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
if ( updateCommentTextArea.current.value !== '' ) {
|
||||||
|
let commentData = {
|
||||||
|
id: comment.id,
|
||||||
|
token: user.token,
|
||||||
|
text: updateCommentTextArea.current.value
|
||||||
|
}
|
||||||
|
updateCommentTextArea.current.value = ''
|
||||||
|
updateComment(commentData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [commentText, setCommentText] = useState(0)
|
||||||
|
|
||||||
|
if ( thisComment.isActive === true && thisComment.comment_id === comment.id) {
|
||||||
|
return (
|
||||||
|
<div className='forumFormComment'>
|
||||||
|
<form onSubmit={ updateOldComment }>
|
||||||
|
<textarea
|
||||||
|
name='addCommentText'
|
||||||
|
placeholder={ comment.text }
|
||||||
|
ref={ updateCommentTextArea }
|
||||||
|
cols='150'
|
||||||
|
maxLength='1000'
|
||||||
|
onChange={ e => setCommentText( e.target.value.length ) }>
|
||||||
|
</textarea>
|
||||||
|
<p>{commentText}/1000</p>
|
||||||
|
<button>
|
||||||
|
Update Comment
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div className='forumHiddenDiv'>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
user: state.user,
|
||||||
|
subjects: state.subjects,
|
||||||
|
comments: state.comments
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
updateComment: comments => dispatch( updateComment(comments) ),
|
||||||
|
getCommentRatings: comments => dispatch( getCommentRatings(comments) ),
|
||||||
|
refreshSubjectComments: subjects => dispatch( refreshSubjectComments(subjects) ),
|
||||||
|
|
||||||
|
deactivate: () => dispatch( actions.deactivate() )
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(ForumCommentUpdate)
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
|
import { getCommentRatings, addComment, deleteComment } from '../../stores/comments/duck/operations'
|
||||||
|
import { refreshSubjectComments } from '../../stores/subjects/duck/operations'
|
||||||
|
|
||||||
|
import actions from '../../stores/subjects/duck/actions'
|
||||||
|
|
||||||
|
import '../../styles/indexForum.scss'
|
||||||
|
|
||||||
|
import ForumRatings from './forumRatings'
|
||||||
|
import ForumCommentUpdate from './forumCommentUpdate'
|
||||||
|
|
||||||
|
const ForumComments = ({
|
||||||
|
user,
|
||||||
|
subjects, refreshSubjectComments, deactivate,
|
||||||
|
comments, addComment, deleteComment, getCommentRatings }) => {
|
||||||
|
|
||||||
|
useEffect( () => { getCommentRatings(subjects.commentsList) }, [])
|
||||||
|
|
||||||
|
const [updateFormDiv, setUpdateFormDiv] = useState( { isActive: false, comment_id: -1 } )
|
||||||
|
const [formDiv, setFormDiv] = useState(false)
|
||||||
|
|
||||||
|
const addCommentTextArea = React.createRef()
|
||||||
|
const updateCommentTextArea = React.createRef()
|
||||||
|
|
||||||
|
const addNewComment = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
if ( addCommentTextArea.current.value !== '' ) {
|
||||||
|
let newComment = {
|
||||||
|
text: addCommentTextArea.current.value,
|
||||||
|
subject_id: subjects.actualSubjectID,
|
||||||
|
user_id: user.id,
|
||||||
|
token: user.token
|
||||||
|
}
|
||||||
|
addCommentTextArea.current.value = ''
|
||||||
|
addComment(newComment)
|
||||||
|
setFormDiv( !formDiv )
|
||||||
|
let actualSubject = {
|
||||||
|
id: subjects.actualSubjectID
|
||||||
|
}
|
||||||
|
refreshSubjectComments(actualSubject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteOldComment = (commentID) => {
|
||||||
|
let delComment = {
|
||||||
|
id: commentID,
|
||||||
|
token: user.token
|
||||||
|
}
|
||||||
|
deleteComment(delComment)
|
||||||
|
let actualSubject = {
|
||||||
|
id: subjects.actualSubjectID
|
||||||
|
}
|
||||||
|
refreshSubjectComments(actualSubject)
|
||||||
|
}
|
||||||
|
|
||||||
|
const [commentText, setCommentText] = useState(0)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className='forumTitle'>
|
||||||
|
<p>Subject:</p>
|
||||||
|
<p>{subjects.actualSubjectName}</p>
|
||||||
|
<button onClick={ () => deactivate() }>
|
||||||
|
Back to subjects
|
||||||
|
</button>
|
||||||
|
<p>author {subjects.actualSubjectAuthor}</p>
|
||||||
|
</div>
|
||||||
|
<div className='forumItemsList'>
|
||||||
|
{ subjects.commentsList.map( comment =>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
className={comment.author_privilige === 3 ? 'forumListComment adminDivColor' :
|
||||||
|
(comment.author_privilige === 2 ? 'forumListComment moderDivColor' : 'forumListComment') }
|
||||||
|
key={comment.id}>
|
||||||
|
<div className='commentAvatar'>
|
||||||
|
<img src={comment.author_avatar} />
|
||||||
|
<p>{comment.author}</p>
|
||||||
|
{ ( user.id === comment.user_id || user.privilige > 1 ) ? (
|
||||||
|
<div>
|
||||||
|
<button onClick={ () => setUpdateFormDiv( { isActive: !updateFormDiv.isActive, comment_id: comment.id } ) }>
|
||||||
|
{ updateFormDiv.isActive ? 'Close Edit' : 'Edit Comment'}
|
||||||
|
</button>
|
||||||
|
{ subjects.commentsList[0].id === comment.id ?
|
||||||
|
(
|
||||||
|
<div></div>
|
||||||
|
) : (
|
||||||
|
<button onClick={ () => deleteOldComment(comment.id) }>
|
||||||
|
Delete Comment
|
||||||
|
</button>
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div></div>
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
<div className='commentText'>
|
||||||
|
<p>{comment.text}</p>
|
||||||
|
</div>
|
||||||
|
<div className='commentRating'>
|
||||||
|
<ForumRatings comment={comment} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ForumCommentUpdate comment={comment} thisComment={updateFormDiv} />
|
||||||
|
</div>
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
<div className={ formDiv === true ? 'forumFormComment' : 'forumHiddenDiv' }>
|
||||||
|
<form onSubmit={ addNewComment }>
|
||||||
|
<textarea
|
||||||
|
name='addCommentText'
|
||||||
|
placeholder='Write a comment'
|
||||||
|
ref={addCommentTextArea}
|
||||||
|
cols='150'
|
||||||
|
maxLength='1000'
|
||||||
|
onChange={ e => setCommentText( e.target.value.length )}>
|
||||||
|
</textarea>
|
||||||
|
<p>{commentText}/1000</p>
|
||||||
|
<button>
|
||||||
|
Add Comment
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div className='forumFoot'>
|
||||||
|
<button onClick={ () => setFormDiv( !formDiv ) }>
|
||||||
|
{ formDiv === true ? 'Close Add Comment' : 'Add Comment' }
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
user: state.user,
|
||||||
|
subjects: state.subjects,
|
||||||
|
comments: state.comments
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
addComment: comments => dispatch( addComment(comments) ),
|
||||||
|
deleteComment: comments => dispatch( deleteComment(comments) ),
|
||||||
|
getCommentRatings: comments => dispatch( getCommentRatings(comments) ),
|
||||||
|
refreshSubjectComments: subjects => dispatch( refreshSubjectComments(subjects) ),
|
||||||
|
|
||||||
|
deactivate: () => dispatch( actions.deactivate() )
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(ForumComments)
|
||||||
|
|
@ -0,0 +1,186 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
|
import { getCommentRatings, addRatingComment, updateRatingComment } from '../../stores/comments/duck/operations'
|
||||||
|
import actions from '../../stores/subjects/duck/actions'
|
||||||
|
|
||||||
|
import '../../styles/forumRatings.scss'
|
||||||
|
|
||||||
|
const ForumRatings = ({
|
||||||
|
user, subjects, deactivate,
|
||||||
|
comments, getCommentRatings,
|
||||||
|
addRatingComment, updateRatingComment,
|
||||||
|
comment }) => {
|
||||||
|
|
||||||
|
useEffect( () => { getCommentRatings(subjects.commentsList) }, [])
|
||||||
|
|
||||||
|
let commentRatingsAvg = (commentID) => {
|
||||||
|
for (let comment in Object.entries(subjects.commentsList)) {
|
||||||
|
if (commentID === subjects.commentsList[comment].id)
|
||||||
|
return parseInt(subjects.commentsList[comment].ratings_avg.value__avg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let getUserRating = (commentID) => {
|
||||||
|
let userRating = 0
|
||||||
|
for (let comment = 0; comment < comments.ratingsCommentList.length; comment++)
|
||||||
|
for (let rating = 0; rating < comments.ratingsCommentList[comment].length; rating++) {
|
||||||
|
if ((+comments.ratingsCommentList[comment][rating].user_id) === (+user.id)) {
|
||||||
|
if ((+comments.ratingsCommentList[comment][rating].comment_id) === (+commentID)) {
|
||||||
|
userRating = comments.ratingsCommentList[comment][rating].value
|
||||||
|
return userRating
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
let getRatingID = (commentID) => {
|
||||||
|
let userRatingID = 0
|
||||||
|
for (let comment = 0; comment < comments.ratingsCommentList.length; comment++)
|
||||||
|
for (let rating = 0; rating < comments.ratingsCommentList[comment].length; rating++) {
|
||||||
|
if ((+comments.ratingsCommentList[comment][rating].user_id) === (+user.id)) {
|
||||||
|
if ((+comments.ratingsCommentList[comment][rating].comment_id) === (+commentID)) {
|
||||||
|
userRatingID = comments.ratingsCommentList[comment][rating].id
|
||||||
|
return userRatingID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
const [newRatingValue, setValue] = useState(0)
|
||||||
|
|
||||||
|
const changeRatingValue = (event, commentID) => {
|
||||||
|
|
||||||
|
let ratingDiv = document.getElementById('rate' + commentID)
|
||||||
|
let divYPositionOnPage = ratingDiv.getBoundingClientRect().top + 72
|
||||||
|
let yPosition = event.screenY - divYPositionOnPage
|
||||||
|
|
||||||
|
if ( yPosition > 200 ) {
|
||||||
|
setValue(5)
|
||||||
|
}
|
||||||
|
else if ( yPosition > 150 && yPosition < 200 ) {
|
||||||
|
setValue(4)
|
||||||
|
}
|
||||||
|
else if ( yPosition > 100 && yPosition < 150 ) {
|
||||||
|
setValue(3)
|
||||||
|
}
|
||||||
|
else if ( yPosition > 50 && yPosition < 150 ) {
|
||||||
|
setValue(2)
|
||||||
|
}
|
||||||
|
else if ( yPosition > 0 && yPosition < 50 ) {
|
||||||
|
setValue(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [updateRating, setUpdate] = useState(false)
|
||||||
|
|
||||||
|
const updateUserRating = () => {
|
||||||
|
const data = {
|
||||||
|
'id': getRatingID(comment.id),
|
||||||
|
'value': newRatingValue,
|
||||||
|
'token': user.token
|
||||||
|
}
|
||||||
|
updateRatingComment(data)
|
||||||
|
setUpdate(false)
|
||||||
|
getCommentRatings(subjects.commentsList)
|
||||||
|
}
|
||||||
|
|
||||||
|
const addUserRating = () => {
|
||||||
|
const data = {
|
||||||
|
'user_id': user.id,
|
||||||
|
'comment_id': comment.id,
|
||||||
|
'value': newRatingValue,
|
||||||
|
'token': user.token
|
||||||
|
}
|
||||||
|
addRatingComment(data)
|
||||||
|
getCommentRatings(subjects.commentsList)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( getUserRating(comment.id) === 0 ) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
onClick={ () => addUserRating() }
|
||||||
|
onMouseOver={ event => changeRatingValue(event, comment.id) }
|
||||||
|
className='rating'>
|
||||||
|
<p>{ getUserRating(comment.id) === 0 ? newRatingValue : getUserRating(comment.id) }</p>
|
||||||
|
<div
|
||||||
|
id={'rate' + comment.id}
|
||||||
|
className={'ratingValue ratingValue' + ( getUserRating(comment.id) === 0 ? newRatingValue : getUserRating(comment.id))}>
|
||||||
|
<div className='ratingStick'></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='rating'>
|
||||||
|
<p>{ commentRatingsAvg(comment.id) }</p>
|
||||||
|
<div className={'ratingValue ratingValue' + commentRatingsAvg(comment.id) }>
|
||||||
|
<div className='ratingStick'></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if ( updateRating === false && getUserRating(comment.id) > 0 ) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
onClick={ () => setUpdate( !updateRating ) }
|
||||||
|
onMouseOver={ event => changeRatingValue(event, comment.id) }
|
||||||
|
className='rating'>
|
||||||
|
<p>{ getUserRating(comment.id) === 0 ? newRatingValue : getUserRating(comment.id) }</p>
|
||||||
|
<div
|
||||||
|
id={'rate' + comment.id}
|
||||||
|
className={'ratingValue ratingValue' + ( getUserRating(comment.id) === 0 ? newRatingValue : getUserRating(comment.id))}>
|
||||||
|
<div className='ratingStick'></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='rating'>
|
||||||
|
<p>{ commentRatingsAvg(comment.id) }</p>
|
||||||
|
<div className={'ratingValue ratingValue' + commentRatingsAvg(comment.id) }>
|
||||||
|
<div className='ratingStick'></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if ( updateRating === true ) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
onClick={ () => updateUserRating() }
|
||||||
|
onMouseOver={ event => changeRatingValue(event, comment.id) }
|
||||||
|
className='rating'>
|
||||||
|
<p>{ newRatingValue }</p>
|
||||||
|
<div
|
||||||
|
id={'rate' + comment.id}
|
||||||
|
className={'ratingValue ratingValue' + newRatingValue }>
|
||||||
|
<div className='ratingStick'></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='rating'>
|
||||||
|
<p>{ commentRatingsAvg(comment.id) }</p>
|
||||||
|
<div className={'ratingValue ratingValue' + commentRatingsAvg(comment.id) }>
|
||||||
|
<div className='ratingStick'></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
user: state.user,
|
||||||
|
subjects: state.subjects,
|
||||||
|
comments: state.comments
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
getCommentRatings: comments => dispatch( getCommentRatings(comments) ),
|
||||||
|
addRatingComment: comments => dispatch( addRatingComment(comments) ),
|
||||||
|
updateRatingComment: comments => dispatch( updateRatingComment(comments) ),
|
||||||
|
|
||||||
|
deactivate: () => dispatch( actions.deactivate() )
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(ForumRatings)
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
|
import { refreshThreadSubjects } from '../../stores/threads/duck/operations'
|
||||||
|
import { getSubjectComments, addSubject } from '../../stores/subjects/duck/operations'
|
||||||
|
import { addComment } from '../../stores/comments/duck/operations'
|
||||||
|
import actions from '../../stores/threads/duck/actions'
|
||||||
|
|
||||||
|
import '../../styles/indexForum.scss'
|
||||||
|
|
||||||
|
import ForumComments from './forumComments'
|
||||||
|
|
||||||
|
const ForumSubjects = ({
|
||||||
|
user,
|
||||||
|
threads, deactivate,
|
||||||
|
subjects, addSubject, getSubjectComments,
|
||||||
|
comments, addComment }) => {
|
||||||
|
|
||||||
|
const [formDiv, setFormDiv] = useState(false)
|
||||||
|
|
||||||
|
const addSubjectTitle = React.createRef()
|
||||||
|
const addSubjectComment = React.createRef()
|
||||||
|
|
||||||
|
const addNewSubject = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
if ( addSubjectTitle.current.value !== '' && addSubjectComment.current.value !== '' ) {
|
||||||
|
let newSubject = {
|
||||||
|
name: addSubjectTitle.current.value,
|
||||||
|
user_id: user.id,
|
||||||
|
thread_id: threads.actualThreadID,
|
||||||
|
comment: {
|
||||||
|
text: addSubjectComment.current.value,
|
||||||
|
user_id: user.id,
|
||||||
|
token: user.token
|
||||||
|
},
|
||||||
|
token: user.token
|
||||||
|
}
|
||||||
|
addSubject(newSubject)
|
||||||
|
addSubjectComment.current.value = ''
|
||||||
|
addSubjectTitle.current.value = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [commentText, setCommentText] = useState(0)
|
||||||
|
const [titleText, setTitleText] = useState(0)
|
||||||
|
|
||||||
|
if (threads.isActive === true && subjects.isActive === false) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className='forumTitle'>
|
||||||
|
<p>Subjects in thread:</p>
|
||||||
|
<p>{threads.actualThreadName} </p>
|
||||||
|
<button onClick={ () => deactivate() }>
|
||||||
|
Back to Threads
|
||||||
|
</button>
|
||||||
|
<p>moderator {threads.actualThreadModerator}</p>
|
||||||
|
</div>
|
||||||
|
<div className='forumItemsList'>
|
||||||
|
{ threads.subjectsList.map( subject =>
|
||||||
|
<div
|
||||||
|
className={subject.author_privilige === 3 ? 'forumListItem adminDivColor' :
|
||||||
|
(subject.author_privilige === 2 ? 'forumListItem moderDivColor' : 'forumListItem') }
|
||||||
|
key={subject.id}>
|
||||||
|
<p onClick={ () => getSubjectComments(subject) }>
|
||||||
|
{subject.name}
|
||||||
|
</p>
|
||||||
|
<div></div>
|
||||||
|
{ (user.id === subject.user_id ||
|
||||||
|
user.id === threads.actualThreadModeratorID ||
|
||||||
|
user.privilige === 3) ? (
|
||||||
|
<div>
|
||||||
|
<button>
|
||||||
|
Edit Title
|
||||||
|
</button>
|
||||||
|
<button>
|
||||||
|
Delete Subject
|
||||||
|
</button>
|
||||||
|
<img src={subject.author_avatar} />
|
||||||
|
<p>{subject.author}</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<img src={subject.author_avatar} />
|
||||||
|
<p>{subject.author}</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
<div className={ formDiv === true ? 'forumFormSubject' : 'forumHiddenDiv' }>
|
||||||
|
<form onSubmit={addNewSubject}>
|
||||||
|
<input
|
||||||
|
name='addSubjectTitle'
|
||||||
|
placeholder='Write a subject title'
|
||||||
|
ref={addSubjectTitle}
|
||||||
|
maxLength='30'
|
||||||
|
onChange={ e => setTitleText(e.target.value.length) }>
|
||||||
|
</input>
|
||||||
|
<textarea
|
||||||
|
name='addCommentText'
|
||||||
|
placeholder='Write a first comment'
|
||||||
|
cols='150'
|
||||||
|
ref={addSubjectComment}
|
||||||
|
maxLength='1000'
|
||||||
|
onChange={ e => setCommentText(e.target.value.length) }>
|
||||||
|
</textarea>
|
||||||
|
<p>Title: {titleText}/30</p>
|
||||||
|
<p>Comment: {commentText}/1000</p>
|
||||||
|
<button>
|
||||||
|
Add Subject
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div className='forumFoot'>
|
||||||
|
<button onClick={ () => setFormDiv( !formDiv ) }>
|
||||||
|
{ formDiv === true ? 'Close Add Subject' : 'Add Subject' }
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if (threads.isActive === true && subjects.isActive === true) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<ForumComments />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
user: state.user,
|
||||||
|
threads: state.threads,
|
||||||
|
subjects: state.subjects,
|
||||||
|
comments: state.comments
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
refreshThreadSubjects: threads => dispatch( refreshThreadSubjects(threads) ),
|
||||||
|
getSubjectComments: subjects => dispatch( getSubjectComments(subjects) ),
|
||||||
|
addSubject: subjects => dispatch( addSubject(subjects) ),
|
||||||
|
addComment: comments => dispatch( addComment(comments) ),
|
||||||
|
|
||||||
|
deactivate: () => dispatch( actions.deactivate() )
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(ForumSubjects)
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
import React, { useEffect } from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
|
import { getAllThreads, getThreadSubjects } from '../../stores/threads/duck/operations'
|
||||||
|
|
||||||
|
import '../../styles/indexForum.scss'
|
||||||
|
|
||||||
|
import ForumSubjects from './forumSubjects'
|
||||||
|
|
||||||
|
const IndexForum = ({ user, threads, getAllThreads, getThreadSubjects }) => {
|
||||||
|
|
||||||
|
useEffect( () => { getAllThreads() }, [] )
|
||||||
|
|
||||||
|
if (threads.isActive === false) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className='indexForumMarginTop'>
|
||||||
|
</div>
|
||||||
|
<div className='indexForum'>
|
||||||
|
<div className='forumTitle'>
|
||||||
|
<p>Forum:</p>
|
||||||
|
<p>Threads</p>
|
||||||
|
<p>Forum about BTC exchange</p>
|
||||||
|
</div>
|
||||||
|
<div className='forumItemsList'>
|
||||||
|
{ threads.threadsList.map( thread =>
|
||||||
|
<div
|
||||||
|
className={thread.moderator_privilige === 3 ? 'forumListItem adminDivColor' :
|
||||||
|
(thread.moderator_privilige === 2 ? 'forumListItem moderDivColor' : 'forumListItem') }
|
||||||
|
key={thread.id}
|
||||||
|
onClick={ () => getThreadSubjects(thread) }>
|
||||||
|
<p>{thread.name}</p>
|
||||||
|
<p>moderator: {thread.moderator}</p>
|
||||||
|
</div>
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
<div className='forumFoot'>
|
||||||
|
Foot
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='indexForumMarginTop'>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if (threads.isActive === true) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className='indexForumMarginTop'>
|
||||||
|
</div>
|
||||||
|
<div className='indexForum'>
|
||||||
|
<ForumSubjects />
|
||||||
|
</div>
|
||||||
|
<div className='indexForumMarginTop'>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
user: state.user,
|
||||||
|
threads: state.threads
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
getAllThreads: () => dispatch( getAllThreads() ),
|
||||||
|
getThreadSubjects: thread => dispatch( getThreadSubjects(thread) )
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(IndexForum)
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { getSubjectsThread } from '../stores/subjects/duck/operations'
|
||||||
|
|
||||||
|
import '../styles/index.scss'
|
||||||
|
|
||||||
|
const Index = ({subjects, getSubjectsThread}) =>{
|
||||||
|
|
||||||
|
useEffect( () => { getSubjectsThread() }, [])
|
||||||
|
|
||||||
|
return <ul>
|
||||||
|
{subjects.list.map(subject => <li>{subject}</li>)}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
|
||||||
|
// do odczytu globalnego state'a
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
subjects: state.subjects
|
||||||
|
})
|
||||||
|
|
||||||
|
// do modyfikacji globalnego state'a
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
getSubjectsThread: () => dispatch( getSubjectsThread() )
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(Index)
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import actions from '../stores/subjects/duck/actions'
|
||||||
|
|
||||||
|
const IndexForm = (props) => {
|
||||||
|
|
||||||
|
const subjectInput = React.createRef()
|
||||||
|
|
||||||
|
const addSubject = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
props.add(subjectInput.current.value)
|
||||||
|
|
||||||
|
subjectInput.current.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={addSubject}>
|
||||||
|
<input ref={subjectInput} />
|
||||||
|
<button type='submit'>Add Subject</button>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
add: subject => dispatch(actions.add(subject))
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps)(IndexForm)
|
||||||
|
|
@ -0,0 +1,324 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
|
// Operations Redux
|
||||||
|
|
||||||
|
import { createSession, deleteSession, updateSession, registerUser } from '../stores/user/duck/operations'
|
||||||
|
|
||||||
|
// Actions Redux
|
||||||
|
|
||||||
|
import actions from '../stores/movements/duck/actions'
|
||||||
|
|
||||||
|
// Styles
|
||||||
|
|
||||||
|
import '../styles/index.scss'
|
||||||
|
|
||||||
|
// Components
|
||||||
|
|
||||||
|
import MenuBar from './menuBar/menuBar'
|
||||||
|
|
||||||
|
import Exchange from './exchange/indexExchange'
|
||||||
|
import Forum from './forum/indexForum'
|
||||||
|
import AdminPanel from './admin/adminPanel'
|
||||||
|
|
||||||
|
// Images / Videos
|
||||||
|
|
||||||
|
import VideoEx from '../images/stockExchange.mp4'
|
||||||
|
import BtcLogo from '../images/BtcLogo.png'
|
||||||
|
import ForumLogo from '../images/ForumLogo.png'
|
||||||
|
|
||||||
|
const IndexInterface = ({
|
||||||
|
user, movements,
|
||||||
|
createSession, deleteSession, updateSession, registerUser,
|
||||||
|
setRegister, setEdit, setForum, setExchange, setAdminPanel, resetMovements}) => {
|
||||||
|
|
||||||
|
const loginInput = React.createRef()
|
||||||
|
const passwordInput = React.createRef()
|
||||||
|
|
||||||
|
const userLogin = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
let userInput = {
|
||||||
|
login: loginInput.current.value,
|
||||||
|
password: passwordInput.current.value
|
||||||
|
}
|
||||||
|
loginInput.current.value = ''
|
||||||
|
passwordInput.current.value = ''
|
||||||
|
createSession(userInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
const userLogout = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
let userToken = {
|
||||||
|
token: user.token
|
||||||
|
}
|
||||||
|
deleteSession(userToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
const loginRegister = React.createRef()
|
||||||
|
const passOneRegister = React.createRef()
|
||||||
|
const passTwoRegister = React.createRef()
|
||||||
|
const emailRegister = React.createRef()
|
||||||
|
|
||||||
|
const userRegister = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
if (passOneRegister.current.value === passTwoRegister.current.value) {
|
||||||
|
let userRegister = {
|
||||||
|
login: loginRegister.current.value,
|
||||||
|
password: passOneRegister.current.value,
|
||||||
|
email: emailRegister.current.value
|
||||||
|
}
|
||||||
|
registerUser(userRegister)
|
||||||
|
}
|
||||||
|
loginRegister.current.value = ''
|
||||||
|
passOneRegister.current.value = ''
|
||||||
|
passTwoRegister.current.value = ''
|
||||||
|
emailRegister.current.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const loginUpdate = React.createRef()
|
||||||
|
const passOldOneUpdate = React.createRef()
|
||||||
|
const passOldTwoUpdate = React.createRef()
|
||||||
|
const passNewUpdate = React.createRef()
|
||||||
|
const emailUpdate = React.createRef()
|
||||||
|
const avatarUpdate = React.createRef()
|
||||||
|
|
||||||
|
const userUpdate = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
if ( passOldOneUpdate.current.value === passOldTwoUpdate.current.value ) {
|
||||||
|
let userUpdate = {
|
||||||
|
id: user.id,
|
||||||
|
login: loginUpdate.current.value === '' ? user.login : loginUpdate.current.value,
|
||||||
|
passwordOld: passOldOneUpdate.current.value,
|
||||||
|
passwordNew: passNewUpdate.current.value === '' ? passOldOneUpdate.current.value : passNewUpdate.current.value,
|
||||||
|
email: emailUpdate.current.value === '' ? user.email : emailUpdate.current.value,
|
||||||
|
avatar: avatarUpdate.current.value === '' ? user.avatar : avatarUpdate.current.value,
|
||||||
|
token: user.token
|
||||||
|
}
|
||||||
|
updateSession(userUpdate)
|
||||||
|
}
|
||||||
|
loginUpdate.current.value = ''
|
||||||
|
passOldOneUpdate.current.value = ''
|
||||||
|
passOldTwoUpdate.current.value = ''
|
||||||
|
passNewUpdate.current.value = ''
|
||||||
|
emailUpdate.current.value = ''
|
||||||
|
avatarUpdate.current.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.isActive === false && movements.register === false && movements.exchange === false){
|
||||||
|
return (
|
||||||
|
<div className='indexView'>
|
||||||
|
<video id='indexVideo' autoPlay muted loop>
|
||||||
|
<source src={VideoEx} type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
<div className="interface">
|
||||||
|
<div className='exchangeBtt' onClick={ () => setExchange() }>
|
||||||
|
<img src={BtcLogo} />
|
||||||
|
</div>
|
||||||
|
<div className='emptySpace'>
|
||||||
|
</div>
|
||||||
|
<div className='loginForm'>
|
||||||
|
<form onSubmit={userLogin}>
|
||||||
|
<input type='text' placeholder='Account' ref={loginInput}/>
|
||||||
|
<input type='password' placeholder='Password' ref={passwordInput}/>
|
||||||
|
<br /><br />
|
||||||
|
<button>
|
||||||
|
Log in
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<form>
|
||||||
|
<button onClick={ () => setRegister() }>
|
||||||
|
Register
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if (movements.register === true) {
|
||||||
|
return (
|
||||||
|
<div className='indexView'>
|
||||||
|
<video id='indexVideo' autoPlay muted loop>
|
||||||
|
<source src={VideoEx} type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
<div className="interface">
|
||||||
|
<div className='oneDivForm'>
|
||||||
|
<form onSubmit={userRegister}>
|
||||||
|
<input type='text' placeholder='Login' ref={loginRegister} />
|
||||||
|
<input type='password' placeholder='Password' ref={passOneRegister}/>
|
||||||
|
<input type='password' placeholder='Replace Password' ref={passTwoRegister}/>
|
||||||
|
<input type='text' placeholder='E-mail' ref={emailRegister}/>
|
||||||
|
<br /><br />
|
||||||
|
<button>
|
||||||
|
Register
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<button onClick={ () => resetMovements() }>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if (movements.edit === true) {
|
||||||
|
return (
|
||||||
|
<div className='indexView'>
|
||||||
|
<video id='indexVideo' autoPlay muted loop>
|
||||||
|
<source src={VideoEx} type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
<div className="interface">
|
||||||
|
<div className='oneDivForm'>
|
||||||
|
<form onSubmit={userUpdate}>
|
||||||
|
Login:
|
||||||
|
<input type='text' placeholder={user.login} ref={loginUpdate}/>
|
||||||
|
Old Password
|
||||||
|
<input type='password' placeholder='Password' ref={passOldOneUpdate}/>
|
||||||
|
<input type='password' placeholder='Replace Password' ref={passOldTwoUpdate}/>
|
||||||
|
New Password
|
||||||
|
<input type='password' placeholder='New Password' ref={passNewUpdate}/>
|
||||||
|
E-mail:
|
||||||
|
<input type='text' placeholder={user.email} ref={emailUpdate}/>
|
||||||
|
Avatar URL:
|
||||||
|
<input type='text' placeholder={user.avatar} ref={avatarUpdate}/>
|
||||||
|
<br /><br />
|
||||||
|
<button>
|
||||||
|
Update
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<button onClick={ () => resetMovements() }>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if (movements.exchange === true) {
|
||||||
|
return (
|
||||||
|
<div className='indexView'>
|
||||||
|
<video id='indexVideo' autoPlay muted loop>
|
||||||
|
<source src={VideoEx} type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
<div>
|
||||||
|
<MenuBar />
|
||||||
|
<Exchange />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if (movements.forum === true) {
|
||||||
|
return (
|
||||||
|
<div className='indexView'>
|
||||||
|
<video id='indexVideo' autoPlay muted loop>
|
||||||
|
<source src={VideoEx} type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
<div>
|
||||||
|
<MenuBar />
|
||||||
|
<Forum />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if (movements.adminPanel === true) {
|
||||||
|
return (
|
||||||
|
<div className='indexView'>
|
||||||
|
<video id='indexVideo' autoPlay muted loop>
|
||||||
|
<source src={VideoEx} type="video/mp4" />
|
||||||
|
</video >
|
||||||
|
<div>
|
||||||
|
<MenuBar />
|
||||||
|
<AdminPanel />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if (user.privilige === 3) {
|
||||||
|
return (
|
||||||
|
<div className='indexView'>
|
||||||
|
<video id='indexVideo' autoPlay muted loop>
|
||||||
|
<source src={VideoEx} type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
<div className="interface">
|
||||||
|
<div className='exchangeBtt' onClick={ () => setExchange() }>
|
||||||
|
<img src={BtcLogo} />
|
||||||
|
</div>
|
||||||
|
<div className='forumBtt' onClick={ () => setForum() }>
|
||||||
|
<img src={ForumLogo} />
|
||||||
|
</div>
|
||||||
|
<div className='loginForm'>
|
||||||
|
<form>
|
||||||
|
<p>Welcome</p>
|
||||||
|
<p>{user.login}</p>
|
||||||
|
<br />
|
||||||
|
</form>
|
||||||
|
<button onClick={ () => setAdminPanel() }>
|
||||||
|
Admin Panel
|
||||||
|
</button>
|
||||||
|
<button onClick={ () => setEdit() }>
|
||||||
|
Edit Account
|
||||||
|
</button>
|
||||||
|
<form onSubmit={userLogout}>
|
||||||
|
<button>
|
||||||
|
Log out
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (
|
||||||
|
<div className='indexView'>
|
||||||
|
<video id='indexVideo' autoPlay muted loop>
|
||||||
|
<source src={VideoEx} type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
<div className="interface">
|
||||||
|
<div className='exchangeBtt' onClick={ () => setExchange() }>
|
||||||
|
<img src={BtcLogo} />
|
||||||
|
</div>
|
||||||
|
<div className='forumBtt' onClick={ () => setForum() }>
|
||||||
|
<img src={ForumLogo} />
|
||||||
|
</div>
|
||||||
|
<div className='loginForm'>
|
||||||
|
<form>
|
||||||
|
<p>Welcome</p>
|
||||||
|
<p>{user.login}</p>
|
||||||
|
<br />
|
||||||
|
</form>
|
||||||
|
<button onClick={ () => setEdit()}>
|
||||||
|
Edit Account
|
||||||
|
</button>
|
||||||
|
<form onSubmit={userLogout}>
|
||||||
|
<button>
|
||||||
|
Log out
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
user: state.user,
|
||||||
|
movements: state.movements
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
createSession: user => dispatch( createSession(user) ),
|
||||||
|
deleteSession: user => dispatch( deleteSession(user) ),
|
||||||
|
updateSession: user => dispatch( updateSession(user) ),
|
||||||
|
registerUser: user => dispatch( registerUser(user) ),
|
||||||
|
|
||||||
|
setRegister: movements => dispatch( actions.register() ),
|
||||||
|
setEdit: movements => dispatch( actions.editAccount() ),
|
||||||
|
setExchange: movements => dispatch( actions.exchange() ),
|
||||||
|
setForum: movements => dispatch( actions.forum() ),
|
||||||
|
setAdminPanel: movements => dispatch( actions.adminPanel() ),
|
||||||
|
resetMovements: movements => dispatch( actions.reset() )
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(IndexInterface)
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
|
import { deleteSession } from '../../stores/user/duck/operations'
|
||||||
|
|
||||||
|
import actions from '../../stores/movements/duck/actions'
|
||||||
|
|
||||||
|
import '../../styles/menuBar.scss'
|
||||||
|
|
||||||
|
import BtcLogo from '../../images/BtcLogo.png'
|
||||||
|
|
||||||
|
const MenuBar = ({ user, movements, resetMovements, deleteSession }) => {
|
||||||
|
|
||||||
|
const [menuActive, setActivity] = useState(false)
|
||||||
|
|
||||||
|
const userLogout = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
let userToken = {
|
||||||
|
token: user.token
|
||||||
|
}
|
||||||
|
resetMovements()
|
||||||
|
deleteSession(userToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.isActive === true) {
|
||||||
|
return (
|
||||||
|
<div className={ menuActive === true ? 'menuBarActive' : 'menuBar' }>
|
||||||
|
<img src={BtcLogo} onClick={ () => setActivity( !menuActive ) } />
|
||||||
|
<div>
|
||||||
|
<button onClick={ () => resetMovements() }>
|
||||||
|
Back to Home
|
||||||
|
</button>
|
||||||
|
<form onSubmit={userLogout}>
|
||||||
|
<button>
|
||||||
|
Log out
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<p>{user.login}</p>
|
||||||
|
<p>{user.email}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (
|
||||||
|
<div className={ menuActive === true ? 'menuBarActive' : 'menuBar' }>
|
||||||
|
<img src={BtcLogo} onClick={ () => setActivity( !menuActive ) } />
|
||||||
|
<div>
|
||||||
|
<button onClick={ () => resetMovements() }>
|
||||||
|
Back to Home
|
||||||
|
</button>
|
||||||
|
<p>Welcome Guest!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
user: state.user,
|
||||||
|
movements: state.movements
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
deleteSession: user => dispatch( deleteSession(user) ),
|
||||||
|
resetMovements: movements => dispatch( actions.reset() )
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(MenuBar)
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import IndexInterface from "../components/indexInterface"
|
||||||
|
|
||||||
|
import store from "../stores/store";
|
||||||
|
import { Provider } from "react-redux";
|
||||||
|
|
||||||
|
import '../styles/general.scss'
|
||||||
|
|
||||||
|
const IndexPage = () => (
|
||||||
|
<Provider store={store}>
|
||||||
|
<IndexInterface />
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default IndexPage
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
import types from './types'
|
||||||
|
|
||||||
|
const getRatingsComment = item => ({
|
||||||
|
type: types.GET_COMMENTS_RATINGS, item
|
||||||
|
})
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getRatingsComment
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import commentReducer from './reducers'
|
||||||
|
export { default as commentTypes } from './types'
|
||||||
|
export { default as commentActions } from './actions'
|
||||||
|
|
||||||
|
export default commentReducer
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
import actions from './actions'
|
||||||
|
|
||||||
|
const fetchRatingsComment = async (comment) => {
|
||||||
|
const response = await
|
||||||
|
fetch ('http://localhost:8001/index/comment/' + comment.id + '/rating', {
|
||||||
|
method: 'GET',
|
||||||
|
credentials: 'same-origin'
|
||||||
|
});
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchAddRating = async (data) => {
|
||||||
|
fetch ('http://localhost:8001/index/comment/' + data.comment_id + '/rating', {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchUpdateRating = async (rating) => {
|
||||||
|
fetch ('http://localhost:8001/index/rating/' + rating.id, {
|
||||||
|
method: 'PUT',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify(rating)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getCommentRatings = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
let ratings = []
|
||||||
|
for(let x = 0; x < data.length; x++) {
|
||||||
|
const rating = await fetchRatingsComment(data[x])
|
||||||
|
for(let y = 0; y < rating.length; y++)
|
||||||
|
rating[y].userRating = 0
|
||||||
|
ratings[x] = rating
|
||||||
|
}
|
||||||
|
dispatch( actions.getRatingsComment(ratings) )
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addRatingComment = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
await fetchAddRating(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateRatingComment = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
await fetchUpdateRating(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchAddComment = async (data) => {
|
||||||
|
fetch ('http://localhost:8001/index/subject/' + data.subject_id + '/comment', {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchUpdateComment = async (data) => {
|
||||||
|
fetch ('http://localhost:8001/index/comment/' + data.id, {
|
||||||
|
method: 'PUT',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchDeleteComment = async (data) => {
|
||||||
|
fetch ('http://localhost:8001/index/comment/' + data.id, {
|
||||||
|
method: 'Delete',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addComment = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
await fetchAddComment(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateComment = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
await fetchUpdateComment(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deleteComment = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
await fetchDeleteComment(data)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import types from './types'
|
||||||
|
|
||||||
|
const INITIAL_STATE = {
|
||||||
|
ratingsCommentList: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
function commentReducer(state = INITIAL_STATE, action) {
|
||||||
|
switch(action.type) {
|
||||||
|
case types.GET_COMMENTS_RATINGS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
ratingsCommentList: action.item
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default commentReducer
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
const GET_COMMENTS_RATINGS = 'GET_COMMENTS_RATINGS'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
GET_COMMENTS_RATINGS
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
import types from './types'
|
||||||
|
|
||||||
|
const register = item => ({
|
||||||
|
type: types.REGISTER, item
|
||||||
|
})
|
||||||
|
|
||||||
|
const editAccount = item => ({
|
||||||
|
type: types.EDIT_ACCOUNT, item
|
||||||
|
})
|
||||||
|
|
||||||
|
const adminPanel = item => ({
|
||||||
|
type: types.ADMIN_PANEL, item
|
||||||
|
})
|
||||||
|
|
||||||
|
const exchange = item => ({
|
||||||
|
type: types.EXCHANGE, item
|
||||||
|
})
|
||||||
|
|
||||||
|
const forum = item => ({
|
||||||
|
type: types.FORUM, item
|
||||||
|
})
|
||||||
|
|
||||||
|
const reset = item => ({
|
||||||
|
type: types.RESET, item
|
||||||
|
})
|
||||||
|
|
||||||
|
export default {
|
||||||
|
register,
|
||||||
|
editAccount,
|
||||||
|
adminPanel,
|
||||||
|
exchange,
|
||||||
|
forum,
|
||||||
|
reset,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import movementsReducer from './reducers'
|
||||||
|
export { default as movemetsTypes } from './types'
|
||||||
|
export { default as movementsActions } from './actions'
|
||||||
|
|
||||||
|
export default movementsReducer
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
import types from './types'
|
||||||
|
|
||||||
|
const INITIAL_STATE = {
|
||||||
|
forum: false,
|
||||||
|
exchange: false,
|
||||||
|
edit: false,
|
||||||
|
register: false,
|
||||||
|
adminPanel: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
const movementsReducer = (state = INITIAL_STATE, action) => {
|
||||||
|
switch(action.type) {
|
||||||
|
case types.EXCHANGE:
|
||||||
|
return {
|
||||||
|
exchange: true,
|
||||||
|
forum: false,
|
||||||
|
edit: false,
|
||||||
|
register: false,
|
||||||
|
adminPanel: false
|
||||||
|
}
|
||||||
|
case types.FORUM:
|
||||||
|
return {
|
||||||
|
forum: true,
|
||||||
|
exchange: false,
|
||||||
|
edit: false,
|
||||||
|
register: false,
|
||||||
|
adminPanel: false
|
||||||
|
}
|
||||||
|
case types.REGISTER:
|
||||||
|
return {
|
||||||
|
register: true,
|
||||||
|
forum: false,
|
||||||
|
exchange: false,
|
||||||
|
edit: false,
|
||||||
|
adminPanel: false
|
||||||
|
}
|
||||||
|
case types.EDIT_ACCOUNT:
|
||||||
|
return {
|
||||||
|
edit: true,
|
||||||
|
forum: false,
|
||||||
|
exchange: false,
|
||||||
|
register: false,
|
||||||
|
adminPanel: false
|
||||||
|
}
|
||||||
|
case types.ADMIN_PANEL:
|
||||||
|
return {
|
||||||
|
adminPanel: true,
|
||||||
|
edit: false,
|
||||||
|
forum: false,
|
||||||
|
exchange: false,
|
||||||
|
register: false
|
||||||
|
}
|
||||||
|
case types.RESET:
|
||||||
|
return {
|
||||||
|
edit: false,
|
||||||
|
forum: false,
|
||||||
|
exchange: false,
|
||||||
|
register: false,
|
||||||
|
adminPanel: false
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default movementsReducer
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
const REGISTER = 'REGISTER'
|
||||||
|
const EDIT_ACCOUNT = 'EDIT_ACCOUNT'
|
||||||
|
const FORUM = 'FORUM'
|
||||||
|
const EXCHANGE = 'EXCHANGE'
|
||||||
|
const RESET = 'RESET'
|
||||||
|
const ADMIN_PANEL = 'ADMIN_PANEL'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
REGISTER,
|
||||||
|
EDIT_ACCOUNT,
|
||||||
|
FORUM,
|
||||||
|
EXCHANGE,
|
||||||
|
RESET,
|
||||||
|
ADMIN_PANEL
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { combineReducers } from 'redux'
|
||||||
|
import movementsReducer from './movements/duck'
|
||||||
|
import commentReducer from './comments/duck'
|
||||||
|
import subjectReducer from './subjects/duck'
|
||||||
|
import threadReducer from './threads/duck'
|
||||||
|
import userReducer from './user/duck'
|
||||||
|
|
||||||
|
const rootReducer = combineReducers({
|
||||||
|
user: userReducer,
|
||||||
|
threads: threadReducer,
|
||||||
|
subjects: subjectReducer,
|
||||||
|
comments: commentReducer,
|
||||||
|
movements: movementsReducer
|
||||||
|
})
|
||||||
|
|
||||||
|
export default rootReducer
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { createStore, applyMiddleware } from 'redux'
|
||||||
|
import { composeWithDevTools } from 'redux-devtools-extension'
|
||||||
|
import rootReducer from './reducers'
|
||||||
|
import thunk from 'redux-thunk'
|
||||||
|
|
||||||
|
const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk)))
|
||||||
|
|
||||||
|
window.store = store
|
||||||
|
|
||||||
|
export default store
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import types from './types'
|
||||||
|
|
||||||
|
const getSubjectComments = item => ({
|
||||||
|
type: types.GET_SUBJECT_COMMENTS, item
|
||||||
|
})
|
||||||
|
|
||||||
|
const activate = item => ({
|
||||||
|
type: types.ACTIVATE, item
|
||||||
|
})
|
||||||
|
|
||||||
|
const deactivate = item => ({
|
||||||
|
type: types.DEACTIVATE, item
|
||||||
|
})
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getSubjectComments,
|
||||||
|
activate,
|
||||||
|
deactivate
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import subjectReducer from './reducers'
|
||||||
|
export { default as subjectTypes } from './types'
|
||||||
|
export { default as subjectActions } from './actions'
|
||||||
|
|
||||||
|
export default subjectReducer
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
import actions from './actions'
|
||||||
|
|
||||||
|
const fetchSubjectComments = async (subject) => {
|
||||||
|
const response = await
|
||||||
|
fetch('http://localhost:8001/index/subject/' + subject.id + '/comment', {
|
||||||
|
method: 'GET',
|
||||||
|
credentials: 'same-origin'
|
||||||
|
});
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getSubjectComments = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
const comments = await fetchSubjectComments(data)
|
||||||
|
dispatch( actions.activate(data) )
|
||||||
|
dispatch( actions.getSubjectComments(comments) )
|
||||||
|
}
|
||||||
|
|
||||||
|
export const refreshSubjectComments = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
const comments = await fetchSubjectComments(data)
|
||||||
|
dispatch( actions.getSubjectComments(comments) )
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchAddSubject = async (data) => {
|
||||||
|
const response = await
|
||||||
|
fetch('http://localhost:8001/index/thread/' + data.thread_id + '/subject', {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
});
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addSubject = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
const comments = await fetchAddSubject(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchPutSubject = async (data) => {
|
||||||
|
const response = await
|
||||||
|
fetch('http://localhost:8001/index/subject/' + data.id, {
|
||||||
|
method: 'PUT',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
});
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const putSubject = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
const comments = await fetchPutSubject(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchDeleteSubject = async (data) => {
|
||||||
|
const response = await
|
||||||
|
fetch('http://localhost:8001/index/subject/' + data.id, {
|
||||||
|
method: 'DELETE',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
});
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deleteSubject = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
const comments = await fetchDeleteSubject(data)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
import types from './types'
|
||||||
|
|
||||||
|
const INITIAL_STATE = {
|
||||||
|
commentsList: [],
|
||||||
|
actualSubjectID: -1,
|
||||||
|
actualSubjectName: '',
|
||||||
|
actualSubjectAuthor: '',
|
||||||
|
actualSubjectAuthorID: -1,
|
||||||
|
isActive: false
|
||||||
|
}
|
||||||
|
|
||||||
|
const subjectReducer = (state = INITIAL_STATE, action) => {
|
||||||
|
switch(action.type) {
|
||||||
|
case types.GET_SUBJECT_COMMENTS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
commentsList: action.item
|
||||||
|
}
|
||||||
|
case types.ACTIVATE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
actualSubjectID: action.item.id,
|
||||||
|
actualSubjectName: action.item.name,
|
||||||
|
actualSubjectAuthor: action.item.author,
|
||||||
|
actualSubjectAuthorID: action.item.user_id,
|
||||||
|
isActive: true
|
||||||
|
}
|
||||||
|
case types.DEACTIVATE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
actualSubjectID: -1,
|
||||||
|
actualSubjectName: '',
|
||||||
|
actualSubjectAuthor: '',
|
||||||
|
actualSubjectAuthorID: -1,
|
||||||
|
isActive: false
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default subjectReducer
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
const GET_SUBJECT_COMMENTS = 'GET_SUBJECT_COMMENTS'
|
||||||
|
const ACTIVATE = 'ACTIVATE'
|
||||||
|
const DEACTIVATE = 'DEACTIVATE'
|
||||||
|
|
||||||
|
export default{
|
||||||
|
GET_SUBJECT_COMMENTS,
|
||||||
|
ACTIVATE,
|
||||||
|
DEACTIVATE
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import types from './types'
|
||||||
|
|
||||||
|
const getAll = item => ({
|
||||||
|
type: types.GET_ALL_THREADS, item
|
||||||
|
})
|
||||||
|
|
||||||
|
const getThreadSubjects = item => ({
|
||||||
|
type: types.GET_THREAD_SUBJECTS, item
|
||||||
|
})
|
||||||
|
|
||||||
|
const activate = item => ({
|
||||||
|
type: types.ACTIVATE_THREAD, item
|
||||||
|
})
|
||||||
|
|
||||||
|
const deactivate = item => ({
|
||||||
|
type: types.DEACTIVATE_THREAD, item
|
||||||
|
})
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getAll,
|
||||||
|
getThreadSubjects,
|
||||||
|
activate,
|
||||||
|
deactivate
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import threadReducer from './reducers'
|
||||||
|
export { default as threadTypes } from './types'
|
||||||
|
export { default as threadActions } from './actions'
|
||||||
|
|
||||||
|
export default threadReducer
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import actions from './actions'
|
||||||
|
|
||||||
|
const fetchGetAll = async () => {
|
||||||
|
const response = await
|
||||||
|
fetch (
|
||||||
|
'http://localhost:8001/index/thread', {
|
||||||
|
method: 'GET',
|
||||||
|
credential: 'same-origin'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchGetSubjects = async (threadID) => {
|
||||||
|
const response = await
|
||||||
|
fetch(
|
||||||
|
'http://localhost:8001/index/thread/' + threadID + '/subject', {
|
||||||
|
method: 'GET',
|
||||||
|
credential: 'same-origin'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAllThreads = () =>
|
||||||
|
async (dispatch) => {
|
||||||
|
const allThreads = await fetchGetAll()
|
||||||
|
|
||||||
|
dispatch( actions.getAll(allThreads) )
|
||||||
|
}
|
||||||
|
|
||||||
|
export const refreshThreadSubjects = (threadID) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
const subjects = await fetchGetSubjects(threadID)
|
||||||
|
dispatch( actions.getThreadSubjects(subjects) )
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getThreadSubjects = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
const subjects = await fetchGetSubjects(data.id)
|
||||||
|
dispatch( actions.activate(data) )
|
||||||
|
dispatch( actions.getThreadSubjects(subjects) )
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
import types from './types'
|
||||||
|
|
||||||
|
const INITIAL_STATE = {
|
||||||
|
threadsList: [],
|
||||||
|
actualThreadID: -1,
|
||||||
|
actualThreadName: '',
|
||||||
|
actualThreadModeratorID: -1,
|
||||||
|
actualThreadModerator: '',
|
||||||
|
subjectsList: [],
|
||||||
|
isActive: false
|
||||||
|
}
|
||||||
|
|
||||||
|
const threadReducer = (state = INITIAL_STATE, action) => {
|
||||||
|
switch(action.type) {
|
||||||
|
case types.GET_ALL_THREADS:
|
||||||
|
return {
|
||||||
|
...state, threadsList: action.item
|
||||||
|
}
|
||||||
|
case types.GET_THREAD_SUBJECTS:
|
||||||
|
return {
|
||||||
|
...state, subjectsList: action.item
|
||||||
|
}
|
||||||
|
case types.ACTIVATE_THREAD:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
actualThreadID: action.item.id,
|
||||||
|
actualThreadName: action.item.name,
|
||||||
|
actualThreadModeratorID: action.item.user_id,
|
||||||
|
actualThreadModerator: action.item.moderator,
|
||||||
|
isActive: true
|
||||||
|
}
|
||||||
|
case types.DEACTIVATE_THREAD:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
actualThreadID: -1,
|
||||||
|
actualThreadName: '',
|
||||||
|
actualThreadModeratorID: -1,
|
||||||
|
actualThreadModerator: '',
|
||||||
|
isActive: false
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default threadReducer
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
const GET_ALL_THREADS = 'GET_ALL_THREADS'
|
||||||
|
const GET_THREAD_SUBJECTS = 'GET_THREAD_SUBJECTS'
|
||||||
|
const ACTIVATE_THREAD = 'ACTIVATE_THREAD'
|
||||||
|
const DEACTIVATE_THREAD = '.DEACTIVATE_THREAD'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
GET_ALL_THREADS,
|
||||||
|
GET_THREAD_SUBJECTS,
|
||||||
|
ACTIVATE_THREAD,
|
||||||
|
DEACTIVATE_THREAD,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
import types from './types'
|
||||||
|
|
||||||
|
const login = item => ({
|
||||||
|
type: types.LOGIN_USER, item
|
||||||
|
})
|
||||||
|
|
||||||
|
const logout = item => ({
|
||||||
|
type: types.LOGOUT_USER, item
|
||||||
|
})
|
||||||
|
|
||||||
|
export default {
|
||||||
|
login,
|
||||||
|
logout
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import userReducer from './reducers'
|
||||||
|
export { default as userTypes } from './types'
|
||||||
|
export { default as userActions } from './actions'
|
||||||
|
|
||||||
|
export default userReducer
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
import actions from './actions'
|
||||||
|
|
||||||
|
var jwtDecode = require('jwt-decode')
|
||||||
|
|
||||||
|
const fetchLogin = async (user) => {
|
||||||
|
const response = await
|
||||||
|
fetch (
|
||||||
|
'http://localhost:8001/index/authUser', {
|
||||||
|
method: 'POST',
|
||||||
|
credential: 'same-origin',
|
||||||
|
body: JSON.stringify(user),
|
||||||
|
})
|
||||||
|
const json = await response.json()
|
||||||
|
return json
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchLogout = async (userToken) => {
|
||||||
|
fetch (
|
||||||
|
'http://localhost:8001/index/authUser', {
|
||||||
|
method: 'DELETE',
|
||||||
|
credential: 'same-origin',
|
||||||
|
body: JSON.stringify(userToken),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchUpdate = async (user) => {
|
||||||
|
fetch (
|
||||||
|
'http://localhost:8001/index/user/' + user.id, {
|
||||||
|
method: 'PUT',
|
||||||
|
credential: 'same-origin',
|
||||||
|
body: JSON.stringify(user),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchRegister = async (user) => {
|
||||||
|
fetch (
|
||||||
|
'http://localhost:8001/index/user', {
|
||||||
|
method: 'POST',
|
||||||
|
credential: 'same-origin',
|
||||||
|
body: JSON.stringify(user),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createSession = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
const token = await fetchLogin(data)
|
||||||
|
let user = jwtDecode(token.token)
|
||||||
|
|
||||||
|
let userFull = {
|
||||||
|
'token': token.token,
|
||||||
|
'id': user.payload.id,
|
||||||
|
'login': user.payload.login,
|
||||||
|
'privilige': user.payload.privilige,
|
||||||
|
'avatar': user.payload.avatar,
|
||||||
|
'email': user.payload.email
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(actions.login(userFull))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateSession = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
await fetchUpdate(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deleteSession = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
await fetchLogout(data)
|
||||||
|
dispatch(actions.logout())
|
||||||
|
}
|
||||||
|
|
||||||
|
export const registerUser = (data) =>
|
||||||
|
async (dispatch) => {
|
||||||
|
await fetchRegister(data)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
import types from './types'
|
||||||
|
|
||||||
|
const INITIAL_STATE = {
|
||||||
|
id: -1,
|
||||||
|
login: '',
|
||||||
|
email: '',
|
||||||
|
privilige: '',
|
||||||
|
avatar: '',
|
||||||
|
token: '',
|
||||||
|
isActive: false
|
||||||
|
}
|
||||||
|
|
||||||
|
const userReducer = (state = INITIAL_STATE, action) => {
|
||||||
|
switch(action.type) {
|
||||||
|
case types.LOGIN_USER:
|
||||||
|
return { ...state,
|
||||||
|
id: action.item.id,
|
||||||
|
login: action.item.login,
|
||||||
|
privilige: action.item.privilige,
|
||||||
|
email: action.item.email,
|
||||||
|
avatar: action.item.avatar,
|
||||||
|
token: action.item.token,
|
||||||
|
isActive: true
|
||||||
|
}
|
||||||
|
case types.LOGOUT_USER:
|
||||||
|
return {
|
||||||
|
isActive: false
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default userReducer
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
const LOGIN_USER = 'LOGIN_USER'
|
||||||
|
const LOGOUT_USER = 'LOGOUT_USER'
|
||||||
|
const GET_TOKEN = 'GET_TOKEN'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
LOGIN_USER,
|
||||||
|
LOGOUT_USER,
|
||||||
|
GET_TOKEN
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
|
||||||
|
@mixin center {
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(0, 110%);
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin inputStyle {
|
||||||
|
width: 200px;
|
||||||
|
height: 35px;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
border: 0px;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 12pt;
|
||||||
|
text-align: center;
|
||||||
|
color: rgba(111,108,106,1);
|
||||||
|
background-color: rgba(22,28,29,0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin buttonStyle {
|
||||||
|
width: 200px;
|
||||||
|
height: 35px;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
border: 0px;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 12pt;
|
||||||
|
color: rgba(117,82,29,1);
|
||||||
|
background-color: rgba(22,28,29,1);
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: rgba(22,28,29,1);
|
||||||
|
background-color: rgba(117,82,29,0.7);
|
||||||
|
transition-duration: 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: rgba(117,82,29,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin fontStyle {
|
||||||
|
color: rgba(117,82,29,1);
|
||||||
|
font-size: 20px;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin backgroundDivMenubarStyle{
|
||||||
|
background-color: rgba(22,28,29,0.2);
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
border-color: rgba(117,82,29,0.7);
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin backgroundDefaultDivStyle {
|
||||||
|
background-color: rgba(22,28,29,0.4);
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: rgba(117,82,29,0.7);
|
||||||
|
border-radius: 25px;
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin backgroundDivButtonStyle {
|
||||||
|
background-color: rgba(22,28,29,0.2);
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: rgba(117,82,29,0.7);
|
||||||
|
border-radius: 25px;
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(22,28,29,0.5);
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.adminDivColor {
|
||||||
|
background: rgb(36,0,0);
|
||||||
|
background: linear-gradient(180deg,
|
||||||
|
rgba(121,9,9,0.1) 10%,
|
||||||
|
rgba(0,212,255,0) 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.moderDivColor {
|
||||||
|
background: rgb(0,12,36);
|
||||||
|
background: linear-gradient(180deg,
|
||||||
|
rgba(9,17,121,0.1) 10%,
|
||||||
|
rgba(0,212,255,0) 50%);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
@import 'elements';
|
||||||
|
@import 'indexForum';
|
||||||
|
|
||||||
|
$widthRT: 40px;
|
||||||
|
|
||||||
|
.rating {
|
||||||
|
width: $widthRT;
|
||||||
|
height: 250px;
|
||||||
|
margin-left: 40px;
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratingStick {
|
||||||
|
width: 1px;
|
||||||
|
height: 250px;
|
||||||
|
|
||||||
|
background-color: rgba(117,82,29,1);
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratingValue {
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratingValue5 {
|
||||||
|
width: $widthRT;
|
||||||
|
height: 250px;
|
||||||
|
background-color: rgba(117,82,29,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratingValue4 {
|
||||||
|
width: $widthRT;
|
||||||
|
height: 200px;
|
||||||
|
background-color: rgba(117,82,29,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratingValue3 {
|
||||||
|
width: $widthRT;
|
||||||
|
height: 150px;
|
||||||
|
background-color: rgba(117,82,29,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratingValue2 {
|
||||||
|
width: $widthRT;
|
||||||
|
height: 100px;
|
||||||
|
background-color: rgba(117,82,29,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratingValue1 {
|
||||||
|
width: $widthRT;
|
||||||
|
height: 50px;
|
||||||
|
background-color: rgba(117,82,29,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratingValue0 {
|
||||||
|
width: $widthRT;
|
||||||
|
height: 1px;
|
||||||
|
background-color: rgba(117,82,29,1);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
@import 'elements';
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
input {
|
||||||
|
@include inputStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
@include inputStyle
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
@include buttonStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
@include fontStyle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
@import 'elements';
|
||||||
|
|
||||||
|
.indexView {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: rgba(31,34,35,1);
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#indexVideo {
|
||||||
|
opacity: 0.1;
|
||||||
|
position: fixed;
|
||||||
|
margin-bottom: -100vh;
|
||||||
|
filter: saturate(100%) sepia(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.interface {
|
||||||
|
width: 1030px;
|
||||||
|
height: 300px;
|
||||||
|
@include center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin OneDiv {
|
||||||
|
width: 300px;
|
||||||
|
height: auto;
|
||||||
|
padding: 50px;
|
||||||
|
margin-top: -125px;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
|
||||||
|
@include BigButtonStyle
|
||||||
|
|
||||||
|
input {
|
||||||
|
@include inputStyle
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
@include buttonStyle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin DefaultDiv {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
padding: 50px;
|
||||||
|
margin-right: 40px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin BigButtonStyle {
|
||||||
|
|
||||||
|
@include backgroundDivButtonStyle
|
||||||
|
|
||||||
|
color: rgba(117,82,29,1);
|
||||||
|
font-size: 20pt;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 150px;
|
||||||
|
height: 200px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
img {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin BttAndLogin {
|
||||||
|
@include DefaultDiv
|
||||||
|
@include BigButtonStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
.oneDivForm {
|
||||||
|
@include OneDiv
|
||||||
|
}
|
||||||
|
|
||||||
|
.emptySpace {
|
||||||
|
@include DefaultDiv
|
||||||
|
}
|
||||||
|
|
||||||
|
.exchangeBtt {
|
||||||
|
@include BttAndLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.forumBtt {
|
||||||
|
@include BttAndLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loginForm {
|
||||||
|
@include BttAndLogin;
|
||||||
|
|
||||||
|
input {
|
||||||
|
@include inputStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
@include buttonStyle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,242 @@
|
||||||
|
@import 'elements';
|
||||||
|
|
||||||
|
.indexForumMarginTop {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.indexForum {
|
||||||
|
@include backgroundDefaultDivStyle
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
|
||||||
|
width: 1400px;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin forumDiv {
|
||||||
|
width: 91%;
|
||||||
|
height: 60px;
|
||||||
|
|
||||||
|
padding-bottom: 3%;
|
||||||
|
padding-left: 4.5%;
|
||||||
|
padding-right: 4.5%;
|
||||||
|
|
||||||
|
margin-top: 3%;
|
||||||
|
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin gapTopBetweenElements {
|
||||||
|
border-bottom: 2px dashed;
|
||||||
|
border-color: rgba(117,82,29,0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin gapBetweenItems {
|
||||||
|
border-bottom: 1px dashed;
|
||||||
|
border-color: rgba(117,82,29,0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin gapBetweenSections {
|
||||||
|
border-right: 1px dashed;
|
||||||
|
border-color: rgba(117,82,29,0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.forumTitle {
|
||||||
|
@include forumDiv
|
||||||
|
@include gapTopBetweenElements
|
||||||
|
p {
|
||||||
|
font-size: 50px;
|
||||||
|
float: left;
|
||||||
|
margin-right: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
float: right;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:last-child{
|
||||||
|
float: right;
|
||||||
|
font-size: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:first-child {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.forumItemsList {
|
||||||
|
@include gapTopBetweenElements
|
||||||
|
|
||||||
|
.forumListItem:last-child{
|
||||||
|
border-bottom: 0px dashed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.forumListItem {
|
||||||
|
width: 90%;
|
||||||
|
height: 50px;
|
||||||
|
padding-right: 5%;
|
||||||
|
padding-left: 5%;
|
||||||
|
padding-top: 15px;
|
||||||
|
|
||||||
|
@include gapBetweenItems
|
||||||
|
|
||||||
|
p:first-child {
|
||||||
|
font-size: 30px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
p:last-child {
|
||||||
|
float: right;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div {
|
||||||
|
float: right;
|
||||||
|
width: auto;
|
||||||
|
margin-top: -5px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
float: left;
|
||||||
|
margin-right: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child{
|
||||||
|
border-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(22,28,29,0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.forumListComment {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
@include gapBetweenItems
|
||||||
|
|
||||||
|
&:last-child{
|
||||||
|
border-bottom: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.commentAvatar {
|
||||||
|
width: 20%;
|
||||||
|
padding: 50px;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
text-align: center;
|
||||||
|
@include gapBetweenSections
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.commentText {
|
||||||
|
width: 47.5%;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
padding-top: 20px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
padding-left: 2.5%;
|
||||||
|
padding-right: 2.5%;
|
||||||
|
|
||||||
|
word-wrap: break-word;
|
||||||
|
|
||||||
|
@include gapBetweenSections
|
||||||
|
}
|
||||||
|
.commentRating {
|
||||||
|
width: 15%;
|
||||||
|
height: 100px;
|
||||||
|
|
||||||
|
padding-top: 20px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
padding-left: 2.5%;
|
||||||
|
padding-right: 2.5%;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.forumFormSubject {
|
||||||
|
@include forumDiv
|
||||||
|
|
||||||
|
height: auto;
|
||||||
|
display: flex;
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
|
||||||
|
@include gapTopBetweenElements
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
float: left;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
padding-top: 10px;
|
||||||
|
margin-right: 50px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.forumFormComment {
|
||||||
|
@include forumDiv
|
||||||
|
|
||||||
|
height: auto;
|
||||||
|
display: flex;
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
|
||||||
|
@include gapTopBetweenElements
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
padding-top: 10px;
|
||||||
|
margin-right: 50px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.forumFoot {
|
||||||
|
@include forumDiv
|
||||||
|
button {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.forumHiddenDiv {
|
||||||
|
height: 0px;
|
||||||
|
display: none;
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
@import 'elements';
|
||||||
|
|
||||||
|
.menuBarActive {
|
||||||
|
@include backgroundDivMenubarStyle
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
height: 75px;
|
||||||
|
z-index: 1;
|
||||||
|
padding-top: 25px;
|
||||||
|
margin-top: 0px;
|
||||||
|
|
||||||
|
button, p {
|
||||||
|
float: right;
|
||||||
|
margin-right: 50px;
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
margin-top: 34px;
|
||||||
|
margin-left: 150px;
|
||||||
|
width: 70px;
|
||||||
|
height: 90px;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuBar {
|
||||||
|
@include backgroundDivMenubarStyle
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
height: 75px;
|
||||||
|
z-index: 1;
|
||||||
|
padding-top: 25px;
|
||||||
|
margin-top: -25px;
|
||||||
|
|
||||||
|
button, p {
|
||||||
|
float: right;
|
||||||
|
margin-right: 50px;
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
margin-top: -50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
margin-top: 34px;
|
||||||
|
margin-left: 150px;
|
||||||
|
width: 70px;
|
||||||
|
height: 90px;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue