minsung

Merge branch 'master' of https://bitbucket.org/vel1024/capstone

# Conflicts:
#	back/Dockerfile
#	back/prisma/Dockerfile
...@@ -9,7 +9,11 @@ RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSI ...@@ -9,7 +9,11 @@ RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSI
9 && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ 9 && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
10 && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz 10 && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz
11 11
12 +<<<<<<< HEAD
12 ENTRYPOINT [ "dockerize", "-wait", "tcp://root:prisma@mysql:3306/prisma:3306", "-timeout", "120s" ] 13 ENTRYPOINT [ "dockerize", "-wait", "tcp://root:prisma@mysql:3306/prisma:3306", "-timeout", "120s" ]
14 +=======
15 +ENTRYPOINT [ "dockerize", "-wait", "tcp://root:prisma@mysql:3306/prisma:3306", "-timeout", "60s" ]
16 +>>>>>>> 81d693438b3dd8e67a7daefac47486362f102999
13 17
14 COPY package*.json ./ 18 COPY package*.json ./
15 COPY prisma ./prisma/ 19 COPY prisma ./prisma/
......
...@@ -2242,14 +2242,6 @@ ...@@ -2242,14 +2242,6 @@
2242 "graphql-playground-html": "1.6.12" 2242 "graphql-playground-html": "1.6.12"
2243 } 2243 }
2244 }, 2244 },
2245 - "graphql-subscriptions": {
2246 - "version": "0.5.8",
2247 - "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-0.5.8.tgz",
2248 - "integrity": "sha512-0CaZnXKBw2pwnIbvmVckby5Ge5e2ecmjofhYCdyeACbCly2j3WXDP/pl+s+Dqd2GQFC7y99NB+53jrt55CKxYQ==",
2249 - "requires": {
2250 - "iterall": "^1.2.1"
2251 - }
2252 - },
2253 "graphql-tools": { 2245 "graphql-tools": {
2254 "version": "4.0.7", 2246 "version": "4.0.7",
2255 "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.7.tgz", 2247 "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.7.tgz",
...@@ -2323,6 +2315,16 @@ ...@@ -2323,6 +2315,16 @@
2323 "graphql-tools": "^4.0.0", 2315 "graphql-tools": "^4.0.0",
2324 "graphql-upload": "^8.0.0", 2316 "graphql-upload": "^8.0.0",
2325 "subscriptions-transport-ws": "^0.9.8" 2317 "subscriptions-transport-ws": "^0.9.8"
2318 + },
2319 + "dependencies": {
2320 + "graphql-subscriptions": {
2321 + "version": "0.5.8",
2322 + "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-0.5.8.tgz",
2323 + "integrity": "sha512-0CaZnXKBw2pwnIbvmVckby5Ge5e2ecmjofhYCdyeACbCly2j3WXDP/pl+s+Dqd2GQFC7y99NB+53jrt55CKxYQ==",
2324 + "requires": {
2325 + "iterall": "^1.2.1"
2326 + }
2327 + }
2326 } 2328 }
2327 }, 2329 },
2328 "has": { 2330 "has": {
......
...@@ -9,7 +9,11 @@ RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSI ...@@ -9,7 +9,11 @@ RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSI
9 && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ 9 && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
10 && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz 10 && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz
11 11
12 +<<<<<<< HEAD
12 ENTRYPOINT [ "dockerize", "-wait", "tcp://root:prisma@mysql:3306/prisma:3306", "-timeout", "120s" ] 13 ENTRYPOINT [ "dockerize", "-wait", "tcp://root:prisma@mysql:3306/prisma:3306", "-timeout", "120s" ]
14 +=======
15 +ENTRYPOINT [ "dockerize", "-wait", "tcp://root:prisma@mysql:3306/prisma:3306", "-timeout", "60s" ]
16 +>>>>>>> 81d693438b3dd8e67a7daefac47486362f102999
13 17
14 COPY ./ ./prisma/ 18 COPY ./ ./prisma/
15 19
......
1 import { prisma, isAuthenticated } from "../../../utils"; 1 import { prisma, isAuthenticated } from "../../../utils";
2 +import { NEW_MESSAGE } from "../../../topics";
2 3
3 export default { 4 export default {
4 Mutation: { 5 Mutation: {
5 - createMessage: async (_, args, { request }) => { 6 + createMessage: async (_, args, { request, pubsub }) => {
6 isAuthenticated(request); 7 isAuthenticated(request);
7 const { user } = request; 8 const { user } = request;
8 const { message, roomId } = args; 9 const { message, roomId } = args;
...@@ -46,6 +47,11 @@ export default { ...@@ -46,6 +47,11 @@ export default {
46 } else { 47 } else {
47 throw new Error("There is no room"); 48 throw new Error("There is no room");
48 } 49 }
50 +
51 + if (messageObj !== undefined) {
52 + pubsub.publish(NEW_MESSAGE, { subMessage: messageObj });
53 + }
54 +
49 return messageObj; 55 return messageObj;
50 }, 56 },
51 }, 57 },
......
1 -import { ONE_TO_ONE_MESSAGE } from "../../../topics"; 1 +import { NEW_MESSAGE } from "../../../topics";
2 2
3 export default { 3 export default {
4 Subscription: { 4 Subscription: {
5 subMessage: { 5 subMessage: {
6 subscribe: async (_, __, { pubsub }) => { 6 subscribe: async (_, __, { pubsub }) => {
7 - return pubsub.asyncIterator(ONE_TO_ONE_MESSAGE); 7 + return pubsub.asyncIterator(NEW_MESSAGE);
8 }, 8 },
9 }, 9 },
10 }, 10 },
......
1 -export const ONE_TO_ONE_MESSAGE = "one-to-one message"; 1 +export const NEW_MESSAGE = "new message";
......
1 import React from "react"; 1 import React from "react";
2 import styled from "styled-components"; 2 import styled from "styled-components";
3 -//import { parse, format } from "date-fns"; 3 +import ProfileIcon from "./ProfileIcon";
4 4
5 const MessageWrapper = styled.div` 5 const MessageWrapper = styled.div`
6 display: flex; 6 display: flex;
7 - justify-content: flex-end; 7 + justify-content: flex-start;
8 align-items: center; 8 align-items: center;
9 padding: 20px 10px; 9 padding: 20px 10px;
10 margin-top: 20px; 10 margin-top: 20px;
...@@ -13,6 +13,11 @@ const MessageWrapper = styled.div` ...@@ -13,6 +13,11 @@ const MessageWrapper = styled.div`
13 13
14 const MsgContainer = styled.div` 14 const MsgContainer = styled.div`
15 display: flex; 15 display: flex;
16 + flex-direction: row;
17 +`;
18 +
19 +const ColumnBox = styled.div`
20 + display: flex;
16 flex-direction: column; 21 flex-direction: column;
17 `; 22 `;
18 23
...@@ -20,9 +25,7 @@ const MsgBox = styled.div` ...@@ -20,9 +25,7 @@ const MsgBox = styled.div`
20 display: flex; 25 display: flex;
21 justify-content: center; 26 justify-content: center;
22 align-items: center; 27 align-items: center;
23 - background-color: #54a0ff; 28 + color: black;
24 - color: white;
25 - border-radius: 20px;
26 margin-bottom: 10px; 29 margin-bottom: 10px;
27 `; 30 `;
28 31
...@@ -42,16 +45,19 @@ const Time = styled.span` ...@@ -42,16 +45,19 @@ const Time = styled.span`
42 font-size: 15px; 45 font-size: 15px;
43 `; 46 `;
44 47
45 -export default ({ text }) => { 48 +export default ({ text, avatar }) => {
46 return ( 49 return (
47 <MessageWrapper className="MessageWrapper"> 50 <MessageWrapper className="MessageWrapper">
48 <MsgContainer> 51 <MsgContainer>
52 + <ProfileIcon avatar={avatar} />
53 + <ColumnBox>
49 <MsgBox> 54 <MsgBox>
50 <Msg> {text} </Msg> 55 <Msg> {text} </Msg>
51 </MsgBox> 56 </MsgBox>
52 <TimeBox> 57 <TimeBox>
53 - <Time></Time> 58 + <Time>1</Time>
54 </TimeBox> 59 </TimeBox>
60 + </ColumnBox>
55 </MsgContainer> 61 </MsgContainer>
56 </MessageWrapper> 62 </MessageWrapper>
57 ); 63 );
......
1 import React from "react"; 1 import React from "react";
2 import styled from "styled-components"; 2 import styled from "styled-components";
3 -import defaultProfile from "../imgs/defaultProfile.jpg";
4 3
5 const ProfileIconBox = styled.div` 4 const ProfileIconBox = styled.div`
6 display: flex; 5 display: flex;
...@@ -15,10 +14,10 @@ const ProfileIcon = styled.img` ...@@ -15,10 +14,10 @@ const ProfileIcon = styled.img`
15 src: ${(props) => props.theme.defaultProfile}; 14 src: ${(props) => props.theme.defaultProfile};
16 `; 15 `;
17 16
18 -export default () => { 17 +export default ({ avatar }) => {
19 return ( 18 return (
20 - <ProfileIconBox> 19 + <ProfileIconBox className="ProfileIconBox">
21 - <ProfileIcon src={defaultProfile} /> 20 + <ProfileIcon src={avatar} />
22 </ProfileIconBox> 21 </ProfileIconBox>
23 ); 22 );
24 }; 23 };
......
...@@ -6,20 +6,19 @@ import { ...@@ -6,20 +6,19 @@ import {
6 CREATE_MESSAGE, 6 CREATE_MESSAGE,
7 GET_ROOM_BY_NAME, 7 GET_ROOM_BY_NAME,
8 SEE_ALL_MESSAGE, 8 SEE_ALL_MESSAGE,
9 + SUBSCRIPTION_MSG,
9 } from "./ChatQueries"; 10 } from "./ChatQueries";
10 import useInput from "../../Hooks/useInput"; 11 import useInput from "../../Hooks/useInput";
11 import { toast } from "react-toastify"; 12 import { toast } from "react-toastify";
12 -//import defaultProfile from "../imgs/defaultProfile.jpg";
13 13
14 export default withRouter(({ location }) => { 14 export default withRouter(({ location }) => {
15 const { pathname } = location; 15 const { pathname } = location;
16 const roomName = pathname.slice(1, pathname.length); 16 const roomName = pathname.slice(1, pathname.length);
17 const [createMsg] = useMutation(CREATE_MESSAGE); 17 const [createMsg] = useMutation(CREATE_MESSAGE);
18 - //const { data } = useSubscription(SUBSCRIPTION_MSG);
19 18
20 const message = useInput(""); 19 const message = useInput("");
21 20
22 - let messageObj, roomNum, messageText, messageTime, newMsgObj, messageArray; 21 + let messageObj, roomNum, messageArray;
23 22
24 const { data: getRoom } = useQuery(GET_ROOM_BY_NAME, { 23 const { data: getRoom } = useQuery(GET_ROOM_BY_NAME, {
25 variables: { roomName }, 24 variables: { roomName },
...@@ -31,17 +30,26 @@ export default withRouter(({ location }) => { ...@@ -31,17 +30,26 @@ export default withRouter(({ location }) => {
31 roomNum = Number(roomId); 30 roomNum = Number(roomId);
32 } 31 }
33 32
34 - const { data: messageList } = useQuery(SEE_ALL_MESSAGE, { 33 + const { subscribeToMore, data: messageList } = useQuery(SEE_ALL_MESSAGE, {
35 variables: { roomId: roomNum }, 34 variables: { roomId: roomNum },
36 }); 35 });
36 +
37 if (messageList !== undefined) { 37 if (messageList !== undefined) {
38 messageList.seeAllMessage.map((e) => { 38 messageList.seeAllMessage.map((e) => {
39 if (e.sender.avatarUrl === "") { 39 if (e.sender.avatarUrl === "") {
40 + e.sender.avatarUrl = "../../imgs/defaultProfile.jpg";
40 } 41 }
41 }); 42 });
42 messageArray = messageList; 43 messageArray = messageList;
43 } 44 }
44 45
46 + let resultObj = subscribeToMore({
47 + document: SUBSCRIPTION_MSG,
48 + updateQuery: (prev, { subscriptionData }) => {
49 + if (!subscriptionData.data) return prev;
50 + },
51 + });
52 +
45 const onSubmit = async (e) => { 53 const onSubmit = async (e) => {
46 e.preventDefault(); 54 e.preventDefault();
47 if (message.value !== undefined || message.value !== "") { 55 if (message.value !== undefined || message.value !== "") {
...@@ -54,29 +62,18 @@ export default withRouter(({ location }) => { ...@@ -54,29 +62,18 @@ export default withRouter(({ location }) => {
54 }); 62 });
55 if (!messageObj) { 63 if (!messageObj) {
56 toast.error("fail to create new message !, try again"); 64 toast.error("fail to create new message !, try again");
57 - } else {
58 - const {
59 - data: {
60 - createMessage: { text, createdAt },
61 - },
62 - } = messageObj;
63 - messageText = text;
64 - messageTime = createdAt;
65 - newMsgObj = messageObj;
66 } 65 }
67 } catch { 66 } catch {
68 toast.error("text must be not empty"); 67 toast.error("text must be not empty");
69 } 68 }
70 } 69 }
71 }; 70 };
71 +
72 return ( 72 return (
73 <ChatPresenter 73 <ChatPresenter
74 location={location} 74 location={location}
75 message={message} 75 message={message}
76 onSubmit={onSubmit} 76 onSubmit={onSubmit}
77 - messageText={messageText}
78 - messageTime={messageTime}
79 - newMsgObj={newMsgObj}
80 messageArray={messageArray} 77 messageArray={messageArray}
81 /> 78 />
82 ); 79 );
......
...@@ -90,17 +90,32 @@ const ChatScreenBox = styled.div` ...@@ -90,17 +90,32 @@ const ChatScreenBox = styled.div`
90 flex-direction: column; 90 flex-direction: column;
91 width: 100%; 91 width: 100%;
92 height: 100%; 92 height: 100%;
93 + overflow-y: scroll;
94 + &::-webkit-scrollbar {
95 + width: 10px;
96 + }
97 + &::-webkit-scrollbar-track {
98 + background-color: transparent;
99 + }
100 + &::-webkit-scrollbar-thumb {
101 + border-radius: 3px;
102 + background-color: gray;
103 + }
104 + &::-webkit-scrollbar-button {
105 + width: 0;
106 + height: 0;
107 + }
93 `; 108 `;
94 109
95 const InputContainer = styled.div` 110 const InputContainer = styled.div`
96 position: fixed; 111 position: fixed;
97 bottom: 0; 112 bottom: 0;
98 - justify-self: center; 113 + justify-content: center;
99 - padding: 10px; 114 + align-items: center;
100 - margin-bottom: 20px; 115 + width: 70%;
116 + margin: 10px;
101 display: flex; 117 display: flex;
102 flex-direction: row; 118 flex-direction: row;
103 - width: 70%;
104 form { 119 form {
105 width: 100%; 120 width: 100%;
106 button { 121 button {
...@@ -132,20 +147,10 @@ const StyledLink = styled(Link)` ...@@ -132,20 +147,10 @@ const StyledLink = styled(Link)`
132 } 147 }
133 `; 148 `;
134 149
135 -export default ({ 150 +export default ({ location, message, onSubmit, messageArray }) => {
136 - location,
137 - message,
138 - onSubmit,
139 - messageText,
140 - messageTime,
141 - newMsgObj,
142 - messageArray,
143 -}) => {
144 const { pathname } = location; 151 const { pathname } = location;
145 const roomName = pathname.slice(1, pathname.length); 152 const roomName = pathname.slice(1, pathname.length);
146 153
147 - console.log(messageArray);
148 -
149 return ( 154 return (
150 <Wrapper> 155 <Wrapper>
151 <Header text={"KhuChat"} /> 156 <Header text={"KhuChat"} />
...@@ -169,10 +174,14 @@ export default ({ ...@@ -169,10 +174,14 @@ export default ({
169 <ChatScreenBox> 174 <ChatScreenBox>
170 {messageArray && 175 {messageArray &&
171 messageArray.seeAllMessage.map((e) => ( 176 messageArray.seeAllMessage.map((e) => (
172 - <Message text={e.text} time={e.createdAt} key={e.id} /> 177 + <Message
178 + text={e.text}
179 + time={e.createdAt}
180 + key={e.id}
181 + avatar={e.sender.avatarUrl}
182 + />
173 ))} 183 ))}
174 - {newMsgObj && <Message text={messageText} time={messageTime} />} 184 + <InputContainer className="InputContainer">
175 - <InputContainer>
176 <form onSubmit={onSubmit}> 185 <form onSubmit={onSubmit}>
177 <Input 186 <Input
178 placeholder={"Enter any words"} 187 placeholder={"Enter any words"}
......
1 import { gql } from "apollo-boost"; 1 import { gql } from "apollo-boost";
2 2
3 export const SUBSCRIPTION_MSG = gql` 3 export const SUBSCRIPTION_MSG = gql`
4 - subscription subMessage { 4 + subscription {
5 subMessage { 5 subMessage {
6 id 6 id
7 text 7 text
8 + room {
9 + id
10 + name
11 + }
8 sender { 12 sender {
9 id 13 id
10 username 14 username
15 + avatarUrl
11 } 16 }
12 createdAt 17 createdAt
13 } 18 }
......
...@@ -7,6 +7,7 @@ export default createGlobalStyle` ...@@ -7,6 +7,7 @@ export default createGlobalStyle`
7 box-sizing: border-box; 7 box-sizing: border-box;
8 } 8 }
9 html, body { 9 html, body {
10 + overflow: hidden;
10 height: 100vh; 11 height: 100vh;
11 } 12 }
12 a { 13 a {
......