merge front

front
TBS093A 2020-07-09 16:56:01 +02:00
commit d95de20cfd
73 changed files with 2166 additions and 224 deletions

97
README.md 100755
View File

@ -0,0 +1,97 @@
<!-- AUTO-GENERATED-CONTENT:START (STARTER) -->
<p align="center">
<a href="https://www.gatsbyjs.org">
<img alt="Gatsby" src="https://www.gatsbyjs.org/monogram.svg" width="60" />
</a>
</p>
<h1 align="center">
Gatsby's default starter
</h1>
Kick off your project with this default boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React.
_Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.org/docs/gatsby-starters/)._
## 🚀 Quick start
1. **Create a Gatsby site.**
Use the Gatsby CLI to create a new site, specifying the default starter.
```shell
# create a new Gatsby site using the default starter
gatsby new my-default-starter https://github.com/gatsbyjs/gatsby-starter-default
```
1. **Start developing.**
Navigate into your new sites directory and start it up.
```shell
cd my-default-starter/
gatsby develop
```
1. **Open the source code and start editing!**
Your site is now running at `http://localhost:8000`!
_Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._
Open the `my-default-starter` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time!
## 🧐 What's inside?
A quick look at the top-level files and directories you'll see in a Gatsby project.
.
├── node_modules
├── src
├── .gitignore
├── .prettierrc
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
├── gatsby-ssr.js
├── LICENSE
├── package-lock.json
├── package.json
└── README.md
1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed.
2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”.
3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for.
4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent.
5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser.
6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins youd like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail).
7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process.
8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering.
9. **`LICENSE`**: Gatsby is licensed under the MIT license.
10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You wont change this file directly).**
11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the projects name, author, etc). This manifest is how npm knows which packages to install for your project.
12. **`README.md`**: A text file containing useful reference information about your project.
## 🎓 Learning Gatsby
Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start:
- **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.org/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process.
- **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar.
## 💫 Deploy
[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-default)
<!-- AUTO-GENERATED-CONTENT:END -->

3
run.sh 100755
View File

@ -0,0 +1,3 @@
sudo sysctl fs.inotify.max_user_watches=524288
gatsby clean
gatsby develop

View File

View File

@ -0,0 +1,67 @@
import React from 'react'
import { connect } from 'react-redux'
import { chatOnOpen, chatOnClose, getChatRooms } from '../../stores/chat/duck/operations'
import '../../styles/indexChat.scss'
const ChatConnect = ({ chat, chatOnOpen, chatOnClose, getChatRooms }) => {
const inputLobbyName = React.createRef()
const setLobbyName = (event) => {
event.preventDefault()
if ( inputLobbyName.current.value !== '' ){
chatOnOpen(inputLobbyName.current.value)
}
else
inputLobbyName.current.value = 'Get a lobby name!'
}
const disconnect = (event) => {
event.preventDefault()
try{
chat.webSocket.close()
chatOnClose()
getChatRooms()
}catch {
chatOnClose()
getChatRooms()
}
}
if (chat.connected === false)
return (
<form onSubmit={ setLobbyName }>
<input
placeholder='lobby / room name'
ref={ inputLobbyName } />
<button >
Connect
</button>
</form>
)
else
return (
<form onSubmit={ disconnect }>
<div className='lobbyName'>
Lobby: { chat.lobby }
</div>
<button >
Disconnect
</button>
</form>
)
}
const mapStateToProps = state => ({
chat: state.chat
})
const mapDispatchToProps = dispatch => ({
chatOnOpen: chat => dispatch( chatOnOpen(chat) ),
chatOnClose: chat => dispatch( chatOnClose(chat) ),
getChatRooms: chat => dispatch( getChatRooms(chat) )
})
export default connect(mapStateToProps, mapDispatchToProps)(ChatConnect)

View File

@ -0,0 +1,197 @@
import React, { useState, useEffect } from 'react'
import { connect } from 'react-redux'
import { chatOnMessage, getChatRooms } from '../../stores/chat/duck/operations'
import ChatConnect from './chatConnect'
import '../../styles/indexChat.scss'
import imageIco from '../../images/imageIco.png'
const IndexChat = ({ user, chat, chatOnMessage, getChatRooms }) => {
const [chatVisible, setChatVisible] = useState(false)
const [chatImageVisible, setChatImageVisible] = useState( { visible: false, image: ''} )
const inputMessageText = React.createRef()
useEffect( () => { getChatRooms() }, [] )
if ( chat.host !== '' )
chat.webSocket.onmessage = (event) => {
chatOnMessage(JSON.parse(event.data))
}
const sendMessage = (event) => {
event.preventDefault()
let checkUploadValue = document.getElementById('fileItem').value
if ( inputMessageText.current.value !== '' && checkUploadValue !== '' && chat.host !== '' ) {
let inputMessageImage = document.getElementById('fileItem').files[0]
let message = {
userID: user.id,
userName: user.login,
avatar: user.avatar,
text: inputMessageText.current.value,
textOnly: false,
imageOnly: false
}
inputMessageText.current.value = ''
document.getElementById('fileItem').value = ''
sendBase64Image(inputMessageImage, message)
}
else if (inputMessageText.current.value !== '' && chat.host !== '' ) {
let message = {
userID: user.id,
userName: user.login,
avatar: user.avatar,
text: inputMessageText.current.value,
textOnly: true,
imageOnly: false
}
inputMessageText.current.value = ''
chat.webSocket.send(JSON.stringify(message))
}
else if ( checkUploadValue !== '' ) {
let inputMessageImage = document.getElementById('fileItem').files[0]
let message = {
userID: user.id,
userName: user.login,
avatar: user.avatar,
textOnly: false,
imageOnly: true
}
document.getElementById('fileItem').value = ''
sendBase64Image(inputMessageImage, message)
}
else
inputMessageText.current.value = 'Type message'
}
const sendBase64Image = (image, message) => {
let reader = new FileReader()
reader.onload = () => {
message.image = reader.result
chat.webSocket.send(JSON.stringify(message))
}
reader.readAsDataURL(image)
}
return (
<div className={ chatVisible === true ? (chat.host !== '' ? 'chatWindowOpen' : 'chatWindowChangeLobby') : 'chatWindowHide'}>
<div
className='chatMenuBar'
onClick={ () => setChatVisible( !chatVisible ) }>
chat
</div>
<div className='chatBody'>
<div className='lobbyMessage'>
<ChatConnect/>
</div>
<div className='listMessage'>
{ chat.host !== '' ? chat.messages.map( (message, key) => {
if ( chatImageVisible.visible )
return (
<div className='imageFullStyle' onClick={ () => setChatImageVisible( { visible: !chatImageVisible.visible, image: '' } ) }>
<img src={ chatImageVisible.image } />
</div>
)
if (message.userID === -1)
return (
<div></div>
)
else if (message.userID === user.id)
return (
<div className='rowMessage' key={key}>
<div className="chatAvatar">
<img src={message.avatar} title={message.userName} />
</div>
<div className='chatMessageDisplay' onClick={ message.textOnly !== true ? () => setChatImageVisible( { visible: !chatImageVisible.visible, image: message.image } ) : () => {} }>
{ message.imageOnly === false ?
<div className={ message.imageOnly !== message.textOnly ? 'userMessage': 'userMessage messageWithImage' }>
{message.text}
</div>
:
<div></div>
}
{ message.textOnly === false ? <img src={message.image} /> : <div></div>}
</div>
</div>
)
else
return (
<div className='rowMessage' key={key}>
<div className="chatAvatar">
<img src={message.avatar} title={message.userName} />
</div>
<div className='chatMessageDisplay' onClick={ message.textOnly !== true ? () => setChatImageVisible( { visible: !chatImageVisible.visible, image: message.image } ) : () => {} }>
{ message.imageOnly === false ?
<div className={ message.imageOnly !== message.textOnly ? 'otherMessage': 'otherMessage messageWithImage' }>
{message.text}
</div>
:
<div></div>
}
{ message.textOnly === false ? <img src={message.image} /> : <div></div>}
</div>
</div>
)
}
)
: ( chat.rooms.lenght === 0 ?
() => {
return (
<div className='chatListItem'>
Create first lobby!
</div>
)
}
:
chat.rooms.map( (room, key) => {
return (
<div key={ key } className='chatListItem'>
{ key + 1 }. Lobby: { room.name }, Users: { room.userCount }
</div>
)
}
)
)
}
</div>
<div className='textMessage'>
<form onSubmit={ sendMessage }>
<input
className='inputFile'
type='file'
id='fileItem' />
<img
className='inputFile'
src={ imageIco } />
<input
placeholder='message'
ref={ inputMessageText } />
<button>
Send
</button>
</form>
</div>
</div>
</div>
)
}
const mapStateToProps = state => ({
user: state.user,
chat: state.chat
})
const mapDispatchToProps = dispatch => ({
chatOnMessage: chat => dispatch( chatOnMessage(chat) ),
getChatRooms: chat => dispatch( getChatRooms(chat) )
})
export default connect(mapStateToProps, mapDispatchToProps)(IndexChat)

View File

@ -0,0 +1,57 @@
import React, { useState, useEffect } from 'react'
import { connect } from 'react-redux'
import { deleteNotification, getUserNotifications } from '../../stores/exchange/duck/operations'
import '../../styles/indexExchange.scss'
const ExchangeNotifications = ({
user,
exchange, deleteNotification, getUserNotifications }) => {
useEffect( () => { getUserNotifications(user.id) }, [] )
const deleteOldNotification = (notifyID) => {
let notify = {
id: notifyID,
token: user.token
}
deleteNotification(notify)
}
return (
<div className='exchangeNotificationsDiv'>
<p>{ user.login } exchange notifications:</p>
<div className='notifyList'>
{ exchange.userNotifications
.sort( (a, b) => b.id - a.id )
.map( (notify, key) => {
return (
<div key={ key + 1 }>
<p>{ key + 1 }. { notify.message }</p>
<button
className='deleteButton'
onClick={ () => deleteOldNotification(notify.id) }>
x
</button>
</div>
)
}
)
}
</div>
</div>
)
}
const mapStateToProps = state => ({
user: state.user,
exchange: state.exchange
})
const mapDispatchToProps = dispatch => ({
getUserNotifications: exchange => dispatch( getUserNotifications(exchange) ),
deleteNotification: exchange => dispatch( deleteNotification(exchange) )
})
export default connect(mapStateToProps,mapDispatchToProps)(ExchangeNotifications)

View File

@ -0,0 +1,48 @@
import React, { useState, useEffect } from 'react'
import { connect } from 'react-redux'
import { checkPrognosis } from '../../stores/exchange/duck/operations'
import '../../styles/indexExchange.scss'
const ExchangePrognosis = ({
user,
exchange, checkPrognosis }) => {
const inputPrognosis = React.createRef()
const checkNewPrognosis = () => {
if ( inputPrognosis.current.value > 0 ) {
let prognosis = {
price: inputPrognosis.current.value,
}
checkPrognosis( prognosis )
}
}
return (
<div className='exchangePrognosisDiv'>
<input
placeholder='Write the amount to exchange forecast'
onChange={ () => checkNewPrognosis() }
ref={ inputPrognosis }>
</input>
<p>Forecast: { Number((exchange.prognosis.price_forecast).toFixed(2)) } PLN</p>
<p>Percent: { Number((exchange.prognosis.percent_of_difference).toFixed(3)) } %</p>
<p>Course on payment: { exchange.prognosis.course_on_payment } PLN</p>
<p>AVG: { Number((exchange.prognosis.svg_of_all).toFixed(2)) }</p>
<p>Date: { exchange.prognosis.date_of_transaction }</p>
</div>
)
}
const mapStateToProps = state => ({
user: state.user,
exchange: state.exchange
})
const mapDispatchToProps = dispatch => ({
checkPrognosis: exchange => dispatch( checkPrognosis(exchange) )
})
export default connect(mapStateToProps,mapDispatchToProps)(ExchangePrognosis)

View File

@ -0,0 +1,68 @@
import React, { useState, useEffect } from 'react'
import { connect } from 'react-redux'
import { getChart, getUserTriggers, getUserNotifications, getUserTransactions, addTrigger } from '../../stores/exchange/duck/operations'
import '../../styles/indexExchange.scss'
const ExchangeTriggerAdd = ({
user,
exchange, getChart, getUserTriggers, getUserNotifications, getUserTransactions, addTrigger,
triggerValue }) => {
useEffect( () => { getUserTriggers(user.id) }, [] )
const [inputValue, setInputValue] = useState( triggerValue )
const [message, setMessage] = useState('')
const triggerValueAdd = React.createRef()
const addNewTrigger = (event) => {
event.preventDefault()
if ( triggerValue !== 0 ) {
let newTrigger = {
user_id: user.id,
course_values_for_trigger: triggerValue,
token: user.token
}
addTrigger( newTrigger )
setMessage('Trigger has been added')
}
else
setMessage('Trigger add error')
}
return (
<div className='exchangeTriggerDiv'>
<form onSubmit={ addNewTrigger }>
<p>Trigger value: { triggerValue } </p>
<button>
Add Trigger
</button>
</form>
<p>{ user.login } triggers:</p>
<p>{ message }</p>
<div className='triggerItemList'>
{ exchange.userTriggers
.sort( (a, b) => b.id - a.id )
.map( (trigger, key) => (
<div key={ key + 1 } className='triggerItem'>
<p>{ key + 1 }. Value: { trigger.course_values_for_trigger } PLN, Date: { trigger.date_of_trigger }, Status { trigger.status === 1 ? 'Enabled' : 'Disabled' }</p>
</div>
) ) }
</div>
</div>
)
}
const mapStateToProps = state => ({
user: state.user,
exchange: state.exchange
})
const mapDispatchToProps = dispatch => ({
getUserTriggers: exchange => dispatch( getUserTriggers(exchange) ),
addTrigger: exchange => dispatch( addTrigger(exchange) )
})
export default connect(mapStateToProps,mapDispatchToProps)(ExchangeTriggerAdd)

View File

@ -1,19 +1,177 @@
import React from 'react'
import React, { useState, useEffect } from 'react'
import { connect } from 'react-redux'
import '../../styles/index.scss'
import { getChart, getUserTriggers, getUserNotifications, getUserTransactions } from '../../stores/exchange/duck/operations'
const IndexExchange = ({ user }) => {
import { useInterval } from '../useInterval'
import ExchangeTriggerAdd from './exchangeTriggerAdd'
import ExchangePrognosis from './exchangePrognosis'
import ExchangeNotifications from './exchangeNotifications'
import '../../styles/indexExchange.scss'
const IndexExchange = ({
user,
exchange, getChart, getUserTriggers, getUserNotifications, getUserTransactions }) => {
let fifteenMinuts = 1500000
useInterval(() => {
getChart()
}, fifteenMinuts)
const [candleInfo, setCandleInfo] = useState({ Open: 0, Close: 0, Min: 0, Max: 0, Vol: 0 })
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 })
const [triggerValue, setTriggerValue] = useState(0)
const colorGreen = {
background: 'green'//'rgba(0,93,0,1)',
}
const colorRed = {
background: 'red'//'rgba(136,15,15,1)',
}
const getCandleInformation = (candle) => {
setCandleInfo({
Open: candle.Open,
Close: candle.Close,
Min: candle.Min,
Max: candle.Max,
Vol: candle.Volume,
Date: candle.Date
}
)
}
let pixelScale = (exchange.candles.graphMax - exchange.candles.graphMin) / 590
let cursorValue = exchange.candles.graphMax - (pixelScale * (mousePosition.y - 175))
const getMousePosition = (event) => {
setMousePosition({ x: event.pageX, y: event.pageY })
}
useEffect( () => responsiveIntrface())
const responsiveIntrface = () => {
if ( user.id != -1) {
let chartHeight = 600
let chartPaddingTop = 175
let exchangeInterfaceHeight = window.innerHeight - (chartHeight + chartPaddingTop)
document.getElementById('exchangeInterfaceTwo').style = 'height: ' + exchangeInterfaceHeight + 'px;'
}
}
return (
<div className='indexExchange'>
<div className={user.id > -1 ? 'exchangeChartUser' : 'exchangeChartGuest'}>
<div className='chart'
onMouseOver={event => getMousePosition(event)}
onClick={() => setTriggerValue(parseInt(cursorValue))}
style={{ width: exchange.candles.candlesCount * 15 + 'px' }}>
{user.id > -1 ? (
<div>
<div className='exchangeTriggerDativeY'
style={{ transform: 'translateY(' + (mousePosition.y - 175) + 'px)' }}>
<p>{parseInt(cursorValue)} PLN</p>
</div>
<div className='exchangeTriggerDativeX'
style={{ transform: 'translateX(' + (mousePosition.x) + 'px)' }}>
</div>
</div>
) : (
<div></div>
)}
{exchange.candles.candles.map((candle, key) => {
const color = candle.Open > candle.Close ? colorRed.background : colorGreen.background
let highValue = candle.Open > candle.Close ? candle.Open : candle.Close
let lowValue = candle.Open < candle.Close ? candle.Open : candle.Close
let scaleProperties = 10
let chartScaleY = (exchange.candles.graphMax - candle.Max) / pixelScale
let onePercentScaleY = 100 / chartScaleY
let difference = (highValue - lowValue) / pixelScale
if (parseInt(difference) === 0)
difference = 1
return (
<div
key={key}
className='sectionChart'
onMouseOver={() => getCandleInformation(candle)}>
<div className='sectionCandle'>
<div
className='candle'
style={{ paddingTop: chartScaleY + 'px' }}>
<div
className='candleMaxValue'
style={{ height: parseInt((candle.Max - highValue) / pixelScale) + 'px', background: color }}>
</div>
<div
className='candleHigh'
style={{ height: parseInt(difference) + 'px', background: color }}>
</div>
<div
className='candleMinValue'
style={{ height: parseInt((lowValue - candle.Min) / pixelScale) + 'px', background: color }}>
</div>
</div>
</div>
<div className='sectionVolumen'>
<div className='volumen'
style={{ height: candle.Volume / 1.5 + 'px' }}>
</div>
</div>
</div>
)
}
)
}
</div>
</div>
<div className={user.id > -1 ? 'exchangeInterface' : 'exchangeEmptySpace'}>
<div className='candleInformation'>
<p>Open: {candleInfo.Open} PLN</p>
<p>Close: {candleInfo.Close} PLN</p>
<p>Max: {candleInfo.Max} PLN</p>
<p>Min: {candleInfo.Min} PLN</p>
<p>Volume: {candleInfo.Vol}</p>
<p>Date: {candleInfo.Date}</p>
</div>
</div>
{user.id > -1 ? (
<div id='exchangeInterfaceTwo'>
<ExchangeTriggerAdd triggerValue={triggerValue} />
<ExchangePrognosis />
<ExchangeNotifications />
</div>
) : (
<div></div>
)
}
</div>
)
}
const mapStateToProps = state => ({
user: state.user,
exchange: state.exchange
})
const mapDispatchToProps = dispatch => ({
getChart: exchange => dispatch(getChart(exchange)),
getUserTriggers: exchange => dispatch(getUserTriggers(exchange)),
getUserNotifications: exchange => dispatch(getUserNotifications(exchange)),
getUserTransactions: exchange => dispatch(getUserTransactions(exchange))
})
export default connect(mapStateToProps,null)(IndexExchange)
export default connect(mapStateToProps, mapDispatchToProps)(IndexExchange)

View File

@ -16,7 +16,15 @@ const ForumCommentUpdate = ({
const updateCommentTextArea = React.createRef()
const updateOldComment = (event) => {
const sleep = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms))
}
let subjectLoad = {
id: subjects.actualSubjectID
}
const updateOldComment = async (event) => {
event.preventDefault()
if ( updateCommentTextArea.current.value !== '' ) {
let commentData = {
@ -25,7 +33,9 @@ const ForumCommentUpdate = ({
text: updateCommentTextArea.current.value
}
updateCommentTextArea.current.value = ''
updateComment(commentData)
await updateComment(commentData)
await sleep(100)
await refreshSubjectComments(subjectLoad)
}
}

View File

@ -22,9 +22,16 @@ const ForumComments = ({
const [formDiv, setFormDiv] = useState(false)
const addCommentTextArea = React.createRef()
const updateCommentTextArea = React.createRef()
const addNewComment = (event) => {
let subjectLoad = {
id: subjects.actualSubjectID
}
const sleep = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms))
}
const addNewComment = async (event) => {
event.preventDefault()
if ( addCommentTextArea.current.value !== '' ) {
let newComment = {
@ -34,25 +41,21 @@ const ForumComments = ({
token: user.token
}
addCommentTextArea.current.value = ''
addComment(newComment)
await addComment( newComment )
await sleep(100)
await refreshSubjectComments(subjectLoad)
setFormDiv( !formDiv )
let actualSubject = {
id: subjects.actualSubjectID
}
refreshSubjectComments(actualSubject)
}
}
const deleteOldComment = (commentID) => {
const deleteOldComment = async(commentID) => {
let delComment = {
id: commentID,
token: user.token
}
deleteComment(delComment)
let actualSubject = {
id: subjects.actualSubjectID
}
refreshSubjectComments(actualSubject)
await deleteComment(delComment)
await sleep(100)
await refreshSubjectComments(subjectLoad)
}
const [commentText, setCommentText] = useState(0)

View File

@ -57,21 +57,22 @@ const ForumRatings = ({
let divYPositionOnPage = ratingDiv.getBoundingClientRect().top + 72
let yPosition = event.screenY - divYPositionOnPage
if ( yPosition > 200 ) {
if ( yPosition > 270 ) {
setValue(5)
}
else if ( yPosition > 150 && yPosition < 200 ) {
else if ( yPosition > 215 && yPosition < 270 ) {
setValue(4)
}
else if ( yPosition > 100 && yPosition < 150 ) {
else if ( yPosition > 168 && yPosition < 215 ) {
setValue(3)
}
else if ( yPosition > 50 && yPosition < 150 ) {
else if ( yPosition > 120 && yPosition < 168 ) {
setValue(2)
}
else if ( yPosition > 0 && yPosition < 50 ) {
else if ( yPosition > 60 && yPosition < 120 ) {
setValue(1)
}
console.log(yPosition)
}
const [updateRating, setUpdate] = useState(false)

View File

@ -17,6 +17,7 @@ const ForumSubjectUpdate = ({
const updateSubjectTitle = React.createRef()
const updateSubjectAuthor = React.createRef()
<<<<<<< HEAD
const updateOldSubject = (event) => {
event.preventDefault()
if ( updateSubjectTitle.current.value !== '') {
@ -25,6 +26,29 @@ const ForumSubjectUpdate = ({
name: updateSubjectTitle.current.value,
user_id: user.id,
thread_id: threads.actualThreadID,
=======
const [selectAuthorID, setSelectAuthorID] = useState(-1)
const [selectThreadID, setSelectThreadID] = useState(-1)
const updateOldSubject = (event) => {
event.preventDefault()
if ( updateSubjectTitle.current.value !== '' && selectAuthorID === -1 && selectThreadID === -1 ) {
let putSubject = {
id: subject.id,
name: updateSubjectTitle.current.value,
user_id: subject.user_id,
thread_id: subject.thread_id,
token: user.token
}
updateSubject(putSubject)
updateSubjectTitle.current.value = ''
} else if ( updateSubjectTitle.current.value !== '' && user.privilige >= 2 ) {
let putSubject = {
id: subject.id,
name: updateSubjectTitle.current.value,
user_id: selectAuthorID === -1 ? subject.user_id : selectAuthorID,
thread_id: selectThreadID === -1 ? subject.thread_id : selectThreadID,
>>>>>>> front
token: user.token
}
updateSubject(putSubject)
@ -51,8 +75,13 @@ const ForumSubjectUpdate = ({
<div>
<select
name='updateSubjectAuthorText'
<<<<<<< HEAD
value={ user.allUsersList }
ref={ updateSubjectAuthor }>
=======
onChange={ e => setSelectAuthorID( e.target.value ) }>
<option value={ subject.user_id }>Choice Author ( actual: { subject.author } )</option>
>>>>>>> front
{ user.allUsersList.map( userObject =>
<option value={userObject.id}>{userObject.login}, Privilige: { userObject.privilige >= 2 ? 'Moderator' : 'Normal User' }</option>
)
@ -60,7 +89,12 @@ const ForumSubjectUpdate = ({
</select>
<select
name='updateSubjectAuthorText'
<<<<<<< HEAD
value={ threads.threadsList }>
=======
onChange={ e => setSelectThreadID( e.target.value ) }>
<option value={ threads.actualThreadID }>Choice Thread ( actual: { threads.actualThreadName } )</option>
>>>>>>> front
{ threads.threadsList.map( threadObject =>
<option value={threadObject.id}>{threadObject.name}, moderator: {threadObject.moderator}</option>
)

View File

@ -2,7 +2,7 @@ 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 { getSubjectComments, addSubject, deleteSubject } from '../../stores/subjects/duck/operations'
import { addComment } from '../../stores/comments/duck/operations'
import actions from '../../stores/threads/duck/actions'
@ -14,14 +14,16 @@ import ForumSubjectUpdate from './forumSubjectUpdate'
const ForumSubjects = ({
user,
threads, deactivate,
subjects, addSubject, getSubjectComments,
subjects, addSubject, deleteSubject, getSubjectComments,
comments, addComment }) => {
const [formDiv, setFormDiv] = useState(false)
const [updateFormDiv, setUpdateFormDiv] = useState( { isActive: false, subject_id: -1 } )
const addSubjectTitle = React.createRef()
const addSubjectComment = React.createRef()
const addNewSubject = (event) => {
event.preventDefault()
if ( addSubjectTitle.current.value !== '' && addSubjectComment.current.value !== '' ) {
@ -42,6 +44,16 @@ const ForumSubjects = ({
}
}
const deleteOldSubject = (subject) => {
if( user.id === subject.user_id || user.id === threads.actualThreadModeratorID || user.privilige === 3 ) {
let delSubject = {
token: user.token,
subject_id: subject.id
}
deleteSubject(delSubject)
}
}
const [commentText, setCommentText] = useState(0)
const [titleText, setTitleText] = useState(0)
@ -73,10 +85,10 @@ const ForumSubjects = ({
user.id === threads.actualThreadModeratorID ||
user.privilige === 3) ? (
<div>
<button onClick={ () => setSubjectEdit( { isActive: !subjectEdit.isActive, subject_id: subject.id } ) }>
{ subjectEdit.isActive === true ? 'Close Edit' : 'Edit Subject' }
<button onClick={ () => setUpdateFormDiv( { isActive: !updateFormDiv.isActive, subject_id: subject.id } )}>
{ updateFormDiv.isActive ? 'Close Edit' : 'Edit Subject' }
</button>
<button>
<button onClick={ () => deleteOldSubject(subject) }>
Delete Subject
</button>
<img src={subject.author_avatar} />
@ -90,7 +102,7 @@ const ForumSubjects = ({
)
}
</div>
<ForumSubjectUpdate subject={subject} thisSubject={subjectEdit} />
<ForumSubjectUpdate subject={subject} thisSubject={updateFormDiv} />
</div>
) }
</div>
@ -146,6 +158,7 @@ const mapDispatchToProps = dispatch => ({
refreshThreadSubjects: threads => dispatch( refreshThreadSubjects(threads) ),
getSubjectComments: subjects => dispatch( getSubjectComments(subjects) ),
addSubject: subjects => dispatch( addSubject(subjects) ),
deleteSubject: subjects => dispatch( deleteSubject(subjects) ),
addComment: comments => dispatch( addComment(comments) ),
deactivate: () => dispatch( actions.deactivate() )

98
src/components/forum/indexForum.js 100644 → 100755
View File

@ -1,16 +1,49 @@
import React, { useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import { connect } from 'react-redux'
import { getAllThreads, getThreadSubjects } from '../../stores/threads/duck/operations'
import { getAllThreads, getThreadSubjects, addThread, deleteThread } from '../../stores/threads/duck/operations'
import '../../styles/indexForum.scss'
import ForumSubjects from './forumSubjects'
import ForumThreadUpdate from './indexForumUpdate'
const IndexForum = ({ user, threads, getAllThreads, getThreadSubjects }) => {
const IndexForum = ({
user,
threads, getAllThreads, getThreadSubjects, addThread, deleteThread }) => {
useEffect( () => { getAllThreads() }, [] )
const [formDiv, setFormDiv] = useState(false)
const [updateFormDiv, setUpdateFormDiv] = useState( { isActive: false, thread_id: -1 } )
const [titleText, setTitleText] = useState(0)
const addThreadTitle = React.createRef()
const addNewThread = (event) => {
event.preventDefault()
if ( addThreadTitle.current.value !== '' ) {
let newThread = {
name: addThreadTitle.current.value,
user_id: user.id,
token: user.token
}
addThread(newThread)
addThreadTitle.current.value = ''
}
}
const deleteOldThread = (thread) => {
if( user.privilige === 3 ) {
let delSubject = {
token: user.token,
thread_id: thread.id
}
deleteThread(delSubject)
}
}
if (threads.isActive === false) {
return (
<div>
@ -24,18 +57,63 @@ const IndexForum = ({ user, threads, getAllThreads, getThreadSubjects }) => {
</div>
<div className='forumItemsList'>
{ threads.threadsList.map( thread =>
<div>
<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>
key={thread.id}>
<p onClick={ () => getThreadSubjects(thread) }>{thread.name}</p>
{ (user.id === thread.user_id ||
user.privilige === 3) ? (
<div>
<button onClick={ () => setUpdateFormDiv( { isActive: !updateFormDiv.isActive, thread_id: thread.id } )}>
{ updateFormDiv.isActive ? 'Close Edit' : 'Edit Thread' }
</button>
{ user.privilige === 3 ? (
<button onClick={ () => deleteOldThread( thread )}>
Delete Thread
</button>
) : (
<div></div>
) }
<img src={ thread.moderator_avatar } />
<p>{ thread.moderator }</p>
</div>
) : (
<div>
<img src={ thread.moderator_avatar } />
<p>{ thread.moderator }</p>
</div>
)
}
</div>
<ForumThreadUpdate thread={ thread } thisThread={ updateFormDiv }/>
</div>
) }
</div>
<div className={ formDiv === true ? 'forumFormSubject' : 'forumHiddenDiv' }>
<form onSubmit={ addNewThread }>
<input
name='addThreadTitle'
placeholder='Write a thread title'
maxLength='30'
ref={ addThreadTitle }
onChange={ e => setTitleText(e.target.value.length) }>
</input>
<p>Title: {titleText}/30</p>
<button>
Add Thread
</button>
</form>
</div>
<div className='forumFoot'>
Foot
{ user.privilige === 3 ? (
<button onClick={ () => setFormDiv( !formDiv ) }>
{ formDiv === true ? 'Close Add Thread' : 'Add Thread' }
</button>
) : (
<div></div>
) }
</div>
</div>
<div className='indexForumMarginTop'>
@ -64,8 +142,10 @@ const mapStateToProps = state => ({
})
const mapDispatchToProps = dispatch => ({
addThread: threads => dispatch( addThread(threads) ),
deleteThread: threads => dispatch( deleteThread(threads) ),
getAllThreads: () => dispatch( getAllThreads() ),
getThreadSubjects: thread => dispatch( getThreadSubjects(thread) )
getThreadSubjects: threads => dispatch( getThreadSubjects(threads) )
})
export default connect(mapStateToProps, mapDispatchToProps)(IndexForum)

View File

@ -0,0 +1,95 @@
import React, { useState } from 'react'
import { connect } from 'react-redux'
import { updateThread } from '../../stores/threads/duck/operations'
import '../../styles/indexForum.scss'
const IndexForumUpdate = ({
user,
threads, getAllThreads, getThreadSubjects, updateThread,
thread, thisThread }) => {
const updateThreadTitle = React.createRef()
const [threadTitleText, setThreadTitleText] = useState(0)
const [selectThreadModeratorID, setSelectThreadModeratorID] = useState(-1)
const updateOldThread = (event) => {
event.preventDefault()
if ( updateThreadTitle.current.value !== '' && selectThreadModeratorID === -1 && user.privilige >= 2) {
let putThread = {
id: thread.id,
name: updateThreadTitle.current.value,
user_id: thread.user_id,
token: user.token
}
updateThread(putThread)
updateThreadTitle.current.value = ''
} else if ( updateThreadTitle.current.value !== '' && user.privilige === 3 ) {
let putThread = {
id: thread.id,
name: updateThreadTitle.current.value,
user_id: selectThreadModeratorID === -1 ? thread.user_id : selectThreadModeratorID,
token: user.token
}
updateThread(putThread)
updateThreadTitle.current.value = ''
}
}
if ( thisThread.isActive === true && thisThread.thread_id === thread.id ) {
return (
<div className='forumFormSubject'>
<form onSubmit={ updateOldThread }>
<input
name='updateThreadTitleText'
placeholder={ thread.name }
ref={ updateThreadTitle }
cols='150'
maxLength='30'
onChange={ e => setThreadTitleText( e.target.value.length ) }>
</input>
{ (user.privilige === 3) ? (
<div>
<select
name='updateThreadModerator'
onChange={ e => setSelectThreadModeratorID( e.target.value ) }>
<option value={ thread.user_id }>Choice Moderator ( actual: { thread.moderator } )</option>
{ user.allUsersList
.filter( userObject => userObject.privilige >= 2 )
.map( userObject =>
<option value={userObject.id}>{userObject.login}</option>
)
}
</select>
</div>
) : (
<div></div>
)
}
<p>{threadTitleText}/30</p>
<button>
Update thread
</button>
</form>
</div>
)
} else {
return (
<div className='forumHiddenDiv'>
</div>
)
}
}
const mapStateToProps = state => ({
user: state.user,
threads: state.threads
})
const mapDispatchToProps = dispatch => ({
updateThread: threads => dispatch( updateThread(threads) )
})
export default connect(mapStateToProps, mapDispatchToProps)(IndexForumUpdate)

View File

@ -1,28 +0,0 @@
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)

View File

@ -1,28 +0,0 @@
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)

22
src/components/indexInterface.js 100644 → 100755
View File

@ -1,9 +1,10 @@
import React from 'react'
import React, {useEffect} from 'react'
import { connect } from 'react-redux'
// Operations Redux
import { createSession, deleteSession, updateSession, registerUser } from '../stores/user/duck/operations'
import { getChart } from '../stores/exchange/duck/operations'
// Actions Redux
@ -16,6 +17,7 @@ import '../styles/index.scss'
// Components
import MenuBar from './menuBar/menuBar'
import Chat from './chat/indexChat'
import Exchange from './exchange/indexExchange'
import Forum from './forum/indexForum'
@ -28,9 +30,12 @@ import BtcLogo from '../images/BtcLogo.png'
import ForumLogo from '../images/ForumLogo.png'
const IndexInterface = ({
user, movements,
user, movements, exchange,
createSession, deleteSession, updateSession, registerUser,
setRegister, setEdit, setForum, setExchange, setAdminPanel, resetMovements}) => {
setRegister, setEdit, setForum, setExchange, setAdminPanel, resetMovements,
getChart }) => {
useEffect( () => { getChart() }, [] )
const loginInput = React.createRef()
const passwordInput = React.createRef()
@ -235,6 +240,7 @@ const IndexInterface = ({
}
else if (user.privilige === 3) {
return (
<div>
<div className='indexView'>
<video id='indexVideo' autoPlay muted loop>
<source src={VideoEx} type="video/mp4" />
@ -266,10 +272,13 @@ const IndexInterface = ({
</div>
</div>
</div>
<Chat />
</div>
)
}
else {
return (
<div>
<div className='indexView'>
<video id='indexVideo' autoPlay muted loop>
<source src={VideoEx} type="video/mp4" />
@ -298,12 +307,15 @@ const IndexInterface = ({
</div>
</div>
</div>
<Chat />
</div>
)
}
}
const mapStateToProps = state => ({
user: state.user,
exchange: state.exchange,
movements: state.movements
})
@ -318,7 +330,9 @@ const mapDispatchToProps = dispatch => ({
setExchange: movements => dispatch( actions.exchange() ),
setForum: movements => dispatch( actions.forum() ),
setAdminPanel: movements => dispatch( actions.adminPanel() ),
resetMovements: movements => dispatch( actions.reset() )
resetMovements: movements => dispatch( actions.reset() ),
getChart: exchange => dispatch( getChart(exchange) )
})
export default connect(mapStateToProps, mapDispatchToProps)(IndexInterface)

0
src/components/menuBar/menuBar.js 100644 → 100755
View File

View File

@ -0,0 +1,22 @@
import React, { useState, useEffect, useRef } from 'react';
export const useInterval = (callback, delay) => {
const savedCallback = useRef();
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
export default useInterval

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

4
src/pages/index.js 100644 → 100755
View File

@ -2,13 +2,13 @@ import React from "react";
import IndexInterface from "../components/indexInterface"
import store from "../stores/store";
import { store } from "../stores/store";
import { Provider } from "react-redux";
import '../styles/general.scss'
const IndexPage = () => (
<Provider store={store}>
<Provider store={ store }>
<IndexInterface />
</Provider>
)

View File

@ -0,0 +1,2 @@
export const address = 'http://localhost:9090'//'http://tbs093a.pythonanywhere.com'
export const webSocketAddress = 'ws://localhost:9090/ws/'

View File

@ -0,0 +1,29 @@
import types from './types'
const wsConnect = (host, lobby) => ({
type: types.WS_CONNECT, host, lobby
});
const wsSend = host => ({
type: types.WS_SEND, host
});
const wsDisconnect = host => ({
type: types.WS_DISCONNECT, host
});
const wsSaveMessage = host => ({
type: types.WS_SAVE_MESSAGE, host
})
const getRooms = host => ({
type: types.GET_ROOMS_LIST, host
})
export default {
wsConnect,
wsSend,
wsDisconnect,
wsSaveMessage,
getRooms
}

View File

@ -0,0 +1,5 @@
import chatReducer from './reducers'
export { default as chatTypes } from './types'
export { default as chatActions } from './actions'
export default chatReducer

View File

@ -0,0 +1,34 @@
import actions from './actions'
import { webSocketAddress, address } from './../../apiAddress'
export const chatOnOpen = ( data ) =>
async ( dispatch ) => {
dispatch(actions.wsConnect( webSocketAddress + '' + data + '/', data))
}
export const chatOnMessage = (data) =>
async (dispatch) => {
dispatch(actions.wsSaveMessage(data))
}
export const chatOnClose = () =>
async ( dispatch ) => {
dispatch(actions.wsDisconnect())
}
const fetchGetRooms = async () => {
const response = await
fetch (
address + '/chat/', {
method: 'GET',
credentials: 'same-origin'
})
const json = await response.json()
return json
}
export const getChatRooms = () =>
async ( dispatch ) => {
let roomList = await fetchGetRooms()
dispatch(actions.getRooms(roomList))
}

View File

@ -0,0 +1,45 @@
import types from './types'
const INITIAL_STATE = {
host: '',
lobby: '',
connected: false,
messages: [],
rooms: []
}
const chatReducer = ( state = INITIAL_STATE, action ) => {
switch (action.type) {
case types.GET_ROOMS_LIST:
return {
...state,
rooms: action.host
}
case types.WS_CONNECT:
return {
...state,
connected: true,
lobby: action.lobby,
host: action.host,
webSocket: new WebSocket(action.host)
}
case types.WS_SAVE_MESSAGE:
return {
...state,
messages: [...state.messages, action.host]
}
case types.WS_DISCONNECT:
return {
...state,
webSocket: '',
lobby: '',
connected: false,
messages: [],
host: ''
}
default:
return state;
}
}
export default chatReducer

View File

@ -0,0 +1,13 @@
const WS_CONNECT = 'WS_CONNECT'
const WS_SEND = 'WS_SEND'
const WS_SAVE_MESSAGE = 'WS_SAVE_MESSAGE'
const WS_DISCONNECT = 'WS_DISCONNECT'
const GET_ROOMS_LIST = 'GET_ROOMS_LIST'
export default {
WS_CONNECT,
WS_SEND,
WS_SAVE_MESSAGE,
WS_DISCONNECT,
GET_ROOMS_LIST
}

View File

@ -4,6 +4,11 @@ const getRatingsComment = item => ({
type: types.GET_COMMENTS_RATINGS, item
})
const addComment = item => ({
type: types.ADD_COMMENT, item
})
export default {
getRatingsComment
getRatingsComment,
addComment
}

0
src/stores/comments/duck/index.js 100644 → 100755
View File

View File

@ -1,8 +1,9 @@
import actions from './actions'
import { address } from './../../apiAddress'
const fetchRatingsComment = async (comment) => {
const response = await
fetch ('http://localhost:8001/index/comment/' + comment.id + '/rating', {
fetch (address + '/index/comment/' + comment.id + '/rating', {
method: 'GET',
credentials: 'same-origin'
});
@ -10,7 +11,7 @@ const fetchRatingsComment = async (comment) => {
}
const fetchAddRating = async (data) => {
fetch ('http://localhost:8001/index/comment/' + data.comment_id + '/rating', {
fetch (address + '/index/comment/' + data.comment_id + '/rating', {
method: 'POST',
credentials: 'same-origin',
body: JSON.stringify(data)
@ -18,7 +19,7 @@ const fetchAddRating = async (data) => {
}
const fetchUpdateRating = async (rating) => {
fetch ('http://localhost:8001/index/rating/' + rating.id, {
fetch (address + '/index/rating/' + rating.id, {
method: 'PUT',
credentials: 'same-origin',
body: JSON.stringify(rating)
@ -48,7 +49,7 @@ export const updateRatingComment = (data) =>
}
const fetchAddComment = async (data) => {
fetch ('http://localhost:8001/index/subject/' + data.subject_id + '/comment', {
fetch (address + '/index/subject/' + data.subject_id + '/comment', {
method: 'POST',
credentials: 'same-origin',
body: JSON.stringify(data)
@ -56,7 +57,7 @@ const fetchAddComment = async (data) => {
}
const fetchUpdateComment = async (data) => {
fetch ('http://localhost:8001/index/comment/' + data.id, {
fetch (address + '/index/comment/' + data.id, {
method: 'PUT',
credentials: 'same-origin',
body: JSON.stringify(data)
@ -64,7 +65,7 @@ const fetchUpdateComment = async (data) => {
}
const fetchDeleteComment = async (data) => {
fetch ('http://localhost:8001/index/comment/' + data.id, {
fetch (address + '/index/comment/' + data.id, {
method: 'Delete',
credentials: 'same-origin',
body: JSON.stringify(data)

View File

4
src/stores/comments/duck/types.js 100644 → 100755
View File

@ -1,5 +1,7 @@
const GET_COMMENTS_RATINGS = 'GET_COMMENTS_RATINGS'
const ADD_COMMENT = 'ADD_COMMENT'
export default {
GET_COMMENTS_RATINGS
GET_COMMENTS_RATINGS,
ADD_COMMENT
}

View File

@ -0,0 +1,44 @@
import types from './types'
const setChart = item => ({
type: types.GET_CANDLES_CHART, item
})
const setTriggers = item => ({
type: types.GET_USER_TRIGGERS, item
})
const setNotifications = item => ({
type: types.GET_USER_NOTIFICATIONS, item
})
const setTransactions = item => ({
type: types.GET_USER_TRANSACTIONS, item
})
const deleteOldNotification = item => ({
type: types.DELETE_NOTIFICATION, item
})
const addNewTrigger = item => ({
type: types.ADD_NEW_TRIGGER, item
})
const setNewPrognosis = item => ({
type: types.NEW_PROGNOSIS, item
})
const reset = item => ({
type: types.RESET, item
})
export default {
setChart,
setTriggers,
setNotifications,
setTransactions,
deleteOldNotification,
addNewTrigger,
setNewPrognosis,
reset
}

View File

@ -0,0 +1,5 @@
import exchangeReducer from './reducers'
export { default as exchangeTypes } from './types'
export { default as exchangeActions } from './actions'
export default exchangeReducer

View File

@ -0,0 +1,120 @@
import actions from './actions'
import { address } from './../../apiAddress'
const fetchGetChart = async () => {
const response = await
fetch (
address + '/index/exchange/' + 1800, {
method: 'GET',
credential: 'same-origin'
})
const json = await response.json()
return json
}
const fetchGetUserTriggers = async (userID) => {
const response = await
fetch (
address + '/index/user/' + userID + '/trigger', {
method: 'GET',
credential: 'same-origin'
})
const json = await response.json()
return json
}
const fetchGetUserTransactions = async (userID) => {
const response = await
fetch (
address + '/index/user/' + userID + '/transaction', {
method: 'GET',
credential: 'same-origin'
})
const json = await response.json()
return json
}
const fetchGetUserNotifications = async (userID) => {
const response = await
fetch (
address + '/index/user/' + userID + '/notification', {
method: 'GET',
credential: 'same-origin'
})
const json = await response.json()
return json
}
const fetchAddTrigger = async (data) => {
fetch (
address + '/index/user/' + data.user_id + '/trigger', {
method: 'POST',
credential: 'same-origin',
body: JSON.stringify(data)
}
)
}
const fetchPrognosis = async (data) => {
const response = await fetch (
address + '/index/exchange/1800/prognosis/' + data.price, {
method: 'GET',
credential: 'same-origin'
}
)
const json = response.json()
return json
}
const fetchDeleteNotification = async (data) => {
const response = await fetch (
address + '/index/notification/' + data.id, {
method: 'DELETE',
credential: 'same-origin',
body: JSON.stringify(data)
}
)
const json = response.json()
return json
}
export const getChart = () =>
async (dispatch) => {
const chart = await fetchGetChart()
dispatch(actions.setChart(chart))
}
export const getUserTriggers = (userID) =>
async (dispatch) => {
const triggers = await fetchGetUserTriggers(userID)
dispatch(actions.setTriggers(triggers))
}
export const getUserTransactions = (userID) =>
async (dispatch) => {
const transactions = await fetchGetUserTransactions(userID)
dispatch(actions.setTransactions(transactions))
}
export const getUserNotifications = (userID) =>
async (dispatch) => {
const notifications = await fetchGetUserNotifications(userID)
dispatch(actions.setNotifications(notifications))
}
export const addTrigger = (data) =>
async (dispatch) => {
await fetchAddTrigger(data)
}
export const checkPrognosis = (data) =>
async (dispatch) => {
const prognosis = await fetchPrognosis(data)
dispatch(actions.setNewPrognosis(prognosis))
}
export const deleteNotification = (data) =>
async (dispatch) => {
dispatch(actions.deleteOldNotification(data))
await fetchDeleteNotification(data)
}

View File

@ -0,0 +1,70 @@
import types from './types'
const INITIAL_STATE = {
candles: [],
userTriggers: [],
userNotifications: [],
userTransactions: [],
prognosis: {
price_forecast: 0,
percent_of_difference: 0,
course_on_payment: 0,
svg_of_all: 0,
date_of_transaction: ''
}
}
const exchangeReducer = (state = INITIAL_STATE, action) => {
switch(action.type) {
case types.GET_CANDLES_CHART:
return {
...state,
candles: action.item
}
case types.GET_USER_TRIGGERS:
return {
...state,
userTriggers: action.item
}
case types.GET_USER_NOTIFICATIONS:
return {
...state,
userNotifications: action.item
}
case types.GET_USER_TRANSACTIONS:
return {
...state,
userTransactions: action.item
}
case types.DELETE_NOTIFICATION:
return {
...state,
userNotifications: state.userNotifications.filter(
notify => notify.id !== action.item.id
)
}
case types.NEW_PROGNOSIS:
return {
...state,
prognosis: action.item
}
case types.RESET:
return {
...state,
userTriggers: [],
userNotifications: [],
userTransactions: [],
prognosis: {
price_forecast: 0,
percent_of_difference: 0,
course_on_payment: 0,
svg_of_all: 0,
date_of_transaction: ''
}
}
default:
return state
}
}
export default exchangeReducer

View File

@ -0,0 +1,19 @@
const GET_CANDLES_CHART = 'GET_CANDLES_CHART'
const GET_USER_TRIGGERS = 'GET_USER_TRIGGERS'
const GET_USER_NOTIFICATIONS = 'GET_USER_NOTIFICATIONS'
const GET_USER_TRANSACTIONS = 'GET_USER_TRANSACTIONS'
const DELETE_NOTIFICATION = 'DELETE_NOTIFICATION'
const ADD_NEW_TRIGGER = 'ADD_NEW_TRIGGER'
const NEW_PROGNOSIS = 'NEW_PROGNOSIS'
const RESET = 'RESET'
export default {
GET_CANDLES_CHART,
GET_USER_TRIGGERS,
GET_USER_NOTIFICATIONS,
GET_USER_TRANSACTIONS,
DELETE_NOTIFICATION,
ADD_NEW_TRIGGER,
NEW_PROGNOSIS,
RESET
}

View File

@ -0,0 +1,23 @@
export const loadState = () => {
try {
const serializedState = localStorage.getItem('state');
if (serializedState === null) {
return undefined;
}
return JSON.parse(serializedState);
} catch (err) {
return undefined;
}
};
export const saveState = (state) => {
try {
const serializedState = JSON.stringify(state);
localStorage.setItem('state', serializedState);
} catch (err) {
console.log('save in local storage error');
}
};

View File

View File

View File

View File

9
src/stores/reducers.js 100644 → 100755
View File

@ -1,16 +1,23 @@
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'
import chatReducer from './chat/duck'
import exchangeReducer from './exchange/duck'
const rootReducer = combineReducers({
user: userReducer,
chat: chatReducer,
threads: threadReducer,
subjects: subjectReducer,
comments: commentReducer,
movements: movementsReducer
movements: movementsReducer,
exchange: exchangeReducer
})
export default rootReducer

40
src/stores/store.js 100644 → 100755
View File

@ -1,10 +1,42 @@
import { createStore, applyMiddleware } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import rootReducer from './reducers'
import thunk from 'redux-thunk'
import rootReducer from './reducers'
import { saveState, loadState } from './localStorage';
import lodash from 'lodash';
const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk)))
//const store = createStore(rootReducer) //, composeWithDevTools(applyMiddleware(thunk))
window.store = store
const persistedState = loadState();
export default store
export const store = createStore(rootReducer, persistedState, composeWithDevTools(applyMiddleware(thunk)))
// console.log(store.getState())
store.subscribe(() => {
saveState({
user: store.getState().user,
chat: store.getState().chat,
exchange: store.getState().exchange,
comments: store.getState().comments,
subjects: store.getState().subjects,
threads: store.getState().threads,
movements: store.getState().movements
});
});
store.subscribe(lodash.throttle(() => {
saveState({
user: store.getState().user,
chat: store.getState().chat,
exchange: store.getState().exchange,
comments: store.getState().comments,
subjects: store.getState().subjects,
threads: store.getState().threads,
movements: store.getState().movements
});
}, 1000));
export default preloadedState => {
return createStore(rootReducer, preloadedState)
}

View File

@ -12,8 +12,13 @@ const deactivate = item => ({
type: types.DEACTIVATE, item
})
const addComment = item => ({
type: types.ADD_COMMENT, item
})
export default {
getSubjectComments,
activate,
deactivate
deactivate,
addComment
}

0
src/stores/subjects/duck/index.js 100644 → 100755
View File

View File

@ -1,8 +1,9 @@
import actions from './actions'
import { address } from './../../apiAddress'
const fetchSubjectComments = async (subject) => {
const response = await
fetch('http://localhost:8001/index/subject/' + subject.id + '/comment', {
fetch(address + '/index/subject/' + subject.id + '/comment', {
method: 'GET',
credentials: 'same-origin'
});
@ -24,7 +25,7 @@ export const getSubjectComments = (data) =>
const fetchAddSubject = async (data) => {
const response = await
fetch('http://localhost:8001/index/thread/' + data.thread_id + '/subject', {
fetch(address + '/index/thread/' + data.thread_id + '/subject', {
method: 'POST',
credentials: 'same-origin',
body: JSON.stringify(data)
@ -39,7 +40,7 @@ const fetchAddSubject = async (data) => {
const fetchPutSubject = async (data) => {
const response = await
fetch('http://localhost:8001/index/subject/' + data.id, {
fetch(address + '/index/subject/' + data.id, {
method: 'PUT',
credentials: 'same-origin',
body: JSON.stringify(data)
@ -54,7 +55,7 @@ const fetchPutSubject = async (data) => {
const fetchDeleteSubject = async (data) => {
const response = await
fetch('http://localhost:8001/index/subject/' + data.id, {
fetch(address + '/index/subject/' + data.subject_id, {
method: 'DELETE',
credentials: 'same-origin',
body: JSON.stringify(data)

View File

@ -34,6 +34,11 @@ const subjectReducer = (state = INITIAL_STATE, action) => {
actualSubjectAuthorID: -1,
isActive: false
}
case types.ADD_COMMENT:
return {
...state,
commentsList: [...state.commentsList, action.item]
}
default:
return state;
}

4
src/stores/subjects/duck/types.js 100644 → 100755
View File

@ -1,9 +1,11 @@
const GET_SUBJECT_COMMENTS = 'GET_SUBJECT_COMMENTS'
const ACTIVATE = 'ACTIVATE'
const DEACTIVATE = 'DEACTIVATE'
const ADD_COMMENT = 'ADD_COMMENT'
export default{
GET_SUBJECT_COMMENTS,
ACTIVATE,
DEACTIVATE
DEACTIVATE,
ADD_COMMENT
}

View File

0
src/stores/threads/duck/index.js 100644 → 100755
View File

View File

@ -1,9 +1,10 @@
import actions from './actions'
import { address } from './../../apiAddress'
const fetchGetAll = async () => {
const response = await
fetch (
'http://localhost:8001/index/thread', {
address + '/index/thread', {
method: 'GET',
credential: 'same-origin'
}
@ -14,7 +15,7 @@ const fetchGetAll = async () => {
const fetchGetSubjects = async (threadID) => {
const response = await
fetch(
'http://localhost:8001/index/thread/' + threadID + '/subject', {
address + '/index/thread/' + threadID + '/subject', {
method: 'GET',
credential: 'same-origin'
}
@ -22,6 +23,43 @@ const fetchGetSubjects = async (threadID) => {
return response.json()
}
const fetchAddThread = async (data) => {
const response = await
fetch(
address + '/index/thread', {
method: 'POST',
credential: 'same-origin',
body: JSON.stringify(data)
}
)
return response.json()
}
const fetchUpdateThread = async (data) => {
const response = await
fetch(
address + '/index/thread/' + data.id, {
method: 'PUT',
credential: 'same-origin',
body: JSON.stringify(data)
}
)
return response.json()
}
const fetchDeleteThread = async (data) => {
const response = await
fetch(
address + '/index/thread/' + data.thread_id, {
method: 'DELETE',
credential: 'same-origin',
body: JSON.stringify(data)
}
)
return response.json()
}
export const getAllThreads = () =>
async (dispatch) => {
const allThreads = await fetchGetAll()
@ -41,3 +79,18 @@ export const getThreadSubjects = (data) =>
dispatch( actions.activate(data) )
dispatch( actions.getThreadSubjects(subjects) )
}
export const addThread = (data) =>
async (dispatch) => {
const subjects = await fetchAddThread(data)
}
export const updateThread = (data) =>
async (dispatch) => {
const subjects = await fetchUpdateThread(data)
}
export const deleteThread = (data) =>
async (dispatch) => {
const subjects = await fetchDeleteThread(data)
}

View File

0
src/stores/threads/duck/types.js 100644 → 100755
View File

0
src/stores/user/duck/actions.js 100644 → 100755
View File

0
src/stores/user/duck/index.js 100644 → 100755
View File

21
src/stores/user/duck/operations.js 100644 → 100755
View File

@ -1,11 +1,12 @@
import actions from './actions'
import { address } from './../../apiAddress'
var jwtDecode = require('jwt-decode')
const fetchLogin = async (user) => {
const response = await
fetch (
'http://localhost:8001/index/authUser', {
address + '/index/authUser', {
method: 'POST',
credential: 'same-origin',
body: JSON.stringify(user),
@ -16,7 +17,7 @@ const fetchLogin = async (user) => {
const fetchLogout = async (userToken) => {
fetch (
'http://localhost:8001/index/authUser', {
address + '/index/authUser', {
method: 'DELETE',
credential: 'same-origin',
body: JSON.stringify(userToken),
@ -26,7 +27,7 @@ const fetchLogout = async (userToken) => {
const fetchUpdate = async (user) => {
fetch (
'http://localhost:8001/index/user/' + user.id, {
address + '/index/user/' + user.id, {
method: 'PUT',
credential: 'same-origin',
body: JSON.stringify(user),
@ -35,7 +36,7 @@ const fetchUpdate = async (user) => {
const fetchRegister = async (user) => {
fetch (
'http://localhost:8001/index/user', {
address + '/index/user', {
method: 'POST',
credential: 'same-origin',
body: JSON.stringify(user),
@ -46,12 +47,12 @@ const fetchRegister = async (user) => {
const fetchGetAllUsers = async () => {
const response = await
fetch (
'http://localhost:8001/index/user', {
address + '/index/user', {
method: 'GET',
credential: 'same-origin'
}
)
const json = await response.json()
const json = response.json()
return json
}
@ -61,9 +62,7 @@ export const createSession = (data) =>
const token = await fetchLogin(data)
let user = jwtDecode(token.token)
let allUsers = 'None'
if ( user.payload.privilige > 1 )
allUsers = await fetchGetAllUsers()
let allUsers = await fetchGetAllUsers()
let userFull = {
token: token.token,
@ -79,7 +78,7 @@ export const createSession = (data) =>
}
export const updateSession = (data) =>
async (dispatch) => {
async () => {
await fetchUpdate(data)
}
@ -90,6 +89,6 @@ export const deleteSession = (data) =>
}
export const registerUser = (data) =>
async (dispatch) => {
async () => {
await fetchRegister(data)
}

8
src/stores/user/duck/reducers.js 100644 → 100755
View File

@ -7,7 +7,8 @@ const INITIAL_STATE = {
privilige: '',
avatar: '',
token: '',
isActive: false
isActive: false,
allUsersList: []
}
const userReducer = (state = INITIAL_STATE, action) => {
@ -20,11 +21,12 @@ const userReducer = (state = INITIAL_STATE, action) => {
email: action.item.email,
avatar: action.item.avatar,
token: action.item.token,
isActive: true,
allUsersList: action.item.allUsersList
allUsersList: action.item.allUsersList,
isActive: true
}
case types.LOGOUT_USER:
return {
id: -1,
isActive: false
}
default:

0
src/stores/user/duck/types.js 100644 → 100755
View File

44
src/styles/elements.scss 100644 → 100755
View File

@ -5,6 +5,12 @@
margin: auto;
}
@mixin scrollStyle {
width: 10px;
height: 10px;
background-color: rgba(22,28,29,0.5);
}
@mixin inputStyle {
width: 200px;
height: 35px;
@ -26,7 +32,7 @@
border: 0px;
border-radius: 10px;
font-size: 12pt;
color: rgba(117,82,29,1);
color: rgba(148,104,36,1); //rgba(117,82,29,1)
background-color: rgba(22,28,29,1);
transition-duration: 0.5s;
@ -41,14 +47,21 @@
}
}
@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,700);
@mixin fontStyle {
color: rgba(117,82,29,1);
color: rgba(148,104,36,1); //rgba(117,82,29,1)
font-family: 'Ubuntu';
font-size: 20px;
margin-top: 0;
margin-bottom: 10px;
}
@mixin backgroundDivMenubarStyle{
@mixin backgroundColorOnly {
background-color: rgba(22,28,29,0.4);
}
@mixin backgroundDivMenubarStyle {
background-color: rgba(22,28,29,0.2);
border-bottom: 1px solid;
border-color: rgba(117,82,29,0.7);
@ -89,3 +102,28 @@
rgba(9,17,121,0.1) 10%,
rgba(0,212,255,0) 50%);
}
.deleteButton {
width: 20px;
height: 20px;
background-color: rgba(131, 28, 20, 1);
border-radius: 2px;
color: white;
}
.imageFullStyle {
top: 0;
left: 0;
position: fixed;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
img {
margin: auto;
margin-top: 2.5%;
width: auto;
height: 90%;
}
}

5
src/styles/forumRatings.scss 100644 → 100755
View File

@ -14,11 +14,14 @@ $widthRT: 40px;
width: 1px;
height: 250px;
background-color: rgba(117,82,29,1);
border: solid 1px;
border-color: rgba(117,82,29,1);
margin: auto;
}
.ratingValue {
width: $widthRT;
height: 250px;
transition-duration: 0.5s;
}

4
src/styles/general.scss 100644 → 100755
View File

@ -2,7 +2,11 @@
body {
margin: 0 auto;
overflow-y: hidden;
::-webkit-scrollbar {
@include scrollStyle
}
input {
@include inputStyle
}

4
src/styles/index.scss 100644 → 100755
View File

@ -28,10 +28,10 @@
margin-right: auto;
margin-left: auto;
@include BigButtonStyle
@include BigButtonStyle;
input {
@include inputStyle
@include inputStyle;
width: 100%;
}

View File

@ -0,0 +1,201 @@
@import 'index';
@import 'elements';
@mixin ChatMessageStyle {
padding-top: 10px;
padding-left: 10px;
padding-right: 10px;
padding-bottom: 10px;
border-radius: 10px;
font-size: 13px;
max-width: 190px;
font-family: Ubuntu;
text-align: justify;
}
@mixin ChatWindowStyle {
position: fixed;
height: 400px;
width: 300px;
border-radius: 10px 10px 0px 0px;
margin-left: 50px;
margin-top: -50px;
&:hover {
border-radius: 10px 10px 0px 0px;
}
.chatMenuBar {
width: 300px;
height: 40px;
padding-top: 10px;
border-radius: 10px 10px 0px 0px;
background-color: rgba(22,28,29,0.8);
transition-duration: 0.2s;
&:hover {
color: rgba(22,28,29,1);
background-color: rgba(117,82,29,1);
transition-duration: 0.2s;
}
}
.chatBody {
width: 100%;
height: 100%;
.lobbyMessage {
width: 100%;
height: 50px;
border-top: 1px dashed;
input {
width: 50%;
}
button {
margin-left: 5%;
width: 40%;
}
.lobbyName {
margin-top: 15px;
width: 45%;
padding-left: 5%;
float: left;
text-align: left;
font-family: Ubuntu;
font-size: 17px;
}
}
.listMessage {
width: 100%;
height: 250px;
border-top: 1px dashed;
overflow-y: scroll;
overflow-x: hidden;
.chatListItem {
padding: 20px;
font-family: Ubuntu;
text-align: left;
font-size: 14px;
}
.rowMessage {
width: 100%;
min-height: 40px;
padding-top: 10px;
padding-bottom: 10px;
display: flex;
.chatAvatar {
width: 40px;
height: 40px;
margin-right: 20px;
margin-left: 20px;
border-radius: 50px;
img {
width: 40px;
height: 40px;
}
}
.chatMessageDisplay {
display: block;
padding-right: 10px;
.userMessage {
@include ChatMessageStyle;
color: rgba(22,28,29,1);
background-color: rgba(117,82,29,1);
}
.otherMessage {
@include ChatMessageStyle;
border: 1px solid;
}
.messageWithImage {
border-radius: 10px 10px 0px 0px;
border-bottom: 0px;
}
img {
width: 100%;
height: auto;
}
}
}
}
.textMessage {
width: 100%;
height: 50px;
border-top: 1px dashed;
input {
margin-left: 2%;
width: 55%;
}
input.inputFile {
margin-right: -8%;
opacity: 0;
}
img.inputFile {
width: 10%;
height: 8%;
margin-left: -10%;
margin-top: 2%;
position: absolute;
z-index: -1;
}
.inputFile {
width: 15%;
}
button {
margin-left: 2%;
width: 20%;
}
}
}
}
.chatWindowHide {
@include BigButtonStyle;
@include ChatWindowStyle;
img {
opacity: 1;
}
}
.chatWindowChangeLobby {
@include BigButtonStyle;
@include ChatWindowStyle;
margin-top: -350px;
img {
opacity: 1;
}
}
.chatWindowOpen {
@include BigButtonStyle;
@include ChatWindowStyle;
margin-top: -400px;
img {
opacity: 1;
}
}

View File

@ -0,0 +1,257 @@
@import 'elements';
.indexExchange {
position: relative;
z-index: 0;
overflow: hidden;
width: 100%;
padding-top: 175px; //175px
margin-left: auto;
margin-right: auto;
}
@mixin centerEx {
margin-left: auto;
margin-right: auto;
}
@mixin exchangeChart {
width: 100%;
height: 600px; //600px
overflow: hidden;
overflow-x: scroll;
.chart {
height: 100%;
@include centerEx;
.sectionChart {
width: 10px;
height: 100%;
margin-right: 5px;
float: left;
opacity: 0.6;
&:hover {
opacity: 1;
}
.sectionCandle {
width: 100%;
height: 400px;
@include centerEx;
.candle {
width: 100%;
height: auto;
.candleMaxValue {
@include centerEx;
width: 1px;
}
.candleHigh {
width: 100%;
}
.candleLow {
width: 100%;
}
.candleMinValue {
@include centerEx;
width: 1px;
}
}
}
.sectionVolumen {
width: 100%;
height: 200px;
@include centerEx;
.volumen {
width: 100%;
height: 20px;
background: rgba(0,0,0,0.3);
}
}
}
}
}
.exchangeChartGuest {
@include exchangeChart;
margin-top: 5vh;
}
.exchangeChartUser {
@include exchangeChart;
}
@mixin exchangeInterface {
z-index: -1;
width: 100%;
height: 70%;
position: fixed;
top: 15%;
right: 0px;
.candleInformation {
width: 100%;
height: auto;
padding-top: 10px;
padding-bottom: 30px;
margin-left: auto;
margin-right: auto;
p {
width: 16.66%;
text-align: center;
float: left;
font-size: 15px;
}
}
}
.exchangeEmptySpace {
@include exchangeInterface;
}
.exchangeInterface {
@include exchangeInterface;
}
.exchangeTriggerDativeY {
z-index: -1;
position: fixed;
width: 100vw;
height: 1px;
background-color: rgba(117,82,29,1);
transform: margin 700ms;
}
.exchangeTriggerDativeX {
z-index: -1;
position: fixed;
width: 1px;
height: 590px;
background-color: rgba(117,82,29,1);
transform: margin 700ms;
}
#exchangeInterfaceTwo {
background: rgba(0,0,0,0.1);
}
@mixin gapBetweenSectionsEx {
border-right: 2px dashed;
border-color: rgba(117,82,29,0.7);
}
@mixin exchangeDivInterface {
width: 31.25%;
height: 94%;
float: left;
padding-left: 1%;
padding-right: 1%;
padding-top: 10px;
overflow: hidden;
p {
font-size: 16px;
}
@include gapBetweenSectionsEx
}
.exchangeTriggerDiv {
@include exchangeDivInterface;
form {
width: 100%;
float: left;
display: flex;
p {
padding-top: 10px;
width: 50%;
text-align: center;
}
button {
width: 50%;
}
}
p {
float: left;
width: 50%;
height: 20px;
text-align: center;
}
.triggerItemList {
width: 100%;
height: 75px;
overflow-y: scroll;
.triggerItem {
width: 100%;
height: 20px;
p {
width: 100%;
}
}
}
}
.exchangePrognosisDiv {
@include exchangeDivInterface;
input {
width: 100%;
float: left;
}
p {
width: 50%;
height: 10px;
float: left;
padding-top: 10px;
text-align: center;
&:last-of-type {
width: 100%;
}
}
}
.exchangeNotificationsDiv {
@include exchangeDivInterface;
border-right: 0px;
p {
text-align: center;
}
.notifyList {
overflow-y: scroll;
height: 120px;
p {
width: 90%;
float: left;
}
button {
margin-left: 2.5%;
float: left;
}
}
}

37
src/styles/indexForum.scss 100644 → 100755
View File

@ -6,7 +6,7 @@
}
.indexForum {
@include backgroundDefaultDivStyle
@include backgroundDefaultDivStyle;
position: relative;
z-index: 0;
@ -48,8 +48,8 @@
}
.forumTitle {
@include forumDiv
@include gapTopBetweenElements
@include forumDiv;
@include gapTopBetweenElements;
p {
font-size: 50px;
float: left;
@ -75,7 +75,7 @@
}
.forumItemsList {
@include gapTopBetweenElements
@include gapTopBetweenElements;
.forumListItem:last-child{
border-bottom: 0px dashed;
@ -88,7 +88,7 @@
padding-left: 5%;
padding-top: 15px;
@include gapBetweenItems
@include gapBetweenItems;
p:first-child {
font-size: 30px;
@ -99,7 +99,8 @@
float: right;
text-align: right;
padding-top: 10px;
min-width: 130px;
min-width: 120px;
text-align: right;
}
@ -135,7 +136,7 @@
transition-duration: 0.5s;
display: flex;
@include gapBetweenItems
@include gapBetweenItems;
&:last-child{
border-bottom: 1px;
@ -147,7 +148,7 @@
padding: 50px;
padding-bottom: 30px;
text-align: center;
@include gapBetweenSections
@include gapBetweenSections;
img {
width: 200px;
@ -166,7 +167,7 @@
word-wrap: break-word;
@include gapBetweenSections
@include gapBetweenSections;
}
.commentRating {
width: 15%;
@ -181,22 +182,26 @@
}
.forumFormSubject {
@include forumDiv
@include forumDiv;
height: auto;
display: flex;
transition-duration: 0.5s;
@include gapTopBetweenElements
@include gapTopBetweenElements;
form {
width: 100%;
}
input, select {
input {
width: 100%;
float: left;
text-align: left;
}
select {
width: 100%;
float: left;
}
textarea {
width: 100%;
height: 200px;
@ -213,13 +218,13 @@
}
.forumFormComment {
@include forumDiv
@include forumDiv;
height: auto;
display: flex;
transition-duration: 0.5s;
@include gapTopBetweenElements
@include gapTopBetweenElements;
textarea {
width: 100%;
height: 200px;
@ -235,7 +240,7 @@
}
.forumFoot {
@include forumDiv
@include forumDiv;
button {
float: right;
}

0
src/styles/menuBar.scss 100644 → 100755
View File