Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…iBoo into prod-fe
  • Loading branch information
spearStr committed Dec 2, 2024
2 parents f54be8e + 84f2f68 commit d640193
Show file tree
Hide file tree
Showing 15 changed files with 139 additions and 55 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/prod-fe-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Build and Push Docker Image
on:
push:
branches:
- prod-fe
- test-prod-fe

jobs:
build:
Expand Down Expand Up @@ -51,6 +51,6 @@ jobs:
mkdir -p ~/.ssh
echo "$SSH_PEM_KEY" > ~/.ssh/SSH_PEM_KEY.pem
chmod 600 ~/.ssh/SSH_PEM_KEY.pem
ssh -p $SSH_PORT -i ~/.ssh/SSH_PEM_KEY.pem -o StrictHostKeyChecking=no [email protected] 'cd prod && bash prod_fe.sh'
ssh -p $SSH_PORT -i ~/.ssh/SSH_PEM_KEY.pem -o StrictHostKeyChecking=no $SSH_USERNAME@test.liboo.kr 'cd prod && bash prod_fe.sh'
4 changes: 2 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ services:
- "1935:1935"
- "3000:3000"
volumes:
- /etc/letsencrypt/live/liboo.kr:/etc/letsencrypt/live/liboo.kr:ro
- /etc/letsencrypt/archive/liboo.kr:/etc/letsencrypt/archive/liboo.kr:ro
- /etc/letsencrypt/live/test.liboo.kr:/etc/letsencrypt/live/test.liboo.kr:ro
- /etc/letsencrypt/archive/test.liboo.kr:/etc/letsencrypt/archive/test.liboo.kr:ro
- /etc/nginx/ssl/dhparams.pem:/etc/nginx/ssl/dhparams.pem:ro

networks:
Expand Down
2 changes: 1 addition & 1 deletion fe.build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ services:
build:
context: nginx
dockerfile: dockerfile
image: liboost/nginx:latest
image: liboost/test-nginx:latest
ports:
- "80:80"
- "443:443"
Expand Down
17 changes: 17 additions & 0 deletions frontend/src/apis/fetchChatRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { AxiosResponse } from 'axios';
import { fetchInstance } from '.';

export type ChatRuleResponse = {
notice: string;
channelName: string;
};

export const fetchChatRule = async ({ sessionKey }: { sessionKey: string }): Promise<ChatRuleResponse> => {
const response: AxiosResponse<ChatRuleResponse> = await fetchInstance().get('/streams/notice', {
params: {
sessionKey
}
});

return response.data;
};
2 changes: 1 addition & 1 deletion frontend/src/apis/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { QueryClient, DefaultOptions } from '@tanstack/react-query';
import axios from 'axios';

export const BASE_URL = 'https://liboo.kr';
export const BASE_URL = 'https://test.liboo.kr';
export const RTMP_PORT = '1935';
export const RTMP_HTTP_PORT = '8000';
export const API_PORT = '3000';
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/apis/queries/chat/useFetchChatRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { useQuery } from '@tanstack/react-query';
import { ChatRuleResponse, fetchChatRule } from '@apis/fetchChatRule';

export const useFetchChatRule = ({ sessionKey }: { sessionKey: string }) => {
return useQuery<ChatRuleResponse, Error>({
queryKey: ['chatRule'],
queryFn: () => fetchChatRule({ sessionKey }),
refetchOnWindowFocus: false
});
};
19 changes: 12 additions & 7 deletions frontend/src/components/chat/ChatList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const ChatItemWrapper = memo(
if (chat.msgType === CHATTING_TYPES.QUESTION) {
return (
<ChatItem>
<QuestionCard type="client" question={chat} />
<QuestionCard type="client" question={chat} onNicknameClick={handleNicknameClick} />
</ChatItem>
);
} else if (chat.msgType === CHATTING_TYPES.NOTICE) {
Expand All @@ -43,12 +43,8 @@ const ChatItemWrapper = memo(
return (
<ChatItem>
<NormalChat $isHost={chat.owner === 'host'} $pointColor={chat.owner === 'host' ? '#0ADD91' : chat.color}>
{chat.owner === 'me' ? (
<span className="text_point">🧀</span>
) : chat.owner === 'host' ? (
<StyledIcon as={HostIconGreen} />
) : null}
<span className="text_point" onClick={handleNicknameClick}>
<span className="text_point user_name" onClick={handleNicknameClick}>
{chat.owner === 'me' ? '🧀' : chat.owner === 'host' ? <StyledIcon as={HostIconGreen} /> : null}
{chat.nickname}
</span>
<span className="chat_message">{chat.msg}</span>
Expand Down Expand Up @@ -171,6 +167,15 @@ const NormalChat = styled.div<{ $isHost: boolean; $pointColor: string }>`
line-height: 1.5;
}
.user_name {
cursor: pointer;
padding: 2px;
border-radius: 5px;
&:hover {
background-color: #393939;
}
}
overflow-wrap: break-word;
word-break: break-word;
`;
Expand Down
49 changes: 38 additions & 11 deletions frontend/src/components/chat/ChatQuestionSection.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { memo, useState, useCallback } from 'react';
import styled from 'styled-components';
import QuestionCard from './QuestionCard';
import { MessageReceiveData, MessageSendData } from '@type/chat';
import { MessageReceiveData, MessageSendData, UserInfoData } from '@type/chat';
import { CHATTING_SOCKET_SEND_EVENT } from '@constants/chat';
import { getStoredId } from '@utils/id';
import { UserType } from '@type/user';
import { useChat } from '@contexts/chatContext';

export interface ChatQuestionSectionProps {
questions: MessageReceiveData[];
Expand Down Expand Up @@ -38,6 +39,18 @@ const ChatQuestionSection = ({ questions, worker, userType, roomId }: ChatQuesti
[worker, roomId, userId]
);

const { dispatch } = useChat();

const onNicknameClick = useCallback(
(data: UserInfoData) => {
dispatch({
type: 'SET_SELECTED_USER',
payload: data
});
},
[dispatch]
);

return (
<SectionWrapper>
<SectionContainer>
Expand All @@ -51,18 +64,32 @@ const ChatQuestionSection = ({ questions, worker, userType, roomId }: ChatQuesti
question={questions[0]}
handleQuestionDone={handleQuestionDone}
ellipsis={!expanded}
onNicknameClick={() =>
onNicknameClick({
nickname: questions[0].nickname,
socketId: questions[0].socketId,
entryTime: questions[0].entryTime,
owner: questions[0].owner
})
}
/>
{expanded &&
questions
.slice(1)
.map((question) => (
<QuestionCard
key={question.questionId}
type={userType}
question={question}
handleQuestionDone={handleQuestionDone}
/>
))}
questions.slice(1).map((question) => (
<QuestionCard
key={question.questionId}
type={userType}
question={question}
handleQuestionDone={handleQuestionDone}
onNicknameClick={() =>
onNicknameClick({
nickname: question.nickname,
socketId: question.socketId,
entryTime: question.entryTime,
owner: question.owner
})
}
/>
))}
<SwipeBtn onClick={toggleSection} />
</>
)}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/chat/ChatRoomLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const ChatRoomLayout = ({ userType, roomId }: ChatRoomLayoutProps) => {

{state.isNoticePopupOpen && (
<PopupWrapper>
<NoticeCard />
<NoticeCard sessionKey={roomId} />
</PopupWrapper>
)}

Expand Down
29 changes: 14 additions & 15 deletions frontend/src/components/chat/NoticeCard.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import styled from 'styled-components';
import CloseIcon from '@assets/icons/close.svg';
import { useContext } from 'react';
import { memo, useCallback, useContext } from 'react';
import { ChatContext } from 'src/contexts/chatContext';
import { useFetchChatRule } from '@apis/queries/chat/useFetchChatRule';

export const NoticeCard = () => {
export const NoticeCard = ({ sessionKey }: { sessionKey: string }) => {
const { dispatch } = useContext(ChatContext);

const toggleSettings = () => {
const toggleSettings = useCallback(() => {
dispatch({ type: 'TOGGLE_ANNOUNCEMENT_POPUP' });
};
}, [dispatch]);

const { data: noticeInfo } = useFetchChatRule({ sessionKey });

return (
<NoticeCardContainer>
Expand All @@ -17,28 +20,22 @@ export const NoticeCard = () => {
<NoticeCardProfile></NoticeCardProfile>
<NoticeCardArea>
<div className="text_info">
<span className="text_point">네이버 부스트 캠프</span>
<span className="text_point">{noticeInfo?.channelName}</span>
<span>님의</span>
</div>
<div className="text_strong">컨퍼런스 공지 📢</div>
<div className="text_strong">채팅 규칙 📢</div>
</NoticeCardArea>
</NoticeCardWrapper>
<CloseBtn onClick={toggleSettings}>
<StyledCloseIcon />
</CloseBtn>
</NoticeCardHeader>

<NoticeMessage>
- 질문은 질문 채팅으로 부탁드립니다
<br /> - 컨퍼런스 보러와주셔서 감사합니다
<br /> - 컨퍼런스 보러와주셔서 감사합니다
<br /> - 컨퍼런스 보러와주셔서 감사합니다
<br /> - 컨퍼런스 보러와주셔서 감사합니다
</NoticeMessage>
<NoticeMessage>{noticeInfo?.notice}</NoticeMessage>
</NoticeCardContainer>
);
};
export default NoticeCard;
export default memo(NoticeCard);

const NoticeCardContainer = styled.div`
display: flex;
Expand Down Expand Up @@ -113,5 +110,7 @@ const NoticeMessage = styled.p`
margin-top: 10px;
max-height: 170px;
overflow-y: auto;
${({ theme }) => theme.tokenTypographys['display-bold14']}
${({ theme }) => theme.tokenTypographys['display-bold14']};
white-space: pre-line;
word-break: keep-all;
`;
35 changes: 29 additions & 6 deletions frontend/src/components/chat/QuestionCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { memo, useEffect, useMemo, useRef } from 'react';
import { memo, useEffect, useMemo, useRef, useCallback } from 'react';
import styled from 'styled-components';
import CheckIcon from '@assets/icons/check.svg';
import { MessageReceiveData } from '@type/chat';
Expand All @@ -10,9 +10,10 @@ interface QuestionCardProps {
question: MessageReceiveData;
handleQuestionDone?: (questionId: number) => void;
ellipsis?: boolean;
onNicknameClick: () => void;
}

export const QuestionCard = ({ type, question, handleQuestionDone, ellipsis = false }: QuestionCardProps) => {
const QuestionCard = ({ type, question, handleQuestionDone, onNicknameClick, ellipsis = false }: QuestionCardProps) => {
const startDateFormat = useMemo(() => new Date(question.msgTime), [question.msgTime]);
const nowRef = useRef<Date>(new Date());

Expand All @@ -36,19 +37,29 @@ export const QuestionCard = ({ type, question, handleQuestionDone, ellipsis = fa

const timeElement = useRef<HTMLSpanElement>(null);

const handleQuestionDoneMemoized = useCallback(() => {
if (handleQuestionDone) {
handleQuestionDone(question.questionId as number);
}
}, [handleQuestionDone, question.questionId]);

const onNicknameClickMemoized = useCallback(() => {
onNicknameClick();
}, [onNicknameClick]);

return (
<QuestionCardContainer>
<QuestionCardTop>
<QuestionInfo>
<span className="name_info">
<span className="name_info" onClick={onNicknameClickMemoized}>
<StyledIcon as={QuestionUserIcon} /> {question.nickname}
</span>
<span className="time_info" ref={timeElement}>
{formatTime.current}
</span>
</QuestionInfo>
{type === 'host' && handleQuestionDone && (
<CheckBtn onClick={() => handleQuestionDone(question.questionId as number)}>
<CheckBtn onClick={handleQuestionDoneMemoized}>
<StyledCheckIcon />
</CheckBtn>
)}
Expand All @@ -59,7 +70,14 @@ export const QuestionCard = ({ type, question, handleQuestionDone, ellipsis = fa
);
};

export default memo(QuestionCard);
// shouldComponentUpdate를 내부에서 사용할 수 있도록 memo 사용
export default memo(QuestionCard, (prevProps, nextProps) => {
return (
prevProps.question.questionId === nextProps.question.questionId &&
prevProps.type === nextProps.type &&
prevProps.ellipsis === nextProps.ellipsis
);
});

const QuestionCardContainer = styled.div`
display: flex;
Expand All @@ -86,7 +104,12 @@ const QuestionInfo = styled.div`
align-items: end;
gap: 12px;
.name_info {
${({ theme }) => theme.tokenTypographys['display-bold12']}
border-radius: 7px;
${({ theme }) => theme.tokenTypographys['display-bold12']};
cursor: pointer;
&:hover {
color: #bbbbbb;
}
}
.time_info {
${({ theme }) => theme.tokenTypographys['display-medium12']}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/host/SettingInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ export default function SettingInfo({ closeModal }: SettingInfoProps) {
<SettingRow>
<Label htmlFor="streamUrl">스트림 URL</Label>
<ValueWithButton>
<StreamURL>rtmp://liboo.kr:1935/live</StreamURL>
<CopyButton onClick={() => navigator.clipboard.writeText('rtmp://liboo.kr:1935/live')}>
<StreamURL>rtmp://test.liboo.kr:1935/live</StreamURL>
<CopyButton onClick={() => navigator.clipboard.writeText('rtmp://test.liboo.kr:1935/live')}>
복사
</CopyButton>
</ValueWithButton>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/contexts/chatContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const chatReducer = (state: ChatState, action: Action): ChatState => {
const initialState: ChatState = {
isSettingsOpen: false,
settingOption: null,
isNoticePopupOpen: false,
isNoticePopupOpen: true,
isUserInfoPopupOpen: false,
selectedUser: null
};
Expand Down
6 changes: 3 additions & 3 deletions nginx/conf.d/rtmp.conf
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
server {
listen 8000 ssl; # HTTPS 8000 포트 수신
server_name liboo.kr;
server_name test.liboo.kr;

ssl_certificate "/etc/letsencrypt/live/liboo.kr/fullchain.pem";
ssl_certificate "/etc/letsencrypt/live/test.liboo.kr/fullchain.pem";
ssl_protocols TLSv1.2 TLSv1.3;
ssl_certificate_key "/etc/letsencrypt/live/liboo.kr/privkey.pem";
ssl_certificate_key "/etc/letsencrypt/live/test.liboo.kr/privkey.pem";
ssl_dhparam "/etc/nginx/ssl/dhparams.pem";
add_header Strict-Transport-Security "max-age=31536000";

Expand Down
9 changes: 6 additions & 3 deletions nginx/conf.d/ssl.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ server {
# listen [::]:443 ssl http2 default_server;
client_max_body_size 10M;

ssl_certificate "/etc/letsencrypt/live/liboo.kr/fullchain.pem";
ssl_certificate "/etc/letsencrypt/live/test.liboo.kr/fullchain.pem";
ssl_protocols TLSv1.2 TLSv1.3;
ssl_certificate_key "/etc/letsencrypt/live/liboo.kr/privkey.pem";
ssl_certificate_key "/etc/letsencrypt/live/test.liboo.kr/privkey.pem";
ssl_dhparam "/etc/nginx/ssl/dhparams.pem";
add_header Strict-Transport-Security "max-age=31536000";
server_name liboo.kr;
server_name test.liboo.kr;

root /usr/share/nginx/html;
index index.html;

root /usr/share/nginx/html;
index index.html;
Expand Down

0 comments on commit d640193

Please sign in to comment.