diff --git a/src/actions/RoomActions.js b/src/actions/RoomActions.js
index a0e5e0d..a941384 100644
--- a/src/actions/RoomActions.js
+++ b/src/actions/RoomActions.js
@@ -1,6 +1,7 @@
import {
- ROOM_SELECT,
- ROOM_JOIN
+ ROOM_JOIN,
+ ROOM_SAY,
+ ROOM_SELECT
} from "../constants/ActionTypes";
import SocketActions from "./SocketActions";
@@ -10,13 +11,21 @@ import ControlRequest from "../utils/ControlRequest";
export default ({
getRoomList: () => SocketActions.send(ControlRequest.roomList()),
+ join: (room) => SocketActions.send(ControlRequest.joinRoom(room)),
+
select: (room) => ({
type: ROOM_SELECT,
payload: room
}),
- join: (room) => ({
- type: ROOM_JOIN,
- paylod: room
- })
+ say: (room, message) => (dispatch) => {
+ dispatch(SocketActions.send(ControlRequest.sayRoom(room, message)));
+ dispatch({
+ type: ROOM_SAY,
+ payload: {
+ room_name: room,
+ message
+ }
+ });
+ }
});
diff --git a/src/actions/RoomActionsFactory.js b/src/actions/RoomActionsFactory.js
deleted file mode 100644
index a0e5e0d..0000000
--- a/src/actions/RoomActionsFactory.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import {
- ROOM_SELECT,
- ROOM_JOIN
-} from "../constants/ActionTypes";
-
-import SocketActions from "./SocketActions";
-
-import ControlRequest from "../utils/ControlRequest";
-
-export default ({
- getRoomList: () => SocketActions.send(ControlRequest.roomList()),
-
- select: (room) => ({
- type: ROOM_SELECT,
- payload: room
- }),
-
- join: (room) => ({
- type: ROOM_JOIN,
- paylod: room
- })
-});
diff --git a/src/components/ConnectForm.js b/src/components/ConnectForm.js
index 98b6d73..1fae4b1 100644
--- a/src/components/ConnectForm.js
+++ b/src/components/ConnectForm.js
@@ -3,7 +3,6 @@ import {reduxForm} from "redux-form";
import SocketStatusPane from "./SocketStatusPane";
import { STATE_CLOSED } from "../constants/socket";
-import ControlRequest from "../utils/ControlRequest";
const ConnectForm = (props) => {
const { fields: { url }, handleSubmit, socket, actions } = props;
diff --git a/src/components/RoomChatForm.js b/src/components/RoomChatForm.js
new file mode 100644
index 0000000..d36f51c
--- /dev/null
+++ b/src/components/RoomChatForm.js
@@ -0,0 +1,33 @@
+import React, {PropTypes} from "react";
+import {reduxForm} from "redux-form";
+
+const RoomChatForm = (props) => {
+ const { fields: { message }, handleSubmit, name, say } = props;
+
+ const onSubmit = handleSubmit((values) => {
+ say(name, values.message);
+ });
+
+ return (
+
+
+
+ );
+};
+
+RoomChatForm.propTypes = {
+ fields: PropTypes.object.isRequired,
+ handleSubmit: PropTypes.func.isRequired,
+ name: PropTypes.string,
+ say: PropTypes.func.isRequired
+};
+
+export default reduxForm({
+ form: "chat",
+ fields: ["message"]
+})(RoomChatForm);
+
diff --git a/src/components/RoomList.js b/src/components/RoomList.js
index 65ca86a..884c3b3 100644
--- a/src/components/RoomList.js
+++ b/src/components/RoomList.js
@@ -17,7 +17,6 @@ class RoomList extends React.Component {
const children = [];
- console.log(`Selected: "${selected}"`);
for (const [room_name, room_data] of rooms) {
const onClick = (event) => {
roomActions.select(room_name);
diff --git a/src/containers/RoomChat.js b/src/containers/RoomChat.js
index b1d0206..2c70dd1 100644
--- a/src/containers/RoomChat.js
+++ b/src/containers/RoomChat.js
@@ -1,14 +1,44 @@
import React, { PropTypes } from "react";
import { connect } from "react-redux";
-const RoomChat = ({ name }) => {
- return {name}
;
+import RoomActions from "../actions/RoomActions";
+import RoomChatForm from "../components/RoomChatForm";
+
+const RoomChat = ({ name, data, roomActions }) => {
+ if (!name) {
+ return Select a room
;
+ }
+
+ // Append all messages in the chat room.
+ const children = [];
+ let i = 0;
+ for (const { user_name, message } of data.messages) {
+ children.push(
+
+ {user_name}: {message}
+
+ );
+ i++;
+ }
+
+ return (
+
+ );
};
RoomChat.propTypes = {
- name: PropTypes.string
+ data: PropTypes.object,
+ name: PropTypes.string,
+ roomActions: PropTypes.object.isRequired
};
-export default connect(
- (state) => ({ name: state.rooms.selected })
-)(RoomChat);
+export default RoomChat;
diff --git a/src/containers/RoomsPane.js b/src/containers/RoomsPane.js
index ab1fee1..f384a97 100644
--- a/src/containers/RoomsPane.js
+++ b/src/containers/RoomsPane.js
@@ -21,7 +21,11 @@ class RoomsPane extends React.Component {
roomActions={this.props.actions.room}
selected={this.props.selected}
/>
-
+
);
}
@@ -29,7 +33,8 @@ class RoomsPane extends React.Component {
RoomsPane.propTypes = {
actions: PropTypes.object.isRequired,
- rooms: PropTypes.object.isRequired
+ rooms: PropTypes.object.isRequired,
+ selected: PropTypes.string
};
const mapStateToProps = (state) => state.rooms;
diff --git a/src/reducers/rooms.js b/src/reducers/rooms.js
index ade3b60..ac96987 100644
--- a/src/reducers/rooms.js
+++ b/src/reducers/rooms.js
@@ -2,6 +2,7 @@ import Immutable from "immutable";
import {
ROOM_JOIN,
+ ROOM_SAY,
ROOM_SELECT,
SOCKET_RECEIVE_MESSAGE
} from "../constants/ActionTypes";
@@ -11,6 +12,19 @@ const initialState = {
selected: null
};
+const reduceRoom = (old_room, new_room) => {
+ if (!old_room) {
+ return {
+ messages: Immutable.List(),
+ ...new_room
+ };
+ }
+ return {
+ ...old_room,
+ ...new_room
+ };
+};
+
const reduceRoomList = (old_rooms, room_list) => {
// First sort the room list by room name
room_list.sort((room_pair_1, room_pair_2) => {
@@ -28,28 +42,34 @@ const reduceRoomList = (old_rooms, room_list) => {
let new_rooms = Immutable.OrderedMap();
for (const [ room_name, room_data ] of room_list) {
const old_data = old_rooms.get(room_name);
- if (old_data) {
- new_rooms = new_rooms.set(room_name, {
- ...old_data,
- ...room_data
- });
- } else {
- new_rooms = new_rooms.set(room_name, room_data);
- }
+ const new_data = reduceRoom(old_data, room_data);
+ new_rooms = new_rooms.set(room_name, new_data);
}
return new_rooms;
};
-const reduceReceiveMessage = (state, payload) => {
+const reduceReceiveMessage = (rooms, payload) => {
switch (payload.variant) {
case "RoomListResponse":
- return {
- ...state,
- rooms: reduceRoomList(state.rooms, payload.data.rooms)
+ return reduceRoomList(rooms, payload.data.rooms);
+
+ case "SayRoomResponse":
+ {
+ const { room_name, user_name, message } = payload.data;
+ const room_data = rooms.get(room_name);
+ if (!room_data) {
+ console.log(`Error: room "${room_name} not found`);
+ return rooms;
+ }
+ const new_room_data = {
+ ...room_data,
+ messages: room_data.messages.push({ user_name, message })
};
+ return rooms.set(room_name, new_room_data);
+ }
default:
- return state;
+ return rooms;
}
};
@@ -57,7 +77,13 @@ export default (state = initialState, action) => {
const { type, payload } = action;
switch (type) {
case SOCKET_RECEIVE_MESSAGE:
- return reduceReceiveMessage(state, payload);
+ return {
+ ...state,
+ rooms: reduceReceiveMessage(state.rooms, payload)
+ };
+
+ case ROOM_SAY:
+ return state;
case ROOM_SELECT:
return {