Simplify project structure

- harmonize module and directory names
- optimize Gradle settings
- remove unused Grails sample

Resolves: #1447
This commit is contained in:
Vedran Pavic
2019-06-04 23:08:08 +02:00
parent a4ff3682f6
commit 084d1c7286
269 changed files with 17 additions and 858 deletions

View File

@@ -0,0 +1,2 @@
#server.servlet.session.timeout=1m
spring.h2.console.enabled=true

View File

@@ -0,0 +1,5 @@
insert into user(id,email,password,first_name,last_name) values (0,'rob','password','Rob','Winch');
insert into user(id,email,password,first_name,last_name) values (1,'luke','password','Luke','Taylor');
insert into user(id,email,password,first_name,last_name) values (2,'eve','password','Luke','Taylor');
update user set password = '$2a$10$FBAKClV1zBIOOC9XMXf3AO8RoGXYVYsfvUdoLxGkd/BnXEn4tqT3u';

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,152 @@
function ApplicationModel(stompClient) {
var self = this;
self.friends = ko.observableArray();
self.username = ko.observable();
self.conversation = ko.observable(new ImConversationModel(stompClient,this.username));
self.notifications = ko.observableArray();
self.csrfToken = ko.computed(function() {
return JSON.parse($.ajax({
type: 'GET',
url: 'csrf',
dataType: 'json',
success: function() { },
data: {},
async: false
}).responseText);
}, this);
self.connect = function() {
var headers = {};
var csrf = self.csrfToken();
headers[csrf.headerName] = csrf.token;
stompClient.connect(headers, function(frame) {
console.log('Connected ' + frame);
self.username(frame.headers['user-name']);
// self.friendSignin({"username": "luke"});
stompClient.subscribe("/user/queue/errors", function(message) {
self.pushNotification("Error " + message.body);
});
stompClient.subscribe("/app/users", function(message) {
var friends = JSON.parse(message.body);
for(var i=0;i<friends.length;i++) {
self.friendSignin({"username": friends[i]});
}
});
stompClient.subscribe("/topic/friends/signin", function(message) {
var friends = JSON.parse(message.body);
for(var i=0;i<friends.length;i++) {
self.friendSignin(new ImFriend({"username": friends[i]}));
}
});
stompClient.subscribe("/topic/friends/signout", function(message) {
var friends = JSON.parse(message.body);
for(var i=0;i<friends.length;i++) {
self.friendSignout(new ImFriend({"username": friends[i]}));
}
});
stompClient.subscribe("/user/queue/messages", function(message) {
self.conversation().receiveMessage(JSON.parse(message.body));
});
}, function(error) {
self.pushNotification(error)
console.log("STOMP protocol error " + error);
});
}
self.pushNotification = function(text) {
self.notifications.push({notification: text});
if (self.notifications().length > 5) {
self.notifications.shift();
}
}
self.logout = function() {
stompClient.disconnect();
window.location.href = "../logout.html";
}
self.friendSignin = function(friend) {
self.friends.push(friend);
}
self.friendSignout = function(friend) {
var r = self.friends.remove(
function(item) {
item.username == friend.username
}
);
self.friends(r);
}
}
function ImFriend(data) {
var self = this;
self.username = data.username;
}
function ImConversationModel(stompClient,from) {
var self = this;
self.stompClient = stompClient;
self.from = from;
self.to = ko.observable(new ImFriend('null'));
self.draft = ko.observable('')
self.messages = ko.observableArray();
self.receiveMessage = function(message) {
var elem = $('#chat');
var isFromSelf = self.from() == message.from;
var isFromTo = self.to().username == message.from;
if(!(isFromTo || isFromSelf)) {
self.chat(new ImFriend({"username":message.from}))
}
var atBottom = (elem[0].scrollHeight - elem.scrollTop() == elem.outerHeight());
self.messages.push(new ImModel(message));
if (atBottom)
elem.scrollTop(elem[0].scrollHeight);
};
self.chat = function(to) {
self.to(to);
self.draft('');
self.messages.removeAll()
$('#trade-dialog').modal();
}
self.send = function() {
var data = {
"created" : new Date(),
"from" : self.from(),
"to" : self.to().username,
"message" : self.draft()
};
var destination = "/app/im"; // /queue/messages-user1
stompClient.send(destination, {}, JSON.stringify(data));
self.draft('');
}
};
function ImModel(data) {
var self = this;
self.created = new Date(data.created);
self.to = data.to;
self.message = data.message;
self.from = data.from;
self.messageFormatted = ko.computed(function() {
return self.created.getHours() + ":" + self.created.getMinutes() + ":" + self.created.getSeconds() + " - " + self.from + " - " + self.message;
})
};

View File

@@ -0,0 +1,74 @@
<html xmlns:th="https://www.thymeleaf.org" xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect" layout:decorate="~{layout}">
<head>
<title>View All</title>
</head>
<body>
<div layout:fragment="content">
<div class="container">
<div id="heading" class="masthead">
<h3 class="muted">Chat Application</h3>
</div>
<div id="main-content">
<table class="table table-striped">
<thead>
<tr>
<th>User</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: friends()">
<tr>
<td data-bind="text: username"></td>
<td class="trade-buttons">
<button class="btn btn-primary" data-bind="click: $root.conversation().chat">Chat</button>
</td>
</tr>
</tbody>
</table>
<div id="trade-dialog" class="modal hide fade" tabindex="-1">
<div class="modal-body">
<div>Chat with <span data-bind="text: conversation().to().username"></span></div>
<div id="chat" style="height: 5em;max-height: 200px;overflow:scroll" data-bind="foreach: conversation().messages()">
<div data-bind="text: messageFormatted"></div>
</div>
<form class="form-horizontal" data-bind="submit: conversation().send">
<textarea data-bind="value: conversation().draft"></textarea>
<button class="btn btn-primary" type="submit">Send</button>
</form>
</div>
</div>
<div class="alert alert-warning">
<h5>Notifications</h5>
<ul data-bind="foreach: notifications">
<li data-bind="text: notification"></li>
</ul>
</div>
</div>
</div>
<!-- 3rd party -->
<script th:src="@{/webjars/jquery/jquery.min.js}" src="/webjars/jquery/jquery.min.js"></script>
<script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}" src="/webjars/bootstrap/js/bootstrap.min.js"></script>
<script th:src="@{/webjars/knockout/knockout.js}" src="/webjars/knockout/knockout.js"></script>
<script th:src="@{/webjars/sockjs-client/sockjs.min.js}" src="/webjars/sockjs-client/sockjs.min.js"></script>
<script th:src="@{/webjars/stomp-websocket/stomp.min.js}" src="/webjars/stomp-websocket/stomp.min.js"></script>
<!-- application -->
<script th:src="@{/js/message.js}" src="../static/js/message.js"></script>
<script type="text/javascript">
(function() {
var socket = new SockJS('/messages');
var stompClient = Stomp.over(socket);
var appModel = new ApplicationModel(stompClient);
ko.applyBindings(appModel);
appModel.connect();
})();
</script>
</div>
</body>
</html>

View File

@@ -0,0 +1,124 @@
<!DOCTYPE html SYSTEM "https://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="https://www.thymeleaf.org"
xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect">
<head>
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">Spring Session Sample</title>
<link rel="icon" type="image/x-icon" th:href="@{/favicon.ico}" href="../static/favicon.ico"/>
<link th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" href="/webjars/bootstrap/css/bootstrap.min.css" rel="stylesheet"></link>
<style type="text/css">
/* Sticky footer styles
-------------------------------------------------- */
html,
body {
height: 100%;
/* The html and body elements cannot have any padding or margin. */
}
/* Wrapper for page content to push down footer */
#wrap {
min-height: 100%;
height: auto !important;
height: 100%;
/* Negative indent footer by it's height */
margin: 0 auto -60px;
}
/* Set the fixed height of the footer here */
#push,
#footer {
height: 60px;
}
#footer {
background-color: #f5f5f5;
}
/* Lastly, apply responsive CSS fixes as necessary */
@media (max-width: 767px) {
#footer {
margin-left: -20px;
margin-right: -20px;
padding-left: 20px;
padding-right: 20px;
}
}
/* Custom page CSS
-------------------------------------------------- */
/* Not required for template or sticky footer method. */
.container {
width: auto;
max-width: 680px;
}
.container .credit {
margin: 20px 0;
text-align: center;
}
a {
color: green;
}
.navbar-form {
margin-left: 1em;
}
</style>
<link th:href="@{/webjars/bootstrap/css/bootstrap-responsive.min.css}" href="/webjars/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet"></link>
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script th:src="@{/webjars/html5shiv/html5shiv.min.js}" src="/webjars/html5shiv/html5shiv.min.js"></script>
<![endif]-->
</head>
<body>
<div id="wrap">
<div class="navbar navbar-inverse navbar-static-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" th:href="@{/}"><img th:src="@{/images/logo.png}" alt="Spring Security Sample"/></a>
<div class="nav-collapse collapse"
th:with="currentUser=${#httpServletRequest.userPrincipal?.principal}">
<div th:if="${currentUser != null}">
<form class="navbar-form pull-right" th:action="@{/logout}" method="post">
<input type="submit" value="Log out" />
</form>
<p id="un" class="navbar-text pull-right" th:text="${currentUser.username}">
sample_user
</p>
</div>
<ul class="nav">
<li><a th:href="@{/}">IM</a></li>
<li><a th:href="@{/h2-console/}">H2</a></li>
</ul>
</div>
</div>
</div>
</div>
<!-- Begin page content -->
<div class="container">
<div class="alert alert-success"
th:if="${globalMessage}"
th:text="${globalMessage}">
Some Success message
</div>
<div layout:fragment="content">
Fake content
</div>
</div>
<div id="push"><!-- --></div>
</div>
<div id="footer">
<div class="container">
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site for more <a href="https://github.com/spring-projects/spring-session/tree/master/samples">samples</a>.</p>
</div>
</div>
</body>
</html>