diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..34b336e --- /dev/null +++ b/run.sh @@ -0,0 +1,2 @@ +sudo sysctl fs.inotify.max_user_watches=524288 +gatsby develop \ No newline at end of file diff --git a/src/components/chat/chatConnect.js b/src/components/chat/chatConnect.js new file mode 100644 index 0000000..0861e83 --- /dev/null +++ b/src/components/chat/chatConnect.js @@ -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 ( +
+ + +
+ ) + else + return ( +
+
+ Lobby: { chat.lobby } +
+ +
+ ) +} + +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) \ No newline at end of file diff --git a/src/components/chat/indexChat.js b/src/components/chat/indexChat.js index ccbe02c..d03c537 100644 --- a/src/components/chat/indexChat.js +++ b/src/components/chat/indexChat.js @@ -1,14 +1,88 @@ 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' -const IndexChat = ({ user }) => { +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 ( -
+
setChatVisible( !chatVisible ) }> @@ -16,31 +90,93 @@ const IndexChat = ({ user }) => {
-
- - -
+
-
-
-
-
- niesamowite naprwdÄ™ nie wierygodne -
-
-
-
-
-
- xd -
-
+ { chat.host !== '' ? chat.messages.map( (message, key) => { + if ( chatImageVisible.visible ) + return ( +
setChatImageVisible( { visible: !chatImageVisible.visible, image: '' } ) }> + +
+ ) + if (message.userID === -1) + return ( +
+ ) + else if (message.userID === user.id) + return ( +
+
+ +
+
setChatImageVisible( { visible: !chatImageVisible.visible, image: message.image } ) : () => {} }> + { message.imageOnly === false ? +
+ {message.text} +
+ : +
+ } + { message.textOnly === false ? :
} +
+
+ ) + else + return ( +
+
+ +
+
setChatImageVisible( { visible: !chatImageVisible.visible, image: message.image } ) : () => {} }> + { message.imageOnly === false ? +
+ {message.text} +
+ : +
+ } + { message.textOnly === false ? :
} +
+
+ ) + } + ) + : ( chat.rooms.lenght === 0 ? + () => { + return ( +
+ Create first lobby! +
+ ) + } + : + chat.rooms.map( (room, key) => { + return ( +
+ { key + 1 }. Lobby: { room.name }, Users: { room.userCount } +
+ ) + } + ) + ) + }
-
- - + + + + +
@@ -50,10 +186,12 @@ const IndexChat = ({ user }) => { 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) \ No newline at end of file diff --git a/src/components/exchange/exchangeTriggerAdd.js b/src/components/exchange/exchangeTriggerAdd.js index f53935e..6ec8a3f 100644 --- a/src/components/exchange/exchangeTriggerAdd.js +++ b/src/components/exchange/exchangeTriggerAdd.js @@ -46,7 +46,9 @@ const ExchangeTriggerAdd = ({ { exchange.userTriggers .sort( (a, b) => b.id - a.id ) .map( (trigger, key) => ( -

{ key + 1 }. Value: { trigger.course_values_for_trigger } PLN, Date: { trigger.date_of_trigger }, Status { trigger.status === 1 ? 'Enabled' : 'Disabled' }

+
+

{ key + 1 }. Value: { trigger.course_values_for_trigger } PLN, Date: { trigger.date_of_trigger }, Status { trigger.status === 1 ? 'Enabled' : 'Disabled' }

+
) ) }
diff --git a/src/components/useInterval.js b/src/components/useInterval.js index d15ade0..324d354 100644 --- a/src/components/useInterval.js +++ b/src/components/useInterval.js @@ -18,3 +18,5 @@ export const useInterval = (callback, delay) => { } }, [delay]); } + +export default useInterval diff --git a/src/stores/chat/duck/action.js b/src/stores/chat/duck/action.js deleted file mode 100644 index c743fc6..0000000 --- a/src/stores/chat/duck/action.js +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/src/stores/chat/duck/actions.js b/src/stores/chat/duck/actions.js new file mode 100644 index 0000000..900265e --- /dev/null +++ b/src/stores/chat/duck/actions.js @@ -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 +} \ No newline at end of file diff --git a/src/stores/chat/duck/operations.js b/src/stores/chat/duck/operations.js index a3b4327..1976bf3 100644 --- a/src/stores/chat/duck/operations.js +++ b/src/stores/chat/duck/operations.js @@ -1,29 +1,34 @@ import actions from './actions' -import { webSocketAddress } from './../../apiAddress' +import { webSocketAddress, address } from './../../apiAddress' -// export const chatConnect = ( lobby ) => -// async ( dispatch ) => { -// const host = webSocketAddress + '' + lobby; -// try { -// dispatch(actions.wsConnect(host)); -// } catch { -// console.log('chat connect error'); -// } -// } - -export const chatOnOpen = ( event ) => +export const chatOnOpen = ( data ) => async ( dispatch ) => { - console.log('websocket open', event.target.url) - dispatch(actions.wsConnected(event.target.url)) + dispatch(actions.wsConnect( webSocketAddress + '' + data + '/', data)) } +export const chatOnMessage = (data) => + async (dispatch) => { + dispatch(actions.wsSaveMessage(data)) + } + export const chatOnClose = () => async ( dispatch ) => { - dispatch(actions.wsDisconnected()) + dispatch(actions.wsDisconnect()) } -export const chatOnMessage = ( event ) => +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 ) => { - const payload = JSON.parse(event.data) - dispatch(actions.wsSaveMessage(payload)) + let roomList = await fetchGetRooms() + dispatch(actions.getRooms(roomList)) } \ No newline at end of file diff --git a/src/stores/chat/duck/reducers.js b/src/stores/chat/duck/reducers.js index bf2e3db..aeb1fc2 100644 --- a/src/stores/chat/duck/reducers.js +++ b/src/stores/chat/duck/reducers.js @@ -1,17 +1,45 @@ import types from './types' const INITIAL_STATE = { + host: '', lobby: '', - socket: '', - messages: [] + 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, - 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; } -} \ No newline at end of file +} + +export default chatReducer \ No newline at end of file diff --git a/src/stores/chat/duck/types.js b/src/stores/chat/duck/types.js index 2fca436..8f0a4a5 100644 --- a/src/stores/chat/duck/types.js +++ b/src/stores/chat/duck/types.js @@ -1,15 +1,13 @@ const WS_CONNECT = 'WS_CONNECT' -const WS_CONNECTING = 'WS_CONNECTING' -const WS_CONNECTED = 'WS_CONNECTED' -const WS_DISCONNECT = 'WS_DISCONNECT' -const WS_DISCONNECTED = 'WS_DISCONNECTED' +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_CONNECTING, - WS_CONNECTED, + WS_SEND, + WS_SAVE_MESSAGE, WS_DISCONNECT, - WS_DISCONNECTED, - WS_SAVE_MESSAGE + GET_ROOMS_LIST } \ No newline at end of file diff --git a/src/stores/reducers.js b/src/stores/reducers.js index 4bfb51c..22c57c3 100644 --- a/src/stores/reducers.js +++ b/src/stores/reducers.js @@ -4,12 +4,15 @@ 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, diff --git a/src/stores/store.js b/src/stores/store.js index 95c59ed..cfcdd4f 100644 --- a/src/stores/store.js +++ b/src/stores/store.js @@ -16,6 +16,7 @@ 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, @@ -27,6 +28,7 @@ store.subscribe(() => { 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, diff --git a/src/styles/elements.scss b/src/styles/elements.scss index 1a550b6..3353b84 100644 --- a/src/styles/elements.scss +++ b/src/styles/elements.scss @@ -110,3 +110,20 @@ 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%; + } +} diff --git a/src/styles/indexChat.scss b/src/styles/indexChat.scss index bb5ab94..3ea76bc 100644 --- a/src/styles/indexChat.scss +++ b/src/styles/indexChat.scss @@ -1,4 +1,5 @@ @import 'index'; +@import 'elements'; @mixin ChatMessageStyle { padding-top: 10px; @@ -13,11 +14,13 @@ 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; @@ -40,6 +43,7 @@ background-color: rgba(117,82,29,1); transition-duration: 0.2s; } + } .chatBody { width: 100%; @@ -57,6 +61,15 @@ 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 { @@ -66,6 +79,13 @@ overflow-y: scroll; overflow-x: hidden; + .chatListItem { + padding: 20px; + font-family: Ubuntu; + text-align: left; + font-size: 14px; + } + .rowMessage { width: 100%; min-height: 40px; @@ -79,18 +99,36 @@ margin-right: 20px; margin-left: 20px; border-radius: 50px; - background-color: rgba(117,82,29,1); - } - .userMessage { - @include ChatMessageStyle; - color: rgba(22,28,29,1); - background-color: rgba(117,82,29,1); + img { + width: 40px; + height: 40px; + } } + .chatMessageDisplay { + display: block; + padding-right: 10px; - .otherMessage { - @include ChatMessageStyle; - border: 1px solid; + .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; + } } } } @@ -101,10 +139,30 @@ border-top: 1px dashed; 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 { - margin-left: 5%; + margin-left: 2%; width: 20%; } } @@ -114,6 +172,21 @@ .chatWindowHide { @include BigButtonStyle; @include ChatWindowStyle; + + img { + opacity: 1; + } +} + +.chatWindowChangeLobby { + @include BigButtonStyle; + @include ChatWindowStyle; + + margin-top: -350px; + + img { + opacity: 1; + } } .chatWindowOpen { @@ -121,4 +194,8 @@ @include ChatWindowStyle; margin-top: -400px; + + img { + opacity: 1; + } } \ No newline at end of file