Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Final merge #155

Merged
merged 16 commits into from Mar 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions README.md
@@ -1,4 +1,4 @@
<img src="https://github.com/chingu-voyages/v16-bears-03-BE/blob/project-readme/client/public/apple-touch-icon.png" title="Slack Clone" alt="Slack Clone">
<img src="assets/apple-touch-icon.png" title="Slack Clone" alt="Slack Clone">

# Slack Clone

Expand Down Expand Up @@ -30,19 +30,19 @@
## Screenshots

- Dashboard
![Screenshot](https://github.com/chingu-voyages/v16-bears-03-BE/blob/project-readme/assets/Channel-Image.png)
![Screenshot](assets/Channel-Image.png)

- Thread
![Screenshot](https://github.com/chingu-voyages/v16-bears-03-BE/blob/project-readme/assets/Thread-Image.png)
![Screenshot](assets/Thread-Image.png)

- Live Messages
![Add Comment](https://github.com/chingu-voyages/v16-bears-03-BE/blob/project-readme/assets/Add-Comment.gif)
![Add Comment](assets/Add-Comment.gif)

- Threaded Replies
![Add Thread](https://github.com/chingu-voyages/v16-bears-03-BE/blob/project-readme/assets/Add-Thread.gif)
![Add Thread](assets/Add-Thread.gif)

- Update User Details
![Update User](https://github.com/chingu-voyages/v16-bears-03-BE/blob/project-readme/assets/Update-User.gif)
![Update User](assets/Update-User.gif)
---

## Installation
Expand Down Expand Up @@ -106,4 +106,4 @@ $ npm run dev

[![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://badges.mit-license.org)

- **[MIT license](http://opensource.org/licenses/mit-license.php)**
- **[MIT license](http://opensource.org/licenses/mit-license.php)**
Binary file added assets/apple-touch-icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 6 additions & 9 deletions client/src/components/main/AppContainer.js
Expand Up @@ -40,9 +40,8 @@ const updateUser = (arr, data) => {
element.user = name;
}

if (userImage) {
element.userImage = userImage;
}
element.userImage = userImage ? userImage : null;

return element;
}
return element;
Expand Down Expand Up @@ -93,17 +92,15 @@ const reducer = (state, action) => {

case 'EDIT_THREAD': {
const updatedComments = comments.map(comment => {

if (comment._id === action.data.parentID) {
comment.thread.forEach(thread => {
if (thread._id === action.data.id) {
thread.text = action.data.text;
thread.isEdited = true;
}
});
}
return comment;

}
return comment;
});
return { channel: { ...channel, comments: updatedComments } };
}
Expand All @@ -117,8 +114,8 @@ const reducer = (state, action) => {
case 'EDIT_COMMENT': {
const updatedComments = state.channel.comments.map(comment => {
if (comment._id === action.editedComment._id) {
action.editedComment.thread = comment.thread
return action.editedComment;
action.editedComment.thread = comment.thread;
return action.editedComment;
} else {
return comment;
}
Expand Down
44 changes: 37 additions & 7 deletions client/src/components/main/chatwindow/ChatWindow.js
Expand Up @@ -33,7 +33,8 @@ const ChatWindow = props => {
const [chatState, dispatch] = useReducer(reducer, initialState);
const [threadWindow, setThreadWindow] = useState(false);
const [threadinfo, setThreadInfo] = useState({});
const {socket} = useContext(AppContext)
const [clickChange, setClickChange] = useState(1);
const { socket } = useContext(AppContext);

function getThreadInfo(id, name, date, text, user_id, userImage, thread, channelID) {
setThreadInfo({
Expand All @@ -44,15 +45,37 @@ const ChatWindow = props => {
user_id,
userImage,
thread,
channelID
channelID,
});
}

useEffect(()=>{
if(threadWindow){
socket.emit('joinThread', threadinfo.id)
useEffect(() => {
if (threadWindow) {
socket.emit('joinThread', threadinfo.id);
}
}, [socket, threadWindow, threadinfo.id])
}, [socket, threadWindow, threadinfo.id]);

useEffect(() => {
socket.on('updateUser', data => {
if (threadinfo.user_id === data.id) {
if (data.name) {
setThreadInfo(prev => {
return { ...prev, name: data.name };
});

if (data.userImage) {
setThreadInfo(prev => {
return { ...prev, userImage: data.userImage };
});
} else if (data.userImage === null) {
setThreadInfo(prev => {
return { ...prev, userImage: data.userImage };
});
}
}
}
});
}, [socket, threadinfo.user_id]);

return (
<ChatContext.Provider value={{ chatState, dispatch }}>
Expand All @@ -62,9 +85,16 @@ const ChatWindow = props => {
setThreadWindow={setThreadWindow}
getThreadInfo={getThreadInfo}
currentChannel={props.currentChannel.channel}
setClickChange={setClickChange}
/>
<CreateComment />
{threadWindow && <ThreadWindow threadinfo={threadinfo} setThreadWindow={setThreadWindow} />}
{threadWindow && (
<ThreadWindow
clickChange={clickChange}
threadinfo={threadinfo}
setThreadWindow={setThreadWindow}
/>
)}
</Container>
</ChatContext.Provider>
);
Expand Down
43 changes: 31 additions & 12 deletions client/src/components/main/chatwindow/Comment.js
Expand Up @@ -70,7 +70,18 @@ const useAvatar = (user_id, userImage, id) => {
// Comment Component

const Comment = props => {
const { id, name, date, text, user_id, userImage, isEdited, thread, channelID, refContainer } = props;
const {
id,
name,
date,
text,
user_id,
userImage,
isEdited,
thread,
channelID,
refContainer,
} = props;
const dropdown = useRef(null);
const menu = useRef(null);
const [isHidden, setIsHidden] = useHideDropdown(dropdown);
Expand Down Expand Up @@ -100,17 +111,21 @@ const Comment = props => {

const OpenThreadWindow = e => {
props.setThreadWindow(true);
props.getThreadInfo(id, name, date, text, user_id, userImage, thread, channelID );
props.setClickChange(Math.random());
props.getThreadInfo(id, name, date, text, user_id, userImage, thread, channelID);
};

const getDateDifferent = date => {
let currentDate = new Date();
let differentInTime = currentDate.getTime() - new Date(date).getTime();
let differentInDays = differentInTime / (1000 * 3600 * 24);
if (parseInt(differentInDays) > 1) {
return `${parseInt(differentInDays)} days ago`;
} else if (parseInt(differentInDays) === 1) {
return `1 day ago`;
const getDateDifferent = thread => {
if (thread.length !== 0) {
const date = thread[thread.length - 1].date;
let currentDate = new Date();
let differentInTime = currentDate.getTime() - new Date(date).getTime();
let differentInDays = differentInTime / (1000 * 3600 * 24);
if (parseInt(differentInDays) > 1) {
return `${parseInt(differentInDays)} days ago`;
} else if (parseInt(differentInDays) === 1) {
return `1 day ago`;
}
}
};

Expand All @@ -135,9 +150,13 @@ const Comment = props => {
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
<ReplyAvatar thread={thread} />
<ThreadNote onClick={OpenThreadWindow}>
{thread.length > 0 && thread.length !== 1 ? `${thread.length} replies` : '1 reply'}
{thread.length > 1
? `${thread.length} replies`
: thread.length === 1
? `${thread.length} reply`
: ''}
</ThreadNote>
<Time>{getDateDifferent(thread[thread.length - 1].date)}</Time>
<Time>{getDateDifferent(thread)}</Time>
</div>
)}
</Styled.CommentTextWrapper>
Expand Down
21 changes: 11 additions & 10 deletions client/src/components/main/chatwindow/ViewComments.js
Expand Up @@ -22,19 +22,20 @@ const ViewComments = props => {
const [isError, setIsError] = useState(false);

const { chatState } = useContext(ChatContext);
const { appState } = useContext(AppContext);
const { appState } = useContext(AppContext);

useEffect(() => {
setIsLoading(true);
try {
if (appState.channel.comments) {
setAllComments(() =>{
return appState.channel.comments.map(comment =>{
comment.channelID = appState.channel.id

return comment
})});

setAllComments(() => {
return appState.channel.comments.map(comment => {
comment.channelID = appState.channel.id;

return comment;
});
});

setIsLoading(false);
}
} catch (error) {
Expand All @@ -43,7 +44,6 @@ const ViewComments = props => {
}
}, [appState]);


useEffect(() => {
if (chatState.newComment) {
scrollToBottom(refContainer);
Expand Down Expand Up @@ -84,7 +84,8 @@ const ViewComments = props => {
refContainer={refContainer}
setThreadWindow={props.setThreadWindow}
getThreadInfo={props.getThreadInfo}
channelID = {comment.channelID}
channelID={comment.channelID}
setClickChange={props.setClickChange}
></Comment>
);
})
Expand Down
20 changes: 0 additions & 20 deletions client/src/components/main/sidebar/Sidebar.js
Expand Up @@ -19,26 +19,6 @@ function Sidebar(props) {
const [currentChannelID, setCurrentChannelID] = useState();
let errorMessage = useContext(MessageContext);

const getChannels = async () => {
setIsLoading(true);

if (localStorage.loggedIn) {
try {
const result = await axios('/api/channels', {
headers: { authorization: `bearer ${localStorage.authToken}` },
});
setAllChannels(result.data);
setIsLoading(false);
return result.data;
} catch (error) {
localStorage.clear();
setIsLoading(false);
errorMessage.set_message([{ msg: 'Unable to get channels.' }]);
setIsError(true);
}
}
};

useEffect(() => {
const getChannels = async () => {
setIsLoading(true);
Expand Down
27 changes: 19 additions & 8 deletions client/src/components/main/thread/ThreadBody.js
Expand Up @@ -11,13 +11,19 @@ function ThreadBody(props) {

const reducer = (state, action) => {
switch (action.type) {
case 'CLICK':
return [...action.threads];
case 'REPLY_THREAD':
return [...state, action.thread];
case 'DELETE_THREAD': {
const output = state.filter(thread => {
return thread._id !== action.id;
});
return output;
if (state.length === 1) {
return [];
} else {
const output = state.filter(thread => {
return thread._id !== action.id;
});
return output;
}
}
case 'EDIT_THREAD': {
const output = state.map(thread => {
Expand All @@ -37,9 +43,9 @@ function ThreadBody(props) {
if (action.data.name) {
thread.user = action.data.name;
}
if (action.data.userImage) {
thread.userImage = action.data.userImage;
}

thread.userImage = action.data.userImage ? action.data.userImage : null;

return thread;
} else {
return thread;
Expand All @@ -53,8 +59,13 @@ function ThreadBody(props) {

const [allThreads, dispatch] = useReducer(reducer, initialstate.threads);

useEffect(() => {
const threads = props.thread === undefined ? [] : props.thread;
dispatch({ type: 'CLICK', threads });
}, [props.thread, props.clickChange]);

const { socket } = useContext(AppContext);

//handles live updates to threadbody
useEffect(() => {
socket.on('post_threadBody', thread => {
Expand Down
27 changes: 17 additions & 10 deletions client/src/components/main/thread/ThreadWindow.js
@@ -1,17 +1,15 @@
import React, {useContext} from 'react';
import React, { useContext } from 'react';
import { ThreadContainer, Header } from './thread.style.js';
import { CloseButton } from '../../../theme/theme';
import Thread from './Thread';
import ThreadBody from './ThreadBody';
import { AppContext } from '../AppContainer';



function ThreadWindow(props) {
const {socket} = useContext(AppContext)
const { socket } = useContext(AppContext);

//todo:change channel's name after chanel route is set.

return (
<ThreadContainer>
<Header>
Expand All @@ -21,13 +19,22 @@ function ThreadWindow(props) {
<i># </i> Slack Clone
</p>
</div>
<CloseButton
onClick={() => {
props.setThreadWindow(false)
socket.emit('leaveThread', props.threadinfo.id)}}>X</CloseButton>
<CloseButton
onClick={() => {
props.setThreadWindow(false);
socket.emit('leaveThread', props.threadinfo.id);
}}
>
X
</CloseButton>
</Header>
<Thread threadinfo={props.threadinfo} />
<ThreadBody commentid={props.threadinfo.id} thread={props.threadinfo.thread} channelID ={props.threadinfo.channelID} />
<ThreadBody
clickChange={props.clickChange}
commentid={props.threadinfo.id}
thread={props.threadinfo.thread}
channelID={props.threadinfo.channelID}
/>
</ThreadContainer>
);
}
Expand Down