Skip to content

Commit 8a75a28

Browse files
authored
Merge pull request #68 from djkeh/feature/28-chat
[어드민] 어드민 부가 기능 - 채팅 기능 구현
2 parents 2069fb3 + 9b19560 commit 8a75a28

File tree

11 files changed

+180
-5
lines changed

11 files changed

+180
-5
lines changed

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ dependencies {
2525
implementation 'org.springframework.boot:spring-boot-starter-security'
2626
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
2727
implementation 'org.springframework.boot:spring-boot-starter-web'
28+
implementation 'org.springframework.boot:spring-boot-starter-websocket'
2829
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
30+
implementation 'org.webjars:webjars-locator-core'
31+
implementation 'org.webjars:sockjs-client:1.0.2'
32+
implementation 'org.webjars:stomp-websocket:2.3.3'
2933
compileOnly 'org.projectlombok:lombok'
3034
developmentOnly 'org.springframework.boot:spring-boot-devtools'
3135
runtimeOnly 'com.h2database:h2'
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.fastcampus.projectboardadmin.config;
2+
3+
import org.springframework.context.annotation.Configuration;
4+
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
5+
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
6+
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
7+
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
8+
9+
@EnableWebSocketMessageBroker
10+
@Configuration
11+
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
12+
13+
@Override
14+
public void configureMessageBroker(MessageBrokerRegistry registry) {
15+
registry.enableSimpleBroker("/topic");
16+
registry.setApplicationDestinationPrefixes("/app");
17+
}
18+
19+
@Override
20+
public void registerStompEndpoints(StompEndpointRegistry registry) {
21+
registry.addEndpoint("/chat").withSockJS();
22+
}
23+
24+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.fastcampus.projectboardadmin.controller;
2+
3+
import com.fastcampus.projectboardadmin.dto.websocket.WebSocketMessage;
4+
import org.springframework.messaging.handler.annotation.MessageMapping;
5+
import org.springframework.messaging.handler.annotation.SendTo;
6+
import org.springframework.stereotype.Controller;
7+
8+
import java.security.Principal;
9+
10+
@Controller
11+
public class WebSocketController {
12+
13+
@MessageMapping("/hello")
14+
@SendTo("/topic/chat")
15+
public WebSocketMessage chat(WebSocketMessage message, Principal principal) throws Exception {
16+
Thread.sleep(1000); // 대화하는 느낌을 시뮬레이션
17+
18+
return WebSocketMessage.of("안녕하세요 " + principal.getName() + "! " + message.content() + "라고 하셨나요?");
19+
}
20+
21+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.fastcampus.projectboardadmin.dto.websocket;
2+
3+
public record WebSocketMessage(String content) {
4+
public static WebSocketMessage of(String content) {
5+
return new WebSocketMessage(content);
6+
}
7+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
let stompClient = null;
2+
3+
function connect() {
4+
const socket = new SockJS('/chat');
5+
stompClient = Stomp.over(socket);
6+
stompClient.connect({}, function (frame) {
7+
console.log('Connected: ' + frame);
8+
stompClient.subscribe('/topic/chat', function (message) {
9+
respondMessage(JSON.parse(message.body).content);
10+
});
11+
});
12+
}
13+
14+
function sendMessage() {
15+
const message = $('#input-message').val();
16+
17+
$(".direct-chat-messages").append(`
18+
<div class="direct-chat-msg">
19+
<div class="direct-chat-infos clearfix">
20+
<span class="direct-chat-name float-left">Uno</span>
21+
</div>
22+
<div class="direct-chat-text">
23+
${message}
24+
</div>
25+
</div>
26+
`);
27+
28+
stompClient.send("/app/hello", {}, JSON.stringify({'content': $("#input-message").val()}));
29+
}
30+
31+
function respondMessage(message) {
32+
$(".direct-chat-messages").append(`
33+
<div class="direct-chat-msg right">
34+
<div class="direct-chat-infos clearfix">
35+
<span class="direct-chat-name float-right">Bot</span>
36+
</div>
37+
<div class="direct-chat-text">
38+
${message}
39+
</div>
40+
</div>
41+
`);
42+
}
43+
44+
$(function () {
45+
$("#chat-form").on('submit', function (e) {
46+
e.preventDefault();
47+
sendMessage();
48+
});
49+
$("#chat-form button").click(function(e) {
50+
sendMessage();
51+
});
52+
});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<!DOCTYPE html>
2+
<html lang="ko">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>공통 카드 (Direct Chat)</title>
6+
</head>
7+
<body>
8+
<!-- DIRECT CHAT -->
9+
<div class="card direct-chat direct-chat-primary" id="layout-card-chat">
10+
<div class="card-header">
11+
<h3 class="card-title">Direct Chat</h3>
12+
13+
<div class="card-tools">
14+
<button type="button" class="btn btn-tool" data-card-widget="collapse">
15+
<i class="fas fa-minus"></i>
16+
</button>
17+
</div>
18+
</div>
19+
<!-- /.card-header -->
20+
<div class="card-body">
21+
<!-- Conversations are loaded here -->
22+
<div class="direct-chat-messages">
23+
<!-- Message. Default to the left -->
24+
</div>
25+
<!--/.direct-chat-messages-->
26+
</div>
27+
<!-- /.card-body -->
28+
<div class="card-footer">
29+
<form id="chat-form">
30+
<div class="input-group">
31+
<label for="input-message"></label>
32+
<input id="input-message" type="text" name="message" placeholder="Type Message ..." class="form-control">
33+
<span class="input-group-append">
34+
<button type="button" class="btn btn-primary">Send</button>
35+
</span>
36+
</div>
37+
</form>
38+
</div>
39+
<!-- /.card-footer-->
40+
</div>
41+
<!--/.direct-chat -->
42+
</body>
43+
</html>

src/main/resources/templates/layouts/layout-card-todolist.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<title>공통 카드 (Todo List)</title>
66
</head>
77
<body>
8-
<div class="card col-6" id="layout-card-todolist">
8+
<div class="card" id="layout-card-todolist">
99
<div class="card-header">
1010
<h3 class="card-title">
1111
<i class="ion ion-clipboard mr-1"></i>

src/main/resources/templates/layouts/layout-left-aside.th.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0"?>
22
<thlogic>
33
<attr sel="#admin-logo-link" th:href="@{/}" />
4-
<attr sel="#user-profile" th:href="@{#}" />
4+
<attr sel="#user-profile" th:href="@{#}" sec:authorize="isAuthenticated()" sec:authentication="principal.nickname" />
55
<attr sel="#management-category" th:classappend="${#request.requestURI.startsWith('/management')} ? 'active'" />
66
<attr
77
sel="#article-management"

src/main/resources/templates/layouts/layout-main-table.html

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ <h1 id="main-header-title" class="m-0">메인 페이지</h1>
2424
</div>
2525
<!-- /.content-header -->
2626

27-
<!-- <section id="main-section"></section>-->
2827
<section class="content">
2928
<div class="container-fluid">
3029
<div class="row">
@@ -40,10 +39,17 @@ <h3 id="card-title" class="card-title">카드 제목</h3>
4039
<!-- /.card-body -->
4140
</div>
4241
<!-- /.card -->
42+
</section>
43+
</div>
44+
<!-- /.row -->
4345

44-
<div class="card col-6" id="layout-card-todolist"></div>
46+
<div class="row">
47+
<section class="col-6 connectedSortable">
48+
<div class="card" id="layout-card-todolist"></div>
49+
</section>
50+
<section class="col-6 connectedSortable">
51+
<div class="card" id="layout-card-chat"></div>
4552
</section>
46-
<!-- /.col -->
4753
</div>
4854
<!-- /.row -->
4955
</div>

src/main/resources/templates/layouts/layout-main-table.th.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
<attr sel="#card-title" th:text="|${title} 게시판|" />
88
<attr sel="#main-table" th:replace="${table}" />
99
<attr sel="#layout-card-todolist" th:replace="layouts/layout-card-todolist :: #layout-card-todolist" />
10+
<attr sel="#layout-card-chat" th:replace="layouts/layout-card-chat :: #layout-card-chat" />
1011
</thlogic>

0 commit comments

Comments
 (0)