Merge branch 'master' of https://bitbucket.org/vel1024/capstone
Showing
14 changed files
with
137 additions
and
72 deletions
| ... | @@ -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 | }, | ... | ... |
| ... | @@ -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 | ); | ... | ... |
-
Please register or login to post a comment