minsung

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

...@@ -33,13 +33,13 @@ sub-subject : making chat site using JS ...@@ -33,13 +33,13 @@ sub-subject : making chat site using JS
33 - [x] Create Chat Screen View, Make Queries for Front-End 33 - [x] Create Chat Screen View, Make Queries for Front-End
34 34
35 - 5/25 ~ 5/31 35 - 5/25 ~ 5/31
36 -- [ ] Make and Test chatting using GraphQL's Subscription 36 +- [X] Make and Test chatting using GraphQL's Subscription
37 37
38 - 6/1 ~ 6/7 38 - 6/1 ~ 6/7
39 -- [ ] Make one to one chatting, view, toggle. 39 +- [X] Make one to one chatting, view, toggle.
40 40
41 - 6/8 ~ 6/14 41 - 6/8 ~ 6/14
42 -- [ ] Debugging for whole codes in our project 42 +- [X] Debugging for whole codes in our project
43 43
44 - 6/15 ~ 6/21 44 - 6/15 ~ 6/21
45 - [ ] Deploy project in AWS amplify 45 - [ ] Deploy project in AWS amplify
......
...@@ -33,13 +33,13 @@ sub-subject : making chat site using JS ...@@ -33,13 +33,13 @@ sub-subject : making chat site using JS
33 - [x] Create Chat Screen View, Make Queries for Front-End 33 - [x] Create Chat Screen View, Make Queries for Front-End
34 34
35 - 5/25 ~ 5/31 35 - 5/25 ~ 5/31
36 -- [ ] Make and Test chatting using GraphQL's Subscription 36 +- [X] Make and Test chatting using GraphQL's Subscription
37 37
38 - 6/1 ~ 6/7 38 - 6/1 ~ 6/7
39 -- [ ] Make one to one chatting, view, toggle. 39 +- [X] Make one to one chatting, view, toggle.
40 40
41 - 6/8 ~ 6/14 41 - 6/8 ~ 6/14
42 -- [ ] Debugging for whole codes in our project 42 +- [X] Debugging for whole codes in our project
43 43
44 - 6/15 ~ 6/21 44 - 6/15 ~ 6/21
45 - [ ] Deploy project in AWS amplify 45 - [ ] Deploy project in AWS amplify
......
1 -import { prisma } from "../../../utils"; 1 +import { prisma, isAuthenticated } from "../../../utils";
2 +import { NEW_CATEGORY } from "../../../topics";
2 3
3 export default { 4 export default {
4 Mutation: { 5 Mutation: {
5 - addCategory: async (_, args) => { 6 + addCategory: async (_, args, { request, pubsub }) => {
7 + isAuthenticated(request);
6 const { name } = args; 8 const { name } = args;
7 const newCategory = await prisma.category.create({ 9 const newCategory = await prisma.category.create({
8 data: { 10 data: {
9 name, 11 name,
10 }, 12 },
11 }); 13 });
14 + if (newCategory !== undefined) {
15 + pubsub.publish(NEW_CATEGORY, { subCategory: newCategory });
16 + }
12 return newCategory; 17 return newCategory;
13 }, 18 },
14 }, 19 },
......
1 +type Subscription {
2 + subCategory: Category
3 +}
1 +import { NEW_CATEGORY } from "../../../topics";
2 +
3 +export default {
4 + Subscription: {
5 + subCategory: {
6 + subscribe: async (_, __, { pubsub }) => {
7 + return pubsub.asyncIterator(NEW_CATEGORY);
8 + },
9 + },
10 + },
11 +};
1 export const NEW_MESSAGE = "new message"; 1 export const NEW_MESSAGE = "new message";
2 +
3 +export const NEW_CATEGORY = "new category";
......
...@@ -33,13 +33,13 @@ sub-subject : making chat site using JS ...@@ -33,13 +33,13 @@ sub-subject : making chat site using JS
33 - [x] Create Chat Screen View, Make Queries for Front-End 33 - [x] Create Chat Screen View, Make Queries for Front-End
34 34
35 - 5/25 ~ 5/31 35 - 5/25 ~ 5/31
36 -- [ ] Make and Test chatting using GraphQL's Subscription 36 +- [X] Make and Test chatting using GraphQL's Subscription
37 37
38 - 6/1 ~ 6/7 38 - 6/1 ~ 6/7
39 -- [ ] Make one to one chatting, view, toggle. 39 +- [X] Make one to one chatting, view, toggle.
40 40
41 - 6/8 ~ 6/14 41 - 6/8 ~ 6/14
42 -- [ ] Debugging for whole codes in our project 42 +- [X] Debugging for whole codes in our project
43 43
44 - 6/15 ~ 6/21 44 - 6/15 ~ 6/21
45 - [ ] Deploy project in AWS amplify 45 - [ ] Deploy project in AWS amplify
......
1 import React from "react"; 1 import React from "react";
2 import styled from "styled-components"; 2 import styled from "styled-components";
3 import ProfileIcon from "./ProfileIcon"; 3 import ProfileIcon from "./ProfileIcon";
4 -import moment from "moment";
5 4
6 const MessageWrapper = styled.div` 5 const MessageWrapper = styled.div`
7 display: flex; 6 display: flex;
...@@ -35,18 +34,7 @@ const Msg = styled.span` ...@@ -35,18 +34,7 @@ const Msg = styled.span`
35 padding: 20px 10px; 34 padding: 20px 10px;
36 `; 35 `;
37 36
38 -const TimeBox = styled.div` 37 +export default ({ text, avatar }) => {
39 - display: flex;
40 - justify-content: flex-end;
41 - align-items: center;
42 - opacity: 0.8;
43 -`;
44 -
45 -const Time = styled.span`
46 - font-size: 15px;
47 -`;
48 -
49 -export default ({ text, avatar, time }) => {
50 return ( 38 return (
51 <MessageWrapper className="MessageWrapper"> 39 <MessageWrapper className="MessageWrapper">
52 <MsgContainer> 40 <MsgContainer>
...@@ -55,9 +43,6 @@ export default ({ text, avatar, time }) => { ...@@ -55,9 +43,6 @@ export default ({ text, avatar, time }) => {
55 <MsgBox> 43 <MsgBox>
56 <Msg> {text} </Msg> 44 <Msg> {text} </Msg>
57 </MsgBox> 45 </MsgBox>
58 - <TimeBox>
59 - <Time>1</Time>
60 - </TimeBox>
61 </ColumnBox> 46 </ColumnBox>
62 </MsgContainer> 47 </MsgContainer>
63 </MessageWrapper> 48 </MessageWrapper>
......
1 -import React from "react"; 1 +import React, { useEffect, useState } from "react";
2 import CategoryPresenter from "./CategoryPresenter"; 2 import CategoryPresenter from "./CategoryPresenter";
3 import { withRouter } from "react-router-dom"; 3 import { withRouter } from "react-router-dom";
4 -import { useQuery } from "@apollo/react-hooks"; 4 +import { useQuery, useMutation } from "@apollo/react-hooks";
5 -import { GET_CATEGORIRES } from "./CategoryQueries"; 5 +import {
6 + GET_CATEGORIRES,
7 + ADD_CATEGORY,
8 + SUBSCRIPTION_CATEGORY,
9 +} from "./CategoryQueries";
6 10
7 export default withRouter(({ location }) => { 11 export default withRouter(({ location }) => {
8 - const { data } = useQuery(GET_CATEGORIRES); 12 + const [categoryArr, setCategoryArr] = useState([]);
9 - //const [addCategory] = useMutation(ADD_CATEGORY); 13 + const {
10 - //const [editCategory] = useMutation(EDIT_CATEGORY); 14 + subscribeToMore,
11 - //const [deleteCategory] = useMutation(DELETE_CATEGORY); 15 + data: categoryList,
16 + error: categoryQueryError,
17 + loading: categoryQueryLoading,
18 + } = useQuery(GET_CATEGORIRES);
12 19
13 let categories; 20 let categories;
14 - if (data !== undefined) { 21 + if (categoryList !== undefined) {
15 - const { getCategories } = data; 22 + const { getCategories } = categoryList;
16 categories = getCategories; 23 categories = getCategories;
17 } 24 }
18 25
19 - return <CategoryPresenter location={location} categories={categories} />; 26 + useEffect(() => {
27 + if (categoryQueryError) {
28 + console.error(categoryQueryError);
29 + }
30 + if (categoryArr) {
31 + setCategoryArr(categoryArr.getCategories, [
32 + categoryQueryError,
33 + categoryArr,
34 + ]);
35 + }
36 + }, [categoryQueryLoading]);
37 +
38 + const subscribeToNewCategory = () => {
39 + subscribeToMore({
40 + document: SUBSCRIPTION_CATEGORY,
41 + updateQuery: (currentCategories, { subscriptionData }) => {
42 + if (!subscriptionData.data) return currentCategories;
43 + const newCategory = subscriptionData.data.subCategory;
44 + const updateCategory = currentCategories.getCategories.concat(
45 + newCategory
46 + );
47 + setCategoryArr(updateCategory);
48 + return { getCategories: updateCategory };
49 + },
50 + });
51 + };
52 +
53 + return (
54 + <CategoryPresenter
55 + location={location}
56 + categories={categories}
57 + subscribeToNewCategory={subscribeToNewCategory}
58 + />
59 + );
20 }); 60 });
......
1 -import React from "react"; 1 +import React, { useEffect } from "react";
2 import styled from "styled-components"; 2 import styled from "styled-components";
3 import { Link } from "react-router-dom"; 3 import { Link } from "react-router-dom";
4 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; 4 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
...@@ -62,9 +62,10 @@ const StyledLink = styled(Link)` ...@@ -62,9 +62,10 @@ const StyledLink = styled(Link)`
62 } 62 }
63 `; 63 `;
64 64
65 -export default ({ location, categories }) => { 65 +export default ({ location, categories, subscribeToNewCategory }) => {
66 const { pathname } = location; 66 const { pathname } = location;
67 let path; 67 let path;
68 + useEffect(() => subscribeToNewCategory(), []);
68 return ( 69 return (
69 <> 70 <>
70 <CategoryContainer> 71 <CategoryContainer>
......
...@@ -23,3 +23,12 @@ export const DELETE_CATEGORY = gql` ...@@ -23,3 +23,12 @@ export const DELETE_CATEGORY = gql`
23 deleteCategory(name: $name) 23 deleteCategory(name: $name)
24 } 24 }
25 `; 25 `;
26 +
27 +export const SUBSCRIPTION_CATEGORY = gql`
28 + subscription {
29 + subCategory {
30 + id
31 + name
32 + }
33 + }
34 +`;
......
...@@ -11,7 +11,6 @@ import { ...@@ -11,7 +11,6 @@ import {
11 import useInput from "../../Hooks/useInput"; 11 import useInput from "../../Hooks/useInput";
12 import { toast } from "react-toastify"; 12 import { toast } from "react-toastify";
13 13
14 -
15 export default withRouter(({ location }) => { 14 export default withRouter(({ location }) => {
16 const [messageArr, setMessageArr] = useState([]); 15 const [messageArr, setMessageArr] = useState([]);
17 const { pathname } = location; 16 const { pathname } = location;
...@@ -20,7 +19,7 @@ export default withRouter(({ location }) => { ...@@ -20,7 +19,7 @@ export default withRouter(({ location }) => {
20 19
21 const message = useInput(""); 20 const message = useInput("");
22 21
23 - let messageObj, roomNum, messageArray; 22 + let messageObj, roomNum, messageArray; // messageArray 는 useQuery 로 얻은 데이터 인데 undefined 가 아닌 데이터
24 23
25 const { data: getRoom } = useQuery(GET_ROOM_BY_NAME, { 24 const { data: getRoom } = useQuery(GET_ROOM_BY_NAME, {
26 variables: { roomName }, 25 variables: { roomName },
...@@ -36,7 +35,7 @@ export default withRouter(({ location }) => { ...@@ -36,7 +35,7 @@ export default withRouter(({ location }) => {
36 subscribeToMore, 35 subscribeToMore,
37 data: messageList, 36 data: messageList,
38 error: msgQueryError, 37 error: msgQueryError,
39 - loading: msgQueryyLoading, 38 + loading: msgQueryLoading,
40 } = useQuery(SEE_ALL_MESSAGE, { 39 } = useQuery(SEE_ALL_MESSAGE, {
41 variables: { roomId: roomNum }, 40 variables: { roomId: roomNum },
42 }); 41 });
...@@ -52,7 +51,7 @@ export default withRouter(({ location }) => { ...@@ -52,7 +51,7 @@ export default withRouter(({ location }) => {
52 if (messageArr) { 51 if (messageArr) {
53 setMessageArr(messageArr.seeAllMessage, [msgQueryError, messageArr]); 52 setMessageArr(messageArr.seeAllMessage, [msgQueryError, messageArr]);
54 } 53 }
55 - }, [msgQueryyLoading]); 54 + }, [msgQueryLoading]);
56 55
57 const subscribeToNewMessage = () => { 56 const subscribeToNewMessage = () => {
58 subscribeToMore({ 57 subscribeToMore({
......
...@@ -107,28 +107,38 @@ const ChatScreenBox = styled.div` ...@@ -107,28 +107,38 @@ const ChatScreenBox = styled.div`
107 } 107 }
108 `; 108 `;
109 109
110 +const InputWrapper = styled.div`
111 + width: 100%;
112 + display: flex;
113 + flex-direction: row;
114 + justify-content: center;
115 + align-items: center;
116 +`;
117 +
110 const InputContainer = styled.div` 118 const InputContainer = styled.div`
111 position: fixed; 119 position: fixed;
112 bottom: 0; 120 bottom: 0;
113 justify-content: center; 121 justify-content: center;
114 align-items: center; 122 align-items: center;
115 - width: 70%; 123 + width: 50%;
116 - margin: 10px; 124 + margin-bottom: 20px;
117 display: flex; 125 display: flex;
118 flex-direction: row; 126 flex-direction: row;
127 + background-color: #b2bec3;
128 + border: none;
119 form { 129 form {
120 width: 100%; 130 width: 100%;
121 button { 131 button {
122 background-color: #27ae60; 132 background-color: #27ae60;
123 - width: 10%; 133 + width: 20%;
124 color: white; 134 color: white;
125 border-radius: 10px; 135 border-radius: 10px;
126 } 136 }
127 input { 137 input {
138 + background-color: #b2bec3;
128 width: 70%; 139 width: 70%;
129 } 140 }
130 } 141 }
131 - border: 1px solid rgba(0, 0, 0, 0.7);
132 border-radius: 10px; 142 border-radius: 10px;
133 `; 143 `;
134 144
...@@ -156,7 +166,7 @@ export default ({ ...@@ -156,7 +166,7 @@ export default ({
156 }) => { 166 }) => {
157 const { pathname } = location; 167 const { pathname } = location;
158 const roomName = pathname.slice(1, pathname.length); 168 const roomName = pathname.slice(1, pathname.length);
159 - useEffect(() => subscribeToNewMessage()); 169 + useEffect(() => subscribeToNewMessage(), []);
160 170
161 return ( 171 return (
162 <Wrapper> 172 <Wrapper>
...@@ -167,7 +177,7 @@ export default ({ ...@@ -167,7 +177,7 @@ export default ({
167 <Title>{roomName} Room</Title> 177 <Title>{roomName} Room</Title>
168 </TitleContainer> 178 </TitleContainer>
169 <PeopleContainer> 179 <PeopleContainer>
170 - <StyledLink to="People"> 180 + <StyledLink to={`/${roomName}/People`}>
171 <FontAwesomeIcon icon={faAddressBook} /> 181 <FontAwesomeIcon icon={faAddressBook} />
172 <ItemText>People</ItemText> 182 <ItemText>People</ItemText>
173 </StyledLink> 183 </StyledLink>
...@@ -176,30 +186,30 @@ export default ({ ...@@ -176,30 +186,30 @@ export default ({
176 </ChatMenuContainer> 186 </ChatMenuContainer>
177 <ChatScreenContainer> 187 <ChatScreenContainer>
178 <ChatScreenHeader> 188 <ChatScreenHeader>
179 - <Title>Selected Menu Title</Title> 189 + <Title>{roomName}</Title>
180 </ChatScreenHeader> 190 </ChatScreenHeader>
181 <ChatScreenBox> 191 <ChatScreenBox>
182 - <ul> 192 + {messageArray &&
183 - {messageArray && 193 + messageArray.seeAllMessage.map((e) => (
184 - messageArray.seeAllMessage.map((e) => ( 194 + <Message
185 - <Message 195 + text={e.text}
186 - text={e.text} 196 + time={e.createdAt}
187 - time={e.createdAt} 197 + key={e.id}
188 - key={e.id} 198 + avatar={e.sender.avatarUrl}
189 - avatar={e.sender.avatarUrl}
190 - />
191 - ))}
192 - </ul>
193 - <InputContainer className="InputContainer">
194 - <form onSubmit={onSubmit}>
195 - <Input
196 - placeholder={"Enter any words"}
197 - type="text"
198 - {...message}
199 /> 199 />
200 - <Button text={"Submit"} /> 200 + ))}
201 - </form> 201 + <InputWrapper>
202 - </InputContainer> 202 + <InputContainer className="InputContainer">
203 + <form onSubmit={onSubmit}>
204 + <Input
205 + placeholder={"Enter any words"}
206 + type="text"
207 + {...message}
208 + />
209 + <Button text={"Submit"} />
210 + </form>
211 + </InputContainer>
212 + </InputWrapper>
203 </ChatScreenBox> 213 </ChatScreenBox>
204 </ChatScreenContainer> 214 </ChatScreenContainer>
205 </ChatWrapper> 215 </ChatWrapper>
......
...@@ -9,8 +9,8 @@ const LoggedInRoutes = () => ( ...@@ -9,8 +9,8 @@ const LoggedInRoutes = () => (
9 <Switch> 9 <Switch>
10 <Route exact path="/" component={RoomList} /> 10 <Route exact path="/" component={RoomList} />
11 <Route exact path="/:roomname" component={Chat} /> 11 <Route exact path="/:roomname" component={Chat} />
12 - <Route path="/:roomname/People" component={Auth} /> 12 + <Route path="/:roomname/People" component={Chat} />
13 - <Route path="/:roomname/:categoryName" component={Auth} /> 13 + <Route path="/:roomname/:categoryName" component={Chat} />
14 <Redirect from="*" to="/" /> 14 <Redirect from="*" to="/" />
15 </Switch> 15 </Switch>
16 ); 16 );
......