Browse Source

Add very basic UsersPane.

pull/1/head
Titouan Rigoudy 9 years ago
parent
commit
93fc42831d
12 changed files with 164 additions and 5 deletions
  1. +9
    -0
      src/actions/UserActions.js
  2. +3
    -0
      src/components/Header.js
  3. +5
    -2
      src/components/RoomList.js
  4. +48
    -0
      src/components/UserList.js
  5. +3
    -0
      src/constants/ActionTypes.js
  6. +32
    -0
      src/containers/UsersPane.js
  7. +2
    -0
      src/createRoutes.js
  8. +2
    -0
      src/reducers/index.js
  9. +4
    -0
      src/reducers/socket.js
  10. +36
    -0
      src/reducers/users.js
  11. +5
    -0
      src/utils/ControlRequest.js
  12. +15
    -3
      src/utils/OrderedMap.js

+ 9
- 0
src/actions/UserActions.js View File

@ -0,0 +1,9 @@
import { USER_GET_LIST } from "../constants/ActionTypes";
const UserActions = {
getList: () => ({
type: USER_GET_LIST
})
};
export default UserActions;

+ 3
- 0
src/components/Header.js View File

@ -8,6 +8,9 @@ const Header = (props) => {
<Link to="/app/rooms" activeClassName="active">
Rooms
</Link>
<Link to="/app/users" activeClassName="active">
Users
</Link>
</header>
);
};


+ 5
- 2
src/components/RoomList.js View File

@ -10,7 +10,10 @@ class RoomList extends React.Component {
}
componentDidMount() {
this.props.roomActions.getList();
const { rooms, roomActions } = this.props;
if (rooms.shouldUpdate()) {
roomActions.getList();
}
}
render() {
@ -18,7 +21,7 @@ class RoomList extends React.Component {
const children = [];
for (const [roomName, roomData] of rooms.get("byName")) {
for (const [roomName, roomData] of rooms.byName) {
children.push(
<li key={roomName}>
<Room


+ 48
- 0
src/components/UserList.js View File

@ -0,0 +1,48 @@
import React, { PropTypes } from "react";
import ImmutablePropTypes from "react-immutable-proptypes";
class UserList extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
const { users, userActions } = this.props;
if (users.shouldUpdate()) {
userActions.getList();
}
}
render() {
const { users, userActions } = this.props;
let children = [];
for (const [ userName, userData ] of users.byName) {
children.push(
<li key={userName}>
{userName}
</li>
);
}
const onClick = (event) => {
event.preventDefault();
userActions.getList();
};
return (
<div className="user-list">
<button onClick={onClick}>Refresh</button>
<ul>
{children}
</ul>
</div>
);
}
}
UserList.propTypes = {
users: ImmutablePropTypes.record.isRequired,
userActions: PropTypes.object.isRequired
};
export default UserList;

+ 3
- 0
src/constants/ActionTypes.js View File

@ -18,3 +18,6 @@ export const ROOM_LEAVE = "ROOM_LEAVE";
export const ROOM_MESSAGE = "ROOM_MESSAGE";
export const ROOM_SHOW_USERS = "ROOM_SHOW_USERS";
export const ROOM_HIDE_USERS = "ROOM_HIDE_USERS";
// User actions
export const USER_GET_LIST = "USER_GET_LIST";

+ 32
- 0
src/containers/UsersPane.js View File

@ -0,0 +1,32 @@
import React, { PropTypes } from "react";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import ImmutablePropTypes from "react-immutable-proptypes";
import UserActions from "../actions/UserActions";
import UserList from "../components/UserList";
const UsersPane = ({ users, userActions }) => {
return (
<div id="users-pane">
<UserList users={users} userActions={userActions} />
</div>
);
};
UsersPane.propTypes = {
users: ImmutablePropTypes.record.isRequired,
userActions: PropTypes.object.isRequired
};
const mapStateToProps = ({ users }) => ({ users });
const mapDispatchToProps = (dispatch) => ({
userActions: bindActionCreators(UserActions, dispatch)
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(UsersPane);

+ 2
- 0
src/createRoutes.js View File

@ -3,6 +3,7 @@ import { Route, IndexRoute } from 'react-router';
import ConnectPage from "./containers/ConnectPage";
import RoomsPane from "./containers/RoomsPane";
import UsersPane from "./containers/UsersPane";
import SolsticeApp from "./components/SolsticeApp";
@ -25,6 +26,7 @@ const createRoutes = (store) => {
<Route path="app" onEnter={requireLoggedIn} component={SolsticeApp}>
<Route path="rooms(/:roomNameHash)" component={RoomsPane} />
<Route path="users(/:userNameHash)" component={UsersPane} />
</Route>
</Route>
);


+ 2
- 0
src/reducers/index.js View File

@ -4,11 +4,13 @@ import { reducer as form } from "redux-form";
import login from "./login";
import rooms from "./rooms";
import socket from "./socket";
import users from "./users";
const rootReducer = combineReducers({
login,
rooms,
socket,
users,
form
});


+ 4
- 0
src/reducers/socket.js View File

@ -79,6 +79,10 @@ export default (state = initialState, { type, payload }) => {
return state;
}
case types.USER_GET_LIST:
sendRequest(ControlRequest.userList());
return state;
default:
return state;
}


+ 36
- 0
src/reducers/users.js View File

@ -0,0 +1,36 @@
import Immutable from "immutable";
import OrderedMap from "../utils/OrderedMap";
import { SOCKET_RECEIVE_MESSAGE } from "../constants/ActionTypes";
const initialState = OrderedMap();
const reduceUsersReceiveMessage = (users, message) => {
switch (message.variant) {
case "UserListResponse":
return users.updateAll(message.data.user_list,
(newUser, oldUser) => {
if (!oldUser) {
oldUser = Immutable.Map();
}
oldUser.merge(newUser);
}
);
default:
return users;
}
};
const reduceUsers = (users = initialState, action) => {
switch (action.type) {
case SOCKET_RECEIVE_MESSAGE:
return reduceUsersReceiveMessage(users, action.payload);
default:
return users;
}
};
export default reduceUsers;

+ 5
- 0
src/utils/ControlRequest.js View File

@ -25,5 +25,10 @@ export default {
room_name,
message
}]
}),
userList: () =>({
variant: "UserListRequest",
fields: []
})
};

+ 15
- 3
src/utils/OrderedMap.js View File

@ -1,9 +1,13 @@
import Immutable from "immutable";
import md5 from "md5";
// Updates should be requested every 5 minutes at most.
const UPDATE_INTERVAL_MS = 5 * 60 * 1000;
const MapRecord = Immutable.Record({
byName: Immutable.OrderedMap(),
byHash: Immutable.Map()
byName: Immutable.OrderedMap(),
byHash: Immutable.Map(),
lastUpdated: 0
});
class OrderedMap extends MapRecord {
@ -63,7 +67,15 @@ class OrderedMap extends MapRecord {
newByName = newByName.set(name, mergedData);
}
return new OrderedMap({ byName: newByName, byHash });
return new OrderedMap({
byName: newByName,
byHash,
lastUpdated: Date.now()
});
}
shouldUpdate() {
return (Date.now() - this.lastUpdated) > UPDATE_INTERVAL_MS;
}
}


Loading…
Cancel
Save