Skip to content

Commit

Permalink
Merge pull request #132 from jacobrs/add_members
Browse files Browse the repository at this point in the history
#127, #131 Add members
  • Loading branch information
jacobrs committed Apr 5, 2017
2 parents ecf7fea + 90ced48 commit 90e3682
Show file tree
Hide file tree
Showing 12 changed files with 264 additions and 41 deletions.
22 changes: 22 additions & 0 deletions client/modules/User/UserActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export const CREATE_GROUP = 'CREATE_GROUP';
export const SET_CURRENT_STUDY_GROUP = 'SET_CURRENT_STUDY_GROUP';
export const PREPARE_CHAT_MESSAGES = 'PREPARE_CHAT_MESSAGES';
export const PREPARE_CHAT_MESSAGE = 'PREPARE_CHAT_MESSAGE';
export const SHOW_SEARCH_RESULTS = 'SHOW_SEARCH_RESULTS';
export const ADD_USER_TO_CHAT = 'ADD_USER_TO_CHAT';

// Auth Pages
export const DASHBOARD_PAGE = 'DASHBOARD_PAGE';
Expand Down Expand Up @@ -170,6 +172,26 @@ export function prepareChatMessages(messages) {
};
}

export function getUsersByEmailRequest(term){
let request = `users/search/${term}`;
return (dispatch) => {
return callApi(request).then(res => dispatch(showUsersByEmail(res.users)));
};
}

export function showUsersByEmail(users){
return {
type: SHOW_SEARCH_RESULTS,
users,
}
}

export function addUserToChat(guid, cuid){
return (dispatch) => {
return callApi(`studyGroups/${guid}/add/${cuid}`);
};
}

export function prepareChatMessage(message) {
return {
type: PREPARE_CHAT_MESSAGE,
Expand Down
35 changes: 33 additions & 2 deletions client/modules/User/UserReducer.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import { ADD_USER, UPDATE_USER, LOGIN_USER, AUTHENTICATE_SESSION, FAILED_AUTHENTICATION, LOGOUT_USER, SET_CURRENT_STUDY_GROUP, PREPARE_CHAT_MESSAGES, PREPARE_CHAT_MESSAGE } from './UserActions';
import {
ADD_USER,
UPDATE_USER,
LOGIN_USER,
AUTHENTICATE_SESSION,
FAILED_AUTHENTICATION,
LOGOUT_USER,
SET_CURRENT_STUDY_GROUP,
PREPARE_CHAT_MESSAGES,
PREPARE_CHAT_MESSAGE,
SHOW_SEARCH_RESULTS
} from './UserActions';

import { getColorFromUserIndex } from './components/ChatComponent/ChatComponent';
import React from 'react';

// Initial State
const initialState = { data: [], user: null, currentStudyGroup: -1, chat: { messages: [] } };
const initialState = { data: [], user: null, currentStudyGroup: -1, chat: { messages: [] }, search: [] };

const UserReducer = (state = initialState, action) => {
switch (action.type) {
Expand All @@ -17,6 +28,7 @@ const UserReducer = (state = initialState, action) => {
user: action.user,
currentStudyGroup: state.currentStudyGroup,
chat: state.chat,
search: [],
};
case LOGIN_USER: {
const user = (action.response.statusCode === 200) ? action.response.user : null;
Expand All @@ -25,6 +37,7 @@ const UserReducer = (state = initialState, action) => {
user,
currentStudyGroup: state.currentStudyGroup,
chat: state.chat,
search: [],
};
}
case AUTHENTICATE_SESSION: {
Expand All @@ -34,27 +47,31 @@ const UserReducer = (state = initialState, action) => {
user,
currentStudyGroup: state.currentStudyGroup,
chat: state.chat,
search: [],
};
}
case FAILED_AUTHENTICATION: {
return {
user: null,
currentStudyGroup: -1,
chat: initialState.chat,
search: [],
};
}
case LOGOUT_USER: {
return {
user: null,
currentStudyGroup: -1,
chat: initialState.chat,
search: [],
};
}
case SET_CURRENT_STUDY_GROUP: {
return {
user: state.user, // Not sure if this is necessary
currentStudyGroup: action.studyGroupIndex,
chat: state.chat,
search: [],
};
}
case PREPARE_CHAT_MESSAGES: {
Expand All @@ -68,6 +85,7 @@ const UserReducer = (state = initialState, action) => {
user: state.user,
currentStudyGroup: state.currentStudyGroup,
chat: { messages },
search: [],
};
}
case PREPARE_CHAT_MESSAGE: {
Expand All @@ -76,8 +94,21 @@ const UserReducer = (state = initialState, action) => {
user: state.user,
currentStudyGroup: state.currentStudyGroup,
chat: state.chat,
search: [],
};
}
case SHOW_SEARCH_RESULTS: {
if(action.users == undefined){
action.users = [];
}

return {
user: state.user,
currentStudyGroup: state.currentStudyGroup,
chat: state.chat,
search: action.users
};
}
default:
return state;
}
Expand Down
61 changes: 58 additions & 3 deletions client/modules/User/components/ChatComponent/ChatComponent.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,60 @@
#message-area {
background-color: white;
overflow-y:scroll;
height: 90%;
background-color: white;
overflow-y:scroll;
height: calc(100% - 40px - 4em);
z-index: 10;
padding:1em;
font-size: 11pt;
}

#message-input {
height: 40px;
}

#message-wrapper {
height: 100%;
padding:0px;
}

#message-send:hover{
cursor: pointer;
}

#chat-menu{
background:#446CB3;
height:4em;
width:100%;
z-index: -5;
border-top:1px #FFF solid;
}

#chat-title{
line-height: 3em;
padding-left: 1em;
padding-right:1em;
font-size: 12pt;
}

#add-link{
float:right;
padding:1.2em;
}

#add-link:hover{
cursor:pointer;
color:rgba(255,255,255,0.6);
}

#table{
font-size:12pt;
margin-bottom:0px;
margin-top:1em;
}

#table tbody tr td:hover{
cursor: pointer;
}

[type=button]:hover{
cursor: pointer;
}
102 changes: 81 additions & 21 deletions client/modules/User/components/ChatComponent/ChatComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,7 @@ import io from 'socket.io-client';
import styles from './ChatComponent.css';

const COLORS = [
'Red',
// 'Maroon', ugly color
'Yellow',
// 'Olive', also ugly color
'Lime',
'Green',
'Aqua',
'Teal',
'Blue',
'Navy',
'Fuchsia',
'Purple',
'Black',
];

// Ensure we have a color for every user, if we are out of colors just wrap back around.
Expand All @@ -30,27 +19,26 @@ export class ChatComponent extends Component {
super(props);
this.state = { value: '' };
this.socket = null;
this.addUserToChat = this.addUserToChat.bind(this);
this.searchForUsers = this.searchForUsers.bind(this);
this.sendMessage = this.sendMessage.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.onMessageReceive = this.onMessageReceive.bind(this);
}

componentWillMount() {
console.log('Will Mount');
this.chatTitle = (this.props.users.currentStudyGroup == -1)?"":this.props.users.user.studyGroups[this.props.users.currentStudyGroup].groupName;
this.socket = io.connect();
this.socket.emit('UserSignedIn', `${this.props.users.user.firstName} ${this.props.users.user.lastName}`);
this.socket.on('UpdateMessages', this.onMessageReceive);

//this.props.setChat(0);
}

componentWillUpdate(nextProps, nextState) {

this.chatTitle = (this.props.users.currentStudyGroup == -1)?"":this.props.users.user.studyGroups[this.props.users.currentStudyGroup].groupName;
}

componentWillUnmount() {
console.log('Will Unmount');
this.socket.disconnect();
}

Expand Down Expand Up @@ -79,20 +67,92 @@ export class ChatComponent extends Component {
}
}

showAddModal(){
$('#addModal').appendTo('body').modal('show');
}

closeAddModal(){
$('#addModal').modal('hide');
}

searchForUsers(){
this.props.getUsersByEmailRequest($("#search-term").val());
}

addUserToChat(uid){
let guid = this.props.users.user.studyGroups[this.props.users.currentStudyGroup].guid;
if(uid != undefined){
alert("User Added!");
this.props.addUserToChat(guid, uid);
}
this.closeAddModal();
}

// Display form
render() {
if (this.props.users.currentStudyGroup <= -1) {
return null;
}

if(this.props.users.search.length < 1){
this.props.users.search.push({firstName:"N/A", lastName:"N/A", email:"N/A"});
}

return (
<div className="col-md-9">
<div className="col-md-9 animated fadeInRight" id={styles['message-wrapper']}>
<div id={styles['chat-menu']}>
<span id={styles['chat-title']}>{this.chatTitle}</span>
<span id={styles['add-link']} onClick={this.showAddModal}><i className="fa fa-plus"></i> Add Members</span>
</div>
<div className="row-md-3 border rounded" id={styles['message-area']}>
{this.props.users.chat.messages}
</div>
<div className="row">
<textarea className="col-md-11 form-control" rows="3" value={this.state.value} onKeyDown={this.handleKeyDown} onChange={this.handleChange} ></textarea>
<button className="col-md-1 btn btn-primary" onClick={this.sendMessage}>Send</button>
<div className="row" id={styles['message-input']}>
<textarea className="col-md-9 form-control" rows="3" placeholder="Write a message to the group"
value={this.state.value} onKeyDown={this.handleKeyDown} onChange={this.handleChange} ></textarea>
<button className="col-md-3 btn btn-primary" onClick={this.sendMessage} id={styles['message-send']}>Send</button>
</div>

<div className="modal fade" id="addModal" tabIndex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLabel">Add a new member</h5>
<button type="button" className="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div className="modal-body">
<form>
<div className="form-group">
<label htmlFor="recipient-name" className="form-control-label">Search by Email:</label>
<input type="text" className="form-control" onChange={this.searchForUsers} placeholder="Type an email" id="search-term"/>

<table className="table table-hover" id={styles['table']}>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{
(this.props.users.search).map((u, i) => {
return <tr onClick={() => this.addUserToChat(u.cuid)} key={i}><td>{u.firstName}</td><td>{u.lastName}</td><td>{u.email}</td></tr>;
})
}
</tbody>
</table>

</div>
</form>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" onClick={this.closeAddModal}>Close</button>
</div>
</div>
</div>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,18 @@
border-radius: 50%;
width: 100px;
height: 100px;
margin-top: 30px;
margin-bottom: 10px;
margin-left: 45px;
margin-top:.5em;
margin-bottom:.5em;
}

.editButton a:hover{
cursor:pointer;
color:#777;
}

.edit-button{
color: #3366ff;
background-color: #ffffff;
.editButton, .editButton a{
font-size:18pt;
color:#555;
text-align:right;
padding:.5em;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ function UserInfoComponent(props) {
if (props.users.user !== null) { // wait props.users not to be null
return (
<div className="col-md-3" id={styles.sidebar}>
<img className="img-circle" id={styles['circle-image']}src="/static/images/user.png" />
<div className='btn-toolbar pull-right'>
<div className='btn-group'>
<Link type="button" className={`btn btn-primary ${styles['edit-button']}`} to="/editInfo">Edit</Link>
</div>
<div className={styles.editButton}>
<Link to="/editInfo">
<i className="fa fa-wrench" aria-hidden="true"></i>
</Link>
</div>
<img className="img-circle" id={styles['circle-image']}src="/static/images/user.png" />
<h3>{props.users.user.firstName}&nbsp;{props.users.user.lastName}</h3>
<p>{props.users.user.email} </p>
<UserStudyGroupComponent users={props.users} setChat={props.setChat} />
Expand Down
Loading

0 comments on commit 90e3682

Please sign in to comment.