last time upgrades

front
TBS093A 2020-05-07 09:17:09 +02:00
parent f8fa7c4848
commit b65e868b91
14 changed files with 436 additions and 100 deletions

2
run.sh 100755
View File

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

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

@ -1,14 +1,88 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { chatOnMessage, getChatRooms } from '../../stores/chat/duck/operations'
import ChatConnect from './chatConnect'
import '../../styles/indexChat.scss' import '../../styles/indexChat.scss'
const IndexChat = ({ user }) => { import imageIco from '../../images/imageIco.png'
const IndexChat = ({ user, chat, chatOnMessage, getChatRooms }) => {
const [chatVisible, setChatVisible] = useState(false) 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 ( return (
<div className={ chatVisible === true ? 'chatWindowOpen' : 'chatWindowHide'}> <div className={ chatVisible === true ? (chat.host !== '' ? 'chatWindowOpen' : 'chatWindowChangeLobby') : 'chatWindowHide'}>
<div <div
className='chatMenuBar' className='chatMenuBar'
onClick={ () => setChatVisible( !chatVisible ) }> onClick={ () => setChatVisible( !chatVisible ) }>
@ -16,31 +90,93 @@ const IndexChat = ({ user }) => {
</div> </div>
<div className='chatBody'> <div className='chatBody'>
<div className='lobbyMessage'> <div className='lobbyMessage'>
<form> <ChatConnect/>
<input placeholder='lobby / room name'/>
<button type='submit'>Connect</button>
</form>
</div> </div>
<div className='listMessage'> <div className='listMessage'>
<div className='rowMessage'> { 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"> <div className="chatAvatar">
<img src={message.avatar} title={message.userName} />
</div> </div>
<div className='userMessage'> <div className='chatMessageDisplay' onClick={ message.textOnly !== true ? () => setChatImageVisible( { visible: !chatImageVisible.visible, image: message.image } ) : () => {} }>
niesamowite naprwdę nie wierygodne { 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>
</div> </div>
<div className='rowMessage'> )
else
return (
<div className='rowMessage' key={key}>
<div className="chatAvatar"> <div className="chatAvatar">
<img src={message.avatar} title={message.userName} />
</div> </div>
<div className='otherMessage'> <div className='chatMessageDisplay' onClick={ message.textOnly !== true ? () => setChatImageVisible( { visible: !chatImageVisible.visible, image: message.image } ) : () => {} }>
xd { 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>
</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>
<div className='textMessage'> <div className='textMessage'>
<form> <form onSubmit={ sendMessage }>
<input placeholder='message'/> <input
<button type='submit'>Send</button> className='inputFile'
type='file'
id='fileItem' />
<img
className='inputFile'
src={ imageIco } />
<input
placeholder='message'
ref={ inputMessageText } />
<button>
Send
</button>
</form> </form>
</div> </div>
</div> </div>
@ -50,10 +186,12 @@ const IndexChat = ({ user }) => {
const mapStateToProps = state => ({ const mapStateToProps = state => ({
user: state.user, user: state.user,
chat: state.chat
}) })
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
chatOnMessage: chat => dispatch( chatOnMessage(chat) ),
getChatRooms: chat => dispatch( getChatRooms(chat) )
}) })
export default connect(mapStateToProps, mapDispatchToProps)(IndexChat) export default connect(mapStateToProps, mapDispatchToProps)(IndexChat)

View File

@ -46,7 +46,9 @@ const ExchangeTriggerAdd = ({
{ exchange.userTriggers { exchange.userTriggers
.sort( (a, b) => b.id - a.id ) .sort( (a, b) => b.id - a.id )
.map( (trigger, key) => ( .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 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>
</div> </div>

View File

@ -18,3 +18,5 @@ export const useInterval = (callback, delay) => {
} }
}, [delay]); }, [delay]);
} }
export default useInterval

View File

@ -1,34 +0,0 @@
import types from './types'
const wsConnect = host => ({
type: types.WS_CONNECT, host
});
const wsConnecting = host => ({
type: types.WS_CONNECTING, host
});
const wsConnected = host => ({
type: types.WS_CONNECTED, host
});
const wsDisconnect = host => ({
type: types.WS_DISCONNECT, host
});
const wsDisconnected = host => ({
type: types.WS_DISCONNECTED, host
});
const wsSaveMessage = host => ({
type: types.WS_SAVE_MESSAGE, host
})
export default {
wsConnect,
wsConnecting,
wsConnected,
wsDisconnect,
wsDisconnected,
wsSaveMessage
}

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

@ -1,29 +1,34 @@
import actions from './actions' import actions from './actions'
import { webSocketAddress } from './../../apiAddress' import { webSocketAddress, address } from './../../apiAddress'
// export const chatConnect = ( lobby ) => export const chatOnOpen = ( data ) =>
// async ( dispatch ) => {
// const host = webSocketAddress + '' + lobby;
// try {
// dispatch(actions.wsConnect(host));
// } catch {
// console.log('chat connect error');
// }
// }
export const chatOnOpen = ( event ) =>
async ( dispatch ) => { async ( dispatch ) => {
console.log('websocket open', event.target.url) dispatch(actions.wsConnect( webSocketAddress + '' + data + '/', data))
dispatch(actions.wsConnected(event.target.url))
} }
export const chatOnMessage = (data) =>
async (dispatch) => {
dispatch(actions.wsSaveMessage(data))
}
export const chatOnClose = () => export const chatOnClose = () =>
async ( dispatch ) => { async ( dispatch ) => {
dispatch(actions.wsDisconnected()) dispatch(actions.wsDisconnect())
} }
export const chatOnMessage = ( event ) => const fetchGetRooms = async () => {
async ( dispatch ) => { const response = await
const payload = JSON.parse(event.data) fetch (
dispatch(actions.wsSaveMessage(payload)) 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

@ -1,17 +1,45 @@
import types from './types' import types from './types'
const INITIAL_STATE = { const INITIAL_STATE = {
host: '',
lobby: '', lobby: '',
socket: '', connected: false,
messages: [] messages: [],
rooms: []
} }
const chatReducer = ( state = INITIAL_STATE, action ) => { const chatReducer = ( state = INITIAL_STATE, action ) => {
switch (action.type) { switch (action.type) {
case types.GET_ROOMS_LIST:
return {
...state,
rooms: action.host
}
case types.WS_CONNECT: case types.WS_CONNECT:
return { return {
...state, ...state,
socket: new WebSocket(action.host) 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

@ -1,15 +1,13 @@
const WS_CONNECT = 'WS_CONNECT' const WS_CONNECT = 'WS_CONNECT'
const WS_CONNECTING = 'WS_CONNECTING' const WS_SEND = 'WS_SEND'
const WS_CONNECTED = 'WS_CONNECTED'
const WS_DISCONNECT = 'WS_DISCONNECT'
const WS_DISCONNECTED = 'WS_DISCONNECTED'
const WS_SAVE_MESSAGE = 'WS_SAVE_MESSAGE' const WS_SAVE_MESSAGE = 'WS_SAVE_MESSAGE'
const WS_DISCONNECT = 'WS_DISCONNECT'
const GET_ROOMS_LIST = 'GET_ROOMS_LIST'
export default { export default {
WS_CONNECT, WS_CONNECT,
WS_CONNECTING, WS_SEND,
WS_CONNECTED, WS_SAVE_MESSAGE,
WS_DISCONNECT, WS_DISCONNECT,
WS_DISCONNECTED, GET_ROOMS_LIST
WS_SAVE_MESSAGE
} }

View File

@ -4,12 +4,15 @@ import movementsReducer from './movements/duck'
import commentReducer from './comments/duck' import commentReducer from './comments/duck'
import subjectReducer from './subjects/duck' import subjectReducer from './subjects/duck'
import threadReducer from './threads/duck' import threadReducer from './threads/duck'
import userReducer from './user/duck' import userReducer from './user/duck'
import chatReducer from './chat/duck'
import exchangeReducer from './exchange/duck' import exchangeReducer from './exchange/duck'
const rootReducer = combineReducers({ const rootReducer = combineReducers({
user: userReducer, user: userReducer,
chat: chatReducer,
threads: threadReducer, threads: threadReducer,
subjects: subjectReducer, subjects: subjectReducer,
comments: commentReducer, comments: commentReducer,

View File

@ -16,6 +16,7 @@ console.log(store.getState())
store.subscribe(() => { store.subscribe(() => {
saveState({ saveState({
user: store.getState().user, user: store.getState().user,
chat: store.getState().chat,
exchange: store.getState().exchange, exchange: store.getState().exchange,
comments: store.getState().comments, comments: store.getState().comments,
subjects: store.getState().subjects, subjects: store.getState().subjects,
@ -27,6 +28,7 @@ store.subscribe(() => {
store.subscribe(lodash.throttle(() => { store.subscribe(lodash.throttle(() => {
saveState({ saveState({
user: store.getState().user, user: store.getState().user,
chat: store.getState().chat,
exchange: store.getState().exchange, exchange: store.getState().exchange,
comments: store.getState().comments, comments: store.getState().comments,
subjects: store.getState().subjects, subjects: store.getState().subjects,

View File

@ -110,3 +110,20 @@
border-radius: 2px; border-radius: 2px;
color: white; 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%;
}
}

View File

@ -1,4 +1,5 @@
@import 'index'; @import 'index';
@import 'elements';
@mixin ChatMessageStyle { @mixin ChatMessageStyle {
padding-top: 10px; padding-top: 10px;
@ -13,11 +14,13 @@
max-width: 190px; max-width: 190px;
font-family: Ubuntu; font-family: Ubuntu;
text-align: justify;
} }
@mixin ChatWindowStyle { @mixin ChatWindowStyle {
position: fixed; position: fixed;
height: 400px; height: 400px;
width: 300px;
border-radius: 10px 10px 0px 0px; border-radius: 10px 10px 0px 0px;
margin-left: 50px; margin-left: 50px;
@ -40,6 +43,7 @@
background-color: rgba(117,82,29,1); background-color: rgba(117,82,29,1);
transition-duration: 0.2s; transition-duration: 0.2s;
} }
} }
.chatBody { .chatBody {
width: 100%; width: 100%;
@ -57,6 +61,15 @@
margin-left: 5%; margin-left: 5%;
width: 40%; width: 40%;
} }
.lobbyName {
margin-top: 15px;
width: 45%;
padding-left: 5%;
float: left;
text-align: left;
font-family: Ubuntu;
font-size: 17px;
}
} }
.listMessage { .listMessage {
@ -66,6 +79,13 @@
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden; overflow-x: hidden;
.chatListItem {
padding: 20px;
font-family: Ubuntu;
text-align: left;
font-size: 14px;
}
.rowMessage { .rowMessage {
width: 100%; width: 100%;
min-height: 40px; min-height: 40px;
@ -79,8 +99,15 @@
margin-right: 20px; margin-right: 20px;
margin-left: 20px; margin-left: 20px;
border-radius: 50px; border-radius: 50px;
background-color: rgba(117,82,29,1);
img {
width: 40px;
height: 40px;
} }
}
.chatMessageDisplay {
display: block;
padding-right: 10px;
.userMessage { .userMessage {
@include ChatMessageStyle; @include ChatMessageStyle;
@ -92,6 +119,17 @@
@include ChatMessageStyle; @include ChatMessageStyle;
border: 1px solid; border: 1px solid;
} }
.messageWithImage {
border-radius: 10px 10px 0px 0px;
border-bottom: 0px;
}
img {
width: 100%;
height: auto;
}
}
} }
} }
@ -101,10 +139,30 @@
border-top: 1px dashed; border-top: 1px dashed;
input { input {
width: 70%; 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 { button {
margin-left: 5%; margin-left: 2%;
width: 20%; width: 20%;
} }
} }
@ -114,6 +172,21 @@
.chatWindowHide { .chatWindowHide {
@include BigButtonStyle; @include BigButtonStyle;
@include ChatWindowStyle; @include ChatWindowStyle;
img {
opacity: 1;
}
}
.chatWindowChangeLobby {
@include BigButtonStyle;
@include ChatWindowStyle;
margin-top: -350px;
img {
opacity: 1;
}
} }
.chatWindowOpen { .chatWindowOpen {
@ -121,4 +194,8 @@
@include ChatWindowStyle; @include ChatWindowStyle;
margin-top: -400px; margin-top: -400px;
img {
opacity: 1;
}
} }