Skip to content

Commit

Permalink
Merge pull request #201 from boostcampwm-2021/dev
Browse files Browse the repository at this point in the history
Release 0.3.1
  • Loading branch information
Dev-Beom authored Nov 18, 2021
2 parents a59a59f + 0d9be42 commit 66e9faa
Show file tree
Hide file tree
Showing 27 changed files with 189 additions and 63 deletions.
3 changes: 0 additions & 3 deletions client/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,4 @@
<body>
<div id="root"></div>
</body>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Dongle:wght@400;700&display=swap" rel="stylesheet" />
</html>
3 changes: 2 additions & 1 deletion client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import './styles/fonts.css';
import { useCallback, useEffect } from 'react';
import { BrowserRouter, Route, Redirect, Switch } from 'react-router-dom';
import GlobalStyles from './styles/GlobalStyles';
import Introduction from '@pages/Introduction';
import Main from '@pages/Main';
import { useUser, useUserFns } from '@contexts/userContext';
import { getUserByToken } from '@utils/apis';
import { getUserByToken } from '@src/apis';
import Room from '@pages/Room';

const App = (): JSX.Element => {
Expand Down
7 changes: 6 additions & 1 deletion client/src/utils/apis.ts → client/src/apis.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UserProps } from '@contexts/userContext';
import { RoomInfo } from '@components/main/RoomList';
import { HTTPResponse, queryObjToString, fetchGet, fetchPost, fetchDelete } from './apiUtils';
import { HTTPResponse, queryObjToString, fetchGet, fetchPost, fetchDelete } from './utils/apiUtils';

interface PostLogin {
email: string;
Expand All @@ -12,6 +12,11 @@ export const postLogin = async (body: PostLogin): Promise<HTTPResponse<UserProps
return response;
};

export const postLogout = async (): Promise<HTTPResponse<boolean>> => {
const response = await fetchPost<boolean>('/api/auth/logout');
return response;
};

interface PostJoin extends PostLogin {
nickname: string;
}
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/JoinForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import styled, { css } from 'styled-components';
import useInput from '@hooks/useInput';
import { postJoin } from '@utils/apis';
import { postJoin } from '@src/apis';
import { FaGithub } from 'react-icons/fa';
import InfoMessage from './InfoMessage';
import Select from './common/Select';
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/LoginForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import styled, { css } from 'styled-components';
import useInput from '@hooks/useInput';
import { postLogin } from '@utils/apis';
import { postLogin } from '@src/apis';
import { useUserFns } from '@contexts/userContext';
import { FaGithub } from 'react-icons/fa';
import InfoMessage from './InfoMessage';
Expand Down
30 changes: 22 additions & 8 deletions client/src/components/VideoBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from 'agora-rtc-react';
import styled from 'styled-components';
import defaultImage from '@assets/default-avatar.jpeg';
import { useEffect, useState } from 'react';
import { useEffect, useState, useRef, useCallback } from 'react';

const VIDEO_WIDTH = 30;
const VIDEO_HEIGHT = 20;
Expand All @@ -31,11 +31,11 @@ const VolumeVisualizer = styled.div`
height: ${VIDEO_HEIGHT}rem;
position: absolute;
right: 0;
border: 3px solid ${({ theme }) => theme.colors.primary};
border: 3px solid ${({ theme }) => theme.colors.blue};
border-radius: ${BORDER_RADIUS};
`;

const SPEAK_VOLUME = 0.1;
const SPEAK_VOLUME = 0.2;
const VOLUME_VISUAL_TIME = 1000;

interface VideoBoxProps {
Expand All @@ -45,13 +45,27 @@ interface VideoBoxProps {

const VideoBox = ({ videoTrack, audioTrack }: VideoBoxProps): JSX.Element => {
const [isSpeak, setIsSpeak] = useState(false);
const isInterval = useRef(false);

const initInterval = useCallback(
function () {
if (!isInterval.current) {
setInterval(() => {
if (audioTrack) {
setIsSpeak(audioTrack?.getVolumeLevel() > SPEAK_VOLUME);
}
}, VOLUME_VISUAL_TIME);
}
isInterval.current = true;
},
[isInterval, audioTrack],
);

useEffect(() => {
if (audioTrack)
setInterval(() => {
setIsSpeak(audioTrack?.getVolumeLevel() > SPEAK_VOLUME);
}, VOLUME_VISUAL_TIME);
}, [audioTrack]);
if (audioTrack) {
initInterval();
}
}, [audioTrack, initInterval]);

return (
<VideoWrap>
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/main/CreateForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState } from 'react';
import { useHistory } from 'react-router-dom';
import styled, { css } from 'styled-components';
import useInput from '@hooks/useInput';
import { postRoom } from '@utils/apis';
import { postRoom } from '@src/apis';
import { useUser } from '@contexts/userContext';
import Select from '@components/common/Select';
import { adminOptions } from '@utils/utils';
Expand Down
3 changes: 1 addition & 2 deletions client/src/components/main/RoomList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import RoomBox from '@components/RoomBox';
import Tab from '@components/common/Tab';

import { UserProps } from '@src/contexts/userContext';

import { getRoom } from '@utils/apis';
import { getRoom } from '@src/apis';

const RoomListGrid = styled.div`
padding: ${({ theme }) => theme.paddings.lg} 0;
Expand Down
18 changes: 11 additions & 7 deletions client/src/components/main/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useUser, useUserFns } from '@contexts/userContext';
import { IoLogOutOutline } from 'react-icons/io5';
import Modal from '@components/common/Modal';
import CreateForm from './CreateForm';
import { setCookie } from '@utils/cookie';
import { postLogout } from '@src/apis';

const SIDEBAR_MIN_WIDTH = '29rem';

Expand Down Expand Up @@ -102,12 +102,14 @@ const LogoutBtn = styled.button`

const UserAvatar = styled.img`
margin-right: ${({ theme }) => theme.margins.base};
width: 5rem;
height: 5rem;
width: 3rem;
height: 3rem;
border-radius: 50%;
overflow: hidden;
`;

const UserNickname = styled.span``;

const SideBar = (): JSX.Element => {
const [loginModal, setLoginModal] = useState(false);
const [createModal, setCreateModal] = useState(false);
Expand All @@ -117,9 +119,11 @@ const SideBar = (): JSX.Element => {
const onClickLoginBtn = () => setLoginModal(!loginModal);
const onClickCreateBtn = () => setCreateModal(true);
const onClickUserInfoBtn = () => {};
const onClickLogoutBtn = () => {
setCookie('access-token', '');
logUserOut();
const onClickLogoutBtn = async () => {
const { isOk } = await postLogout();
if (isOk) {
logUserOut();
}
};

return (
Expand All @@ -129,7 +133,7 @@ const SideBar = (): JSX.Element => {
<>
<UserInfoDiv onClick={onClickUserInfoBtn}>
<UserAvatar src={user.imageUrl}></UserAvatar>
{user.nickname}
<UserNickname>{user.nickname}</UserNickname>
</UserInfoDiv>
<LogoutBtn onClick={onClickLogoutBtn}>
<span>로그아웃</span>
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/room/tadaktadak/VideoController.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { useState, useCallback, useEffect, useContext } from 'react';
import { useHistory } from 'react-router';
import { ICameraVideoTrack, IMicrophoneAudioTrack } from 'agora-rtc-react';
import styled, { css, ThemeContext } from 'styled-components';
import { FaMicrophone, FaMicrophoneSlash, FaVideo, FaVideoSlash } from 'react-icons/fa';
import { MdOutlineExitToApp, MdScreenShare, MdStopScreenShare } from 'react-icons/md';
import styled, { css, ThemeContext } from 'styled-components';
import { useClient } from './videoConfig';
import Button from '@components/common/Button';
import ScreenShareDiv from './ScreenShareDiv';
import { deleteRoom } from '@utils/apis';
import { deleteRoom } from '@src/apis';
import { useUser } from '@contexts/userContext';

const ButtonContainer = styled.div`
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/Introduction/Introduction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ const IntroContainer = styled.div<IntroContainerProps>`
`}
transition: background-color 1500ms linear;
padding: ${({ theme }) => theme.paddings.base};
font-family: 'Dongle', sans-serif;
font-family: 'Dongle';
`;

const IntroTitle = styled.div`
z-index: 2;
color: white;
font-size: 200px;
font-size: 250px;
`;
const IntroDescription = styled.div`
z-index: 2;
Expand Down
1 change: 1 addition & 0 deletions client/src/pages/Room/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ export const RoomWrapper = styled.div`

export const RoomContainer = styled.div`
height: 100%;
width: 100%;
padding: ${({ theme }) => theme.paddings.lg};
`;
2 changes: 1 addition & 1 deletion client/src/styles/GlobalStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const GlobalStyles = createGlobalStyle`
font-size : 62.5%; // 1rem === 10px
}
body {
font-family: 'Dongle', sans-serif;
font-family: 'Dongle';
}
a {
text-decoration: none;
Expand Down
7 changes: 7 additions & 0 deletions client/src/styles/fonts.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@font-face {
font-family: 'Dongle';
font-style: normal;
font-weight: 700;
src: url('./fonts/dongle-v4-korean-700.woff2') format('woff2'),
url('./fonts/dongle-v4-korean-700.woff') format('woff');
} ;
Binary file not shown.
Binary file not shown.
38 changes: 20 additions & 18 deletions client/src/utils/apiUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,36 @@ export function queryObjToString<T>(queryObj: T): string {
.join('&');
}

function getOptions(): RequestInit {
function simpleOptions(method: string): RequestInit {
return {
method,
headers: {
Accept: 'application/json',
},
credentials: 'include',
};
}

function getOptions(): RequestInit {
return simpleOptions('GET');
}

function postOptions(body: BodyType): RequestInit {
return {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify(body),
};
return Object.keys(body).length
? {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify(body),
}
: simpleOptions('POST');
}

function deleteOptions(): RequestInit {
return {
method: 'DELETE',
headers: {
Accept: 'application/json',
},
credentials: 'include',
};
return simpleOptions('DELETE');
}

export async function fetcher<T>(url: string, options: RequestInit): Promise<HTTPResponse<T>> {
Expand Down Expand Up @@ -89,9 +90,10 @@ export async function fetchGet<T>(url: string, query?: string): Promise<HTTPResp
return response;
}

export async function fetchPost<T>(url: string, body: BodyType): Promise<HTTPResponse<T>> {
export async function fetchPost<T>(url: string, body: BodyType = {}): Promise<HTTPResponse<T>> {
const requestUrl = getUrl(url);
const response = await fetcher<T>(requestUrl, postOptions(body));
console.log(postOptions(body));
return response;
}

Expand Down
3 changes: 2 additions & 1 deletion server/api/src/domain/auth/auth.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import { JwtStrategy } from './strategy/jwt.strategy';
import { AuthController } from './controller/auth.controller';
import { AuthService } from './service/auth.service';
import { UserRepository } from '../user/repository/user.repository';
import { DevFieldRepository } from '../field/repository/dev-field.repository';
import { HistoryModule } from '../history/history.module';

@Module({
imports: [
TypeOrmModule.forFeature([UserRepository]),
TypeOrmModule.forFeature([UserRepository, DevFieldRepository]),
PassportModule,
JwtModule.register({
secret: 'secretkey',
Expand Down
10 changes: 9 additions & 1 deletion server/api/src/domain/auth/service/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@ import { JwtService } from '@nestjs/jwt';
import { LocalDate } from 'js-joda';
import { Bcrypt } from 'src/utils/bcrypt';
import { UserBuilder } from '../../../builder';
import { UserException } from '../../../exception';
import { DevFieldException, UserException } from '../../../exception';
import { User } from '../../user/user.entity';
import { HistoryService } from 'src/domain/history/service/history.service';
import { UserRepository } from '../../user/repository/user.repository';
import { DevFieldRepository } from 'src/domain/field/repository/dev-field.repository';
import { LoginRequestDto } from '../dto/login-request.dto';
import { UserResponseDto } from '../dto/user-response.dto';
import { JoinRequestDto } from '../dto/join-request.dto';
import { DevField } from 'src/domain/field/dev-field.entity';

@Injectable()
export class AuthService {
constructor(
@InjectRepository(UserRepository)
private readonly userRepository: UserRepository,

@InjectRepository(DevFieldRepository)
private readonly devFieldRepository: DevFieldRepository,

private readonly historyService: HistoryService,
private jwtService: JwtService,
) {}
Expand All @@ -42,11 +47,14 @@ export class AuthService {
const { nickname, email, password } = joinRequestDto;
const isExistUser = await this.userRepository.exists(joinRequestDto);
if (isExistUser) throw UserException.userIsExist();
const devField: DevField = await this.devFieldRepository.findDevById(joinRequestDto.devFieldId);
if (!devField) throw DevFieldException.devFieldNotFound();
const user: User = new UserBuilder()
.setNickName(nickname)
.setEmail(email)
.setPassword(Bcrypt.hash(password))
.setImageURL(process.env.DEFAULT_IMG)
.setDevField(devField)
.build();
await this.userRepository.save(user);
return true;
Expand Down
12 changes: 12 additions & 0 deletions server/api/src/domain/room/controller/room.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ export class RoomController {
return { result: await this.roomService.getRoomByUUID(uuid) };
}

@Post(':uuid/join')
@UseGuards(JwtAuthGuard)
async joinRoom(@Param('uuid') uuid: string): Promise<{ result: boolean }> {
return { result: await this.roomService.joinRoom(uuid) };
}

@Post(':uuid/leave')
@UseGuards(JwtAuthGuard)
async leaveRoom(@Param('uuid') uuid: string): Promise<{ result: boolean }> {
return { result: await this.roomService.leaveRoom(uuid) };
}

@Delete(':uuid')
@UseGuards(JwtAuthGuard)
async deleteRoom(@Req() req: Request, @Param('uuid') uuid: string): Promise<{ result: boolean }> {
Expand Down
4 changes: 4 additions & 0 deletions server/api/src/domain/room/dto/room-response.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export class RoomResponseDto {
agoraAppId: string;
agoraToken: string;
owner: UserResponseDto;
nowHeadcount: number;
maxHeadcount: number;

constructor(room: Room) {
const owner: User = room.owner;
Expand All @@ -26,6 +28,8 @@ export class RoomResponseDto {
this.uuid = room.uuid;
this.agoraAppId = room.agoraAppId;
this.agoraToken = room.agoraToken;
this.nowHeadcount = room.nowHeadcount;
this.maxHeadcount = room.maxHeadcount;
this.owner = new UserResponseDtoBuilder()
.setId(room.owner.id)
.setNickName(owner.nickName)
Expand Down
Loading

0 comments on commit 66e9faa

Please sign in to comment.