Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

. #136

Closed
wants to merge 11 commits into from
Closed

. #136

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions back/src/chat-logs/chat-logs.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export class ChatLogsService {
const chat = await Chat.findOneOrFail({
where: {
uuid: createChatLogInput.chatUUID,
isAlive: true,
},
}).catch(() => {
const error = { uuid: `chat with uuid(${createChatLogInput.chatUUID}) does not exist.` };
Expand All @@ -24,6 +25,11 @@ export class ChatLogsService {
const error = { userID: `user(ID: ${createChatLogInput.userID}) does not exist.` };
throw new HttpException({ message: 'Input data validation failed', error }, HttpStatus.BAD_REQUEST);
});
//음소거 된 유저가 메세지를 보낼 경우
//TODO: 채팅방 목록에 없는 유저가 채팅을 보낼 때 exception 발생
if (createChatLogInput.type === 'message' && chat.muteID.includes(user.userID)) {
throw new HttpException({ message: 'Input data validation failed' }, HttpStatus.BAD_REQUEST);
}
const chatLog = new ChatLog();
chatLog.chatUUID = chat.uuid;
chatLog.message = createChatLogInput.message;
Expand Down
8 changes: 8 additions & 0 deletions back/src/chats/chats.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,12 @@ export class ChatsResolver {
) {
return this.chatsService.checkPassword(uuid, password);
}

@Mutation(() => Chat)
toggleMute(
@Args('uuid', { type: () => String }) uuid: string,
@Args('userID', { type: () => String }) userID: string,
) {
return this.chatsService.toggleMute(uuid, userID);
}
}
34 changes: 34 additions & 0 deletions back/src/chats/chats.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@ import { CreateChatInput } from './dto/create-chat.input';
import { UpdateChatInput } from './dto/update-chat.input';
import { Chat } from './entities/chat.entity';
import { validate } from 'class-validator';
import { User } from 'src/users/entities/user.entity';

@Injectable()
export class ChatsService {
private checkNameValication(name: string) {
if (name === '' || name.search(/[^a-zA-Z0-9ㄱ-ㅎ가-힣]/g) !== -1) {
const error = { password: `Chat name must be number, english, or korean.` };
throw new HttpException({ message: 'Input data validation failed', error }, HttpStatus.BAD_REQUEST);
}
}

private checkPasswordValidation(type: string, password: string) {
if (type === 'private') {
if (password === '' || password === undefined) {
Expand All @@ -31,6 +39,7 @@ export class ChatsService {
chat.type = createChatInput.type;
chat.ownerID = createChatInput.ownerID;
chat.userID = [createChatInput.ownerID];
this.checkNameValication(chat.name);
this.checkPasswordValidation(createChatInput.type, createChatInput.password);

//class-validator
Expand Down Expand Up @@ -71,6 +80,7 @@ export class ChatsService {
chat.isAlive = updateChatInput.isAlive !== undefined ? updateChatInput.isAlive : chat.isAlive;
chat.adminID = updateChatInput.adminID ? updateChatInput.adminID : chat.adminID;
chat.userID = updateChatInput.userID ? updateChatInput.userID : chat.userID;
chat.muteID = updateChatInput.muteID ? updateChatInput.muteID : chat.muteID;
const validate_error = await validate(chat);
if (validate_error.length > 0) {
throw new HttpException({ message: 'Input data validation failed' }, HttpStatus.BAD_REQUEST);
Expand Down Expand Up @@ -138,4 +148,28 @@ export class ChatsService {
: false;
return isMatchedPassword;
}

//mute, unmute
async toggleMute(uuid: string, userID: string) {
const chat = await Chat.findOneOrFail({
where: {
uuid: uuid,
},
}).catch(() => {
const error = { uuid: `chat with uuid(${uuid}) does not exist` };
throw new HttpException({ message: 'Input data validation failed', error }, HttpStatus.BAD_REQUEST);
});
const user = await User.findOneOrFail({
where: {
userID: userID,
},
}).catch(() => {
const error = { uuid: `userID(${userID}) does not exist` };
throw new HttpException({ message: 'Input data validation failed', error }, HttpStatus.BAD_REQUEST);
});
chat.muteID = chat.muteID.includes(user.userID)
? chat.muteID.filter((item) => item !== user.userID)
: [...chat.muteID, user.userID];
return await Chat.save(chat);
}
}
3 changes: 3 additions & 0 deletions back/src/chats/dto/update-chat.input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ export class UpdateChatInput extends PartialType(CreateChatInput) {

@Field((type) => [String], { nullable: true })
userID: string[];

@Field((type) => [String], { nullable: true })
muteID: string[];
}
4 changes: 4 additions & 0 deletions back/src/chats/entities/chat.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export class Chat extends BaseEntity {
@Column({ type: 'varchar', array: true, nullable: true, default: {} })
userID: string[];

@Field((type) => [String])
@Column({ type: 'varchar', array: true, nullable: true, default: {} })
muteID: string[];

@Field()
@CreateDateColumn()
createdAt: Date;
Expand Down
58 changes: 29 additions & 29 deletions back/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1184,17 +1184,17 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==

"@carbon/icon-helpers@^10.19.0":
version "10.19.0"
resolved "https://registry.yarnpkg.com/@carbon/icon-helpers/-/icon-helpers-10.19.0.tgz#f6b608b181b4ca4aeeadac72ec11b7cf530b4d1c"
integrity sha512-2eIecDuoEEx+nORHtTBmj5lV/N4Q1kP7XCZUkF15WfXxZHx2RI6KhS4HnMPDoylguhavnRjSIK1gl6oG3Z3wSQ==
"@carbon/icon-helpers@^10.20.0":
version "10.20.0"
resolved "https://registry.yarnpkg.com/@carbon/icon-helpers/-/icon-helpers-10.20.0.tgz#4e6752b984fcbfd5851af5c4dfdab5031bb4aa1d"
integrity sha512-Qe/xHnMDwji541+2ibn90eFI5xWh51SQ6ehmHncagNrPIJb3a+x1DMhQcAMUF6YKwGzSbb5VQfay5wFoxcaf+A==

"@carbon/icons-react@^10.14.0":
version "10.35.0"
resolved "https://registry.yarnpkg.com/@carbon/icons-react/-/icons-react-10.35.0.tgz#dd1e7b9bc233d8d69cb293d01c24c456f7a01eb0"
integrity sha512-FkyY648pyqNeg3MlXuwH6Zf+OTOkCoKQym/qdvvfmkNrqDrM1xWZlJNNFTNpy0RBrjJYptmkN2vLSoffUuZDaQ==
version "10.36.0"
resolved "https://registry.yarnpkg.com/@carbon/icons-react/-/icons-react-10.36.0.tgz#a09dc6b4bcda2f43063014af38e112081a2a91fb"
integrity sha512-lWmG8v09XTVKPsGd0kbZgYAwvQ99XB3Szt0y91W3b2zKXiSilyFuSbG9Vd6fwrfaP84QG48MnCFdct0Aww57Xg==
dependencies:
"@carbon/icon-helpers" "^10.19.0"
"@carbon/icon-helpers" "^10.20.0"
"@carbon/telemetry" "0.0.0-alpha.6"
prop-types "^15.7.2"

Expand Down Expand Up @@ -1632,9 +1632,9 @@
uuid "8.3.2"

"@nestjs/config@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@nestjs/config/-/config-1.0.0.tgz#966067195826b9b82b6fc63e990e31af28912185"
integrity sha512-Id5dQsCISMxWu0oPKcEP4ltQ5Z6eY748WHIXNOFc2Q9qehvHVk8iMRMmTIzTJ+eCOB6qKBAdhTI4KuRyRlwAuQ==
version "1.0.1"
resolved "https://registry.yarnpkg.com/@nestjs/config/-/config-1.0.1.tgz#3d794a8af7fb2cc2b1605a8a293eeae14b2d290d"
integrity sha512-azMl4uYlFIhYsywFxPJT81RxF3Pnn0TZW3EEmr0Wa0Wex8R2xpvBNrCcrOgW3TB1xGMP7eqBrlfsVh5ZP82szg==
dependencies:
dotenv "10.0.0"
dotenv-expand "5.1.0"
Expand Down Expand Up @@ -2336,9 +2336,9 @@
form-data "^3.0.0"

"@types/node@*":
version "16.4.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.4.0.tgz#2c219eaa3b8d1e4d04f4dd6e40bc68c7467d5272"
integrity sha512-HrJuE7Mlqcjj+00JqMWpZ3tY8w7EUd+S0U3L1+PQSWiXZbOgyQDvi+ogoUxaHApPJq5diKxYBQwA3iIlNcPqOg==
version "16.4.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.4.1.tgz#9fad171a5b701613ee8a6f4ece3c88b1034b1b03"
integrity sha512-UW7cbLqf/Wu5XH2RKKY1cHwUNLicIDRLMraYKz+HHAerJ0ZffUEk+fMnd8qU2JaS6cAy0r8tsaf7yqHASf/Y0Q==

"@types/node@^10.1.0":
version "10.17.60"
Expand Down Expand Up @@ -4290,9 +4290,9 @@ date-fns@2.15.0:
integrity sha512-ZCPzAMJZn3rNUvvQIMlXhDr4A+Ar07eLeGsGREoWU19a3Pqf5oYa+ccd+B3F6XVtQY6HANMFdOQ8A+ipFnvJdQ==

date-fns@^2.0.1:
version "2.22.1"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.22.1.tgz#1e5af959831ebb1d82992bf67b765052d8f0efc4"
integrity sha512-yUFPQjrxEmIsMqlHhAhmxkuH769baF21Kk+nZwZGyrMoyLA+LugaQtC0+Tqf9CBUUULWwUJt6Q5ySI3LJDDCGg==
version "2.23.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.23.0.tgz#4e886c941659af0cf7b30fafdd1eaa37e88788a9"
integrity sha512-5ycpauovVyAk0kXNZz6ZoB9AYMZB4DObse7P3BPWmyEjXNORTI8EJ6X0uaSAq4sCHzM1uajzrkr6HnsLQpxGXA==

debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
version "2.6.9"
Expand Down Expand Up @@ -4547,9 +4547,9 @@ ee-first@1.1.1:
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=

electron-to-chromium@^1.3.723:
version "1.3.784"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.784.tgz#c370be79374b02b7f13e8a8fb0d7a02641161dac"
integrity sha512-JTPxdUibkefeomWNaYs8lI/x/Zb4cOhZWX+d7kpzsNKzUd07pNuo/AcHeNJ/qgEchxM1IAxda9aaGUhKN/poOg==
version "1.3.785"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.785.tgz#79f546c69a6be4f30913aaace361bc746f26df48"
integrity sha512-WmCgAeURsMFiyoJ646eUaJQ7GNfvMRLXo+GamUyKVNEM4MqTAsXyC0f38JEB4N3BtbD0tlAKozGP5E2T9K3YGg==

emittery@^0.7.1:
version "0.7.2"
Expand Down Expand Up @@ -6901,9 +6901,9 @@ lines-and-columns@^1.1.6:
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=

lint-staged@^11.0.0:
version "11.0.1"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-11.0.1.tgz#1b8ae8ed5a52ed87252db95fe008c2618c85f55a"
integrity sha512-RkTA1ulE6jAGFskxpGAwxfVRXjHp7D9gFg/+KMARUWMPiVFP0t28Em2u0gL8sA0w3/ck3TC57F2v2RNeQ5XPnw==
version "11.1.0"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-11.1.0.tgz#a21d67ffe4516e907635adeaf6d6450d8cffb4e4"
integrity sha512-pzwEf+NKbTauAlk7gPPwTfulRXESEPZCSFXYfg20F220UOObebxu5uL5mkr9csQLNOM2Ydfrt3DJXakzAL7aaQ==
dependencies:
chalk "^4.1.1"
cli-truncate "^2.1.0"
Expand All @@ -6922,9 +6922,9 @@ lint-staged@^11.0.0:
stringify-object "^3.3.0"

listr2@^3.8.2:
version "3.10.0"
resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.10.0.tgz#58105a53ed7fa1430d1b738c6055ef7bb006160f"
integrity sha512-eP40ZHihu70sSmqFNbNy2NL1YwImmlMmPh9WO5sLmPDleurMHt3n+SwEWNu2kzKScexZnkyFtc1VI0z/TGlmpw==
version "3.11.0"
resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.11.0.tgz#9771b02407875aa78e73d6e0ff6541bbec0aaee9"
integrity sha512-XLJVe2JgXCyQTa3FbSv11lkKExYmEyA4jltVo8z4FX10Vt1Yj8IMekBfwim0BSOM9uj1QMTJvDQQpHyuPbB/dQ==
dependencies:
cli-truncate "^2.1.0"
colorette "^1.2.2"
Expand Down Expand Up @@ -8657,9 +8657,9 @@ regenerate@^1.4.0:
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==

regenerator-runtime@^0.13.4:
version "0.13.7"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==
version "0.13.9"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==

regenerator-transform@^0.14.2:
version "0.14.5"
Expand Down
12 changes: 12 additions & 0 deletions front/src/UI/molecules/Alarm/AlarmChatMessage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ const ChatNotification = ({ chatID, message }: IchatNotification) => {
{chatID}님이 음소거되었습니다.
</Text>
);
} else if (message === 'unmute') {
return (
<Text p="1" fontSize={ALARM_CHAT_MESSAGE_NOTIFICATION_FONTSIZE} textAlign="center">
{chatID}님의 음소거가 해제되었습니다.
</Text>
);
} else if (message === 'enter') {
return (
<Text p="1" fontSize={ALARM_CHAT_MESSAGE_NOTIFICATION_FONTSIZE} textAlign="center">
Expand All @@ -62,6 +68,12 @@ const ChatNotification = ({ chatID, message }: IchatNotification) => {
{chatID}님이 채팅방을 나가셨습니다.
</Text>
);
} else if (message === 'destroy') {
return (
<Text p="1" fontSize={ALARM_CHAT_MESSAGE_NOTIFICATION_FONTSIZE} textAlign="center">
채팅이 종료되었습니다.
</Text>
);
} else {
return <Text>[Error: 0000]오류가 발생했습니다. 관리자에게 문의해주세요.</Text>;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { gql } from '@apollo/client';

export const TOGGLE_BLOCK = gql`
mutation toggleBlock($blockInput: BlockInput!) {
toggleBlock(blockInput: $blockInput) {
checked
blocked
}
}
`;

export const TOGGLE_MUTE = gql`
mutation toggleMute($uuid: String!, $userID: String!) {
toggleMute(uuid: $uuid, userID: $userID) {
index
name
muteID
}
}
`;

export const CREATE_CHAT_LOG = gql`
mutation createChatLog($chatLog: CreateChatLogInput!) {
createChatLog(createChatLogInput: $chatLog) {
userID
type
message
}
}
`;
52 changes: 41 additions & 11 deletions front/src/UI/molecules/Alarm/AlarmChatPeople/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React, { useRef } from 'react';
import { useMutation, useReactiveVar } from '@apollo/client';
import { ContextMenu } from 'holee-contextmenu';

import { currentLoginIDVar } from '../../../../apollo/apolloProvider';
import { currentChatVar, currentLoginIDVar } from '../../../../apollo/apolloProvider';
import { CREATE_CHAT_LOG, TOGGLE_BLOCK, TOGGLE_MUTE } from './AlarmChatPeopleQueries';

const AlarmChatPerson = ({ outerRef, username, ownerID, adminID }) => {
const AlarmChatPerson = ({ outerRef, username, ownerID, adminID = [] }) => {
return (
<div ref={outerRef}>
{username}
{ownerID.includes(username) ? ' 👑' : null}
{ownerID === username ? ' 👑' : null}
{adminID.includes(username) ? ' 🏅' : null}
</div>
);
Expand All @@ -19,13 +21,17 @@ export const AlarmChatPeople = ({
adminID,
}: {
username: string;
ownerID: string[];
ownerID: string;
adminID: string[];
}) => {
const outerRef = useRef<HTMLDivElement>(null);
const [toggleBlock] = useMutation(TOGGLE_BLOCK);
const [toggleMute] = useMutation(TOGGLE_MUTE);
const [createChatLog] = useMutation(CREATE_CHAT_LOG);
const loginID = currentLoginIDVar();
const currentChatUUID = useReactiveVar(currentChatVar);

const menuOnClickHandler = (
const menuOnClickHandler = async (
e: React.MouseEvent<HTMLUListElement, MouseEvent> | React.KeyboardEvent<HTMLUListElement>,
) => {
const eventTarget = e.target as HTMLUListElement;
Expand All @@ -47,10 +53,34 @@ export const AlarmChatPeople = ({
console.log(eventTarget.dataset.option);
break;
case 'block':
console.log(eventTarget.dataset.option);
await toggleBlock({
variables: {
blockInput: {
followerID: loginID,
followingID: username,
},
},
});
break;
case 'mute':
console.log(eventTarget.dataset.option);
await toggleMute({
variables: {
uuid: currentChatUUID,
userID: username,
},
}).then((res) => {
const message = res.data.toggleMute.muteID.includes(username) ? 'mute' : 'unmute';
createChatLog({
variables: {
chatLog: {
chatUUID: currentChatUUID,
userID: username,
type: 'notification',
message: message,
},
},
});
});
break;
case 'forced-out':
console.log(eventTarget.dataset.option);
Expand All @@ -71,7 +101,7 @@ export const AlarmChatPeople = ({
<li data-option="play-game">핑퐁게임 요청</li>
<li data-option="register-admin">관리자 임명(해임)</li>
<li data-option="block">차단(차단 해제)하기</li>
<li data-option="mute">음소거</li>
<li data-option="mute">음소거(음소거 해제)하기</li>
<li data-option="forced-out">강제퇴장</li>
</>
)}
Expand All @@ -90,12 +120,12 @@ export const AlarmChatPeople = ({
<li data-option="add-friend">친구추가 요청</li>
<li data-option="play-game">핑퐁게임 요청</li>
<li data-option="block">차단(차단 해제)하기</li>
<li data-option="mute">음소거</li>
<li data-option="mute">음소거(음소거 해제)하기</li>
<li data-option="forced-out">강제퇴장</li>
</>
)}
</ContextMenu>
<AlarmChatPerson outerRef={outerRef} username={username} />
<AlarmChatPerson outerRef={outerRef} username={username} ownerID={ownerID} adminID={adminID} />
</>
);
}
Expand All @@ -112,7 +142,7 @@ export const AlarmChatPeople = ({
</>
)}
</ContextMenu>
<AlarmChatPerson outerRef={outerRef} username={username} />
<AlarmChatPerson outerRef={outerRef} username={username} ownerID={ownerID} adminID={adminID} />
</>
);
};
Loading