Javascript user search implemented

This commit is contained in:
Rohan Sircar 2019-11-30 00:43:50 +05:30
parent 62a7e192e6
commit d193ec0f11
8 changed files with 227 additions and 68 deletions

View File

@ -73,7 +73,7 @@ public class RegistrationController {
return "user/home"; return "user/home";
} }
@GetMapping(value = "/img/{image_id}", produces = MediaType.IMAGE_PNG_VALUE) @GetMapping(value = "/img/captcha/{image_id}", produces = MediaType.IMAGE_PNG_VALUE)
public ResponseEntity<byte[]> getImage(@PathVariable("image_id") Long imageId) throws IOException { public ResponseEntity<byte[]> getImage(@PathVariable("image_id") Long imageId) throws IOException {
final String captchaText = captchaMap.get(imageId); final String captchaText = captchaMap.get(imageId);

View File

@ -1,6 +1,5 @@
package org.ros.chatto.service; package org.ros.chatto.service;
import javax.transaction.Transactional;
import org.ros.chatto.model.UserToken; import org.ros.chatto.model.UserToken;
import org.ros.chatto.repository.TokenRepository; import org.ros.chatto.repository.TokenRepository;
@ -8,43 +7,43 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
@Service @Service
@Transactional
@Slf4j
@CacheConfig(cacheNames = "userTokenCache") @CacheConfig(cacheNames = "userTokenCache")
public class UserTokenService { public class UserTokenService {
@Autowired @Autowired
private TokenRepository tokenRepository; private TokenRepository tokenRepository;
@Transactional(readOnly = true)
@Cacheable(value = "userTokenCache", key = "#userName", unless="#result == null") @Cacheable(value = "userTokenCache", key = "#userName", unless="#result == null")
public UserToken getTokenByUserName(String userName) public UserToken getTokenByUserName(String userName)
{ {
System.out.println("Inside 1"); log.debug("Inside 1");
return tokenRepository.findByUserName(userName); return tokenRepository.findByUserName(userName);
} }
@Transactional(readOnly = true)
@Cacheable(value = "userTokenCache", key = "#tokenString", unless="#result == null") @Cacheable(value = "userTokenCache", key = "#tokenString", unless="#result == null")
public UserToken getTokenByTokenString(String tokenString) public UserToken getTokenByTokenString(String tokenString)
{ {
System.out.println("Inside 2"); log.debug("Inside 2");
return tokenRepository.findByToken(tokenString); return tokenRepository.findByToken(tokenString);
} }
@Transactional
public void saveToken(UserToken userToken) public void saveToken(UserToken userToken)
{ {
// UserToken userToken2 = tokenRepository.findByToken(userToken.getTokenContent()); log.info("Saving auth token");
// if(userToken2!=null) {
// System.out.println("Found valid token");
// return;
// }
// System.out.println("Saving token");
tokenRepository.save(userToken); tokenRepository.save(userToken);
} }
@Transactional
public void deleteToken(String userName) public void deleteToken(String userName)
{ {
log.info("Deleting token for {}", userName);
tokenRepository.deleteByUserName(userName); tokenRepository.deleteByUserName(userName);
} }
} }

View File

@ -14,7 +14,7 @@ spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDial
spring.jpa.hibernate.ddl-auto = none spring.jpa.hibernate.ddl-auto = none
spring.jpa.open-in-view=false spring.jpa.open-in-view=false
spring.jpa.properties.hibernate.generate_statistics=true #spring.jpa.properties.hibernate.generate_statistics=true
logging.level.org.hibernate.stat=debug logging.level.org.hibernate.stat=debug
logging.level.org.springframework.web=DEBUG logging.level.org.springframework.web=DEBUG
logging.level.web=DEBUG logging.level.web=DEBUG

View File

@ -69,6 +69,13 @@ html {
color: white !important; color: white !important;
} }
.search-cancel {
background-color: rgba(0, 0, 0, 0.3) !important;
border: 0 !important;
/* border-color: rgba(0, 0, 0, 0.3) !important; */
color: white !important;
}
.search:focus { .search:focus {
box-shadow: none !important; box-shadow: none !important;
outline: 0px !important; outline: 0px !important;
@ -250,6 +257,7 @@ html {
position: absolute; position: absolute;
padding: 15px 0; padding: 15px 0;
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(6px);
color: white; color: white;
border-radius: 15px; border-radius: 15px;
top: 30px; top: 30px;
@ -278,6 +286,10 @@ html {
background-color: rgba(0, 0, 0, 0.2); background-color: rgba(0, 0, 0, 0.2);
} }
.bg-blur {
backdrop-filter: blur(6px);
}
@media(max-width: 576px) { @media(max-width: 576px) {
.contacts_card { .contacts_card {
margin-bottom: 15px !important; margin-bottom: 15px !important;

View File

@ -18,6 +18,7 @@ var chatTextArea = document.getElementById('chatTextArea');
var postNewMessageUrl = `http://${hostAddress}/api/chat/post/message`; //hostAddress variable is set in the thymeleaf head fragment var postNewMessageUrl = `http://${hostAddress}/api/chat/post/message`; //hostAddress variable is set in the thymeleaf head fragment
var getAllMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`; var getAllMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`;
var getNewMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`; var getNewMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`;
var getActiveUsersUrl = `http://${hostAddress}/api/chat/get/active-users/`;
// var postNewMessageUrl = "http://localhost:8080/api/chat/post/message"; // var postNewMessageUrl = "http://localhost:8080/api/chat/post/message";
// var getAllMessagesUrl = "http://localhost:8080/api/chat/get/messages/"; // var getAllMessagesUrl = "http://localhost:8080/api/chat/get/messages/";
// var getNewMessagesUrl = "http://localhost:8080/api/chat/get/messages/"; // var getNewMessagesUrl = "http://localhost:8080/api/chat/get/messages/";
@ -32,6 +33,10 @@ var source = document.getElementById("msg_container_template").innerHTML;
var msgContainerTemplate = Handlebars.compile(source); var msgContainerTemplate = Handlebars.compile(source);
var source = document.getElementById("msg_container_send_template").innerHTML; var source = document.getElementById("msg_container_send_template").innerHTML;
var msgContainerSendTemplate = Handlebars.compile(source); var msgContainerSendTemplate = Handlebars.compile(source);
var source = document.getElementById("user-contact-online-template").innerHTML;
var userContactOnlineTemplate = Handlebars.compile(source);
var source = document.getElementById("user-contact-offline-template").innerHTML;
var userContactOfflineTemplate = Handlebars.compile(source);
var chatAreaNew = document.getElementById('chat_area_new'); var chatAreaNew = document.getElementById('chat_area_new');
@ -39,6 +44,22 @@ var userBoxes = document.getElementsByName('user-box');
var md = window.markdownit(); var md = window.markdownit();
var activeUsers = {};
var fuseOptions = {
shouldSort: true,
threshold: 0.01,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: [
"userName",
]
};
log.setLevel('TRACE');
alertify.set('notifier', 'position', 'top-center'); alertify.set('notifier', 'position', 'top-center');
// Loop through the buttons and add the active class to the current/clicked button // Loop through the buttons and add the active class to the current/clicked button
@ -56,39 +77,54 @@ alertify.set('notifier', 'position', 'top-center');
// }); // });
// } // }
for (let i = 0; i < userBoxes.length; i++) { getActiveUsers(authToken)
userBoxes[i].addEventListener('click', function() { .then(data => {
let current = document.getElementsByClassName('user-box active'); // activeUsers = data;
let passphrase = passphraseInput.value; sessionStorage.setItem('activeUsers', JSON.stringify(data));
if (current.length > 0) { log.log(sessionStorage.getItem('activeUsers'));
if (passphrase == '') { })
// alert('Please input passphrase')
alertify.error('Please enter a passphrase');
return;
}
current[0].className = current[0].className.replace(" active", "");
for (let i = 0; i < userBoxes.length; i++) {
userBoxes[i].addEventListener('click', userCallBack)
}
function addUserCallBacks() {
for (let i = 0; i < userBoxes.length; i++) {
userBoxes[i].addEventListener('click', userCallBack)
}
}
function userCallBack() {
let current = document.getElementsByClassName('user-box active');
let passphrase = passphraseInput.value;
if (current.length > 0) {
if (passphrase == '') {
// alert('Please input passphrase')
alertify.error('Please enter a passphrase');
return;
} }
// Add the active class to the current/clicked button current[0].className = current[0].className.replace(" active", "");
else if (current.length == 0) {
let elem = document.getElementById('passphrase-initial'); }
passphrase = elem.value; // Add the active class to the current/clicked button
if (passphrase == '') { else if (current.length == 0) {
// alert('Please input passphrase') let elem = document.getElementById('passphrase-initial');
alertify.error('Please enter a passphrase'); passphrase = elem.value;
return; if (passphrase == '') {
} // alert('Please input passphrase')
document.getElementById('no-user-selected').hidden = true; alertify.error('Please enter a passphrase');
document.getElementById('chat-card').hidden = false; return;
elem.hidden = true;
} }
// console.log(this.getElementsByClassName('to-user-span')); document.getElementById('no-user-selected').hidden = true;
let userName = this.getElementsByClassName('to-user-span')[0].innerText; document.getElementById('chat-card').hidden = false;
document.getElementById('user-name-span').innerText = userName; elem.hidden = true;
populateMessages(userName, passphrase); }
sessionStorage.setItem('selectedUser', userName); // console.log(this.getElementsByClassName('to-user-span'));
this.className += " active"; let userName = this.getElementsByClassName('to-user-span')[0].innerText;
}) document.getElementById('user-name-span').innerText = userName;
populateMessages(userName, passphrase);
sessionStorage.setItem('selectedUser', userName);
this.className += " active";
} }
function populateMessages(userName, passphrase) { function populateMessages(userName, passphrase) {
@ -240,12 +276,11 @@ function populateMessages(userName, passphrase) {
scrollChatAreaAnimated(2400); scrollChatAreaAnimated(2400);
}) })
}); });
} }
// sessionStorage.clear();
// chatTextArea.append(JSON.stringify(storedMessages)); // chatTextArea.append(JSON.stringify(storedMessages));
} }
@ -317,6 +352,56 @@ document.getElementById('chatMessageForm').addEventListener('submit', function(e
messageSend(JSON.stringify(chatMessageDTO)); messageSend(JSON.stringify(chatMessageDTO));
}) })
document.getElementById('user-search').addEventListener('submit', function(e) {
e.preventDefault();
let contactsBox = document.getElementById('contacts-box');
let temp = contactsBox.innerHTML;
// log.trace(temp);
let searchTerm = document.getElementById('user-search-term').value;
log.debug("search term value = " + searchTerm);
let list = JSON.parse(sessionStorage.getItem('activeUsers'));
log.debug("active users");
log.debug(list);
let fuse = new Fuse(list, fuseOptions);
let searchResult = fuse.search(searchTerm);
populateContactsBox(contactsBox, searchResult);
addUserCallBacks();
log.debug(searchResult);
})
document.getElementById('user-search-term').addEventListener('input', function(e) {
e.preventDefault();
if (this.value.length < 2) {
log.debug("inputted")
let cancelButton = document.getElementById('user-search-cancel');
cancelButton.hidden = false;
}
})
document.getElementById('user-search-cancel').addEventListener('click', function(e) {
e.preventDefault();
let list = JSON.parse(sessionStorage.getItem('activeUsers'));
let contactsBox = document.getElementById('contacts-box');
populateContactsBox(contactsBox,list);
addUserCallBacks();
document.getElementById('user-search-term').value = "";
this.hidden = true;
})
function populateContactsBox(contactsBox, list)
{
let userContactBoxList = "";
list.forEach(function(activeUser) {
log.debug(activeUser);
if (activeUser.online) {
userContactBoxList += userContactOnlineTemplate(activeUser);
} else {
userContactBoxList += userContactOfflineTemplate(activeUser);
}
})
contactsBox.innerHTML = userContactBoxList;
}
// console.log('Credentials = ' + JSON.parse(sessionStorage.getItem('credentials'))); // console.log('Credentials = ' + JSON.parse(sessionStorage.getItem('credentials')));
@ -379,6 +464,23 @@ async function getNewMessages(toUser, lastMessageTimeStamp) {
return data; return data;
} }
async function getActiveUsers(authToken2) {
let headers = new Headers();
// headers.append('Authorization', basicAuthToken);
headers.append('X-AUTH-TOKEN', authToken2);
let response = await fetch(getActiveUsersUrl, {
method: 'GET',
headers: headers
});
console.log(response.clone());
if (fetchErrorHandler(response.clone())) {
return null;
}
let data = await response.json();
return data;
}
$(document).ready(function() { $(document).ready(function() {
$('#action_menu_btn').click(function() { $('#action_menu_btn').click(function() {
$('.action_menu').toggle(); $('.action_menu').toggle();

View File

@ -1,13 +1,6 @@
function storeCredentials() { function storeCredentials() {
let usernameInput = document.getElementById('username'); let usernameInput = document.getElementById('username');
let passwordInput = document.getElementById('password'); let passwordInput = document.getElementById('password');
let credentials = {
username: usernameInput.value,
password: passwordInput.value
}
// sessionStorage.setItem('credentials', JSON.stringify(credentials));
localStorage.setItem('username', usernameInput.value);
var jqxhr = $.ajax({ var jqxhr = $.ajax({
type: 'GET', type: 'GET',
url: `http://${hostAddress}/api/chat/get/token`, url: `http://${hostAddress}/api/chat/get/token`,
@ -19,16 +12,28 @@ function storeCredentials() {
jqxhr.done(function() { jqxhr.done(function() {
let authToken = jqxhr.getResponseHeader('X-AUTH-TOKEN'); let authToken = jqxhr.getResponseHeader('X-AUTH-TOKEN');
localStorage.setItem('authToken', authToken); localStorage.setItem('authToken', authToken);
authToken = localStorage.getItem('authToken')
console.log("getting header " + authToken); console.log("getting header " + authToken);
secondClick = true;
$('#loginForm').submit();
}); });
//this section is executed when the server responds with error //this section is executed when the server responds with error
jqxhr.fail(function() { jqxhr.fail(function() {
console.error('Error retrieving auth token'); log.error('Error retrieving auth token');
alertify.error('Error retrieving auth token. Please log in again')
}) })
localStorage.setItem('username', usernameInput.value);
} }
let loginForm = document.getElementById('loginForm'); let secondClick = false;
loginForm.addEventListener('submit', function(e) { $('#loginForm').on('submit', function(e) {
// e.preventDefault(); if(!secondClick) {
storeCredentials(); secondClick = true;
}) e.preventDefault();
storeCredentials();
}
// else {
// secondClick = false;
// }
})

View File

@ -20,6 +20,8 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/AlertifyJS/1.12.0/css/alertify.min.css" integrity="sha256-nhstgDCuZGQRk+wvwXZIPt278arHtuZKJ1YQ0rrXiL4=" crossorigin="anonymous" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/AlertifyJS/1.12.0/css/alertify.min.css" integrity="sha256-nhstgDCuZGQRk+wvwXZIPt278arHtuZKJ1YQ0rrXiL4=" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/AlertifyJS/1.12.0/css/themes/default.css" integrity="sha256-dawRQVhnqw8jRXaGnK0aj/NpOsPaQm+Em1sWN+fvegI=" crossorigin="anonymous" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/AlertifyJS/1.12.0/css/themes/default.css" integrity="sha256-dawRQVhnqw8jRXaGnK0aj/NpOsPaQm+Em1sWN+fvegI=" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/AlertifyJS/1.12.0/css/themes/bootstrap.css" integrity="sha256-1fgYpB3cyITZIur7E+Mj3R54NtlN9HwHykgKTJf0pmU=" crossorigin="anonymous" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/AlertifyJS/1.12.0/css/themes/bootstrap.css" integrity="sha256-1fgYpB3cyITZIur7E+Mj3R54NtlN9HwHykgKTJf0pmU=" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/fuse.js/3.4.5/fuse.min.js" integrity="sha256-Yrh3VGzE4d9b4KANknPJAhfcKt9SgHTL0v/FrJFoPzw=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/loglevel/1.6.4/loglevel.min.js" integrity="sha256-ACTlnmNCkOooSKkPCKYbiex8WLE82aeiN+Z9ElZag5Q=" crossorigin="anonymous"></script>
<!-- <script th:src="@{js/my_Crypto.js}" type="text/javascript"></script> --> <!-- <script th:src="@{js/my_Crypto.js}" type="text/javascript"></script> -->
@ -54,12 +56,16 @@
<div class="col-md-4 col-xl-3 chat"> <div class="col-md-4 col-xl-3 chat">
<div class="card mb-sm-3 mb-md-0 contacts_card"> <div class="card mb-sm-3 mb-md-0 contacts_card">
<div class="card-header"> <div class="card-header">
<div class="input-group"> <form action="#" id="user-search">
<input type="text" placeholder="Search..." name="" class="form-control search"> <div class="input-group">
<div class="input-group-prepend"> <input type="text" placeholder="Search..." id="user-search-term" class="form-control search">
<span class="input-group-text search_btn"><i class="fas fa-search"></i></span> <button class="search-cancel" id="user-search-cancel" hidden><i class="fas fa-times"></i></button>
<div class="input-group-prepend">
<button class="input-group-text search_btn"><i class="fas fa-search"></i></button>
</div>
</div> </div>
</div> </form>
</div> </div>
<div class="card-body contacts_body"> <div class="card-body contacts_body">
<ui class="contacts"> <ui class="contacts">
@ -76,7 +82,7 @@
</div> </div>
</li> </li>
</ui> </ui>
<ui class="contacts"> <ui class="contacts" id="contacts-box">
<th:block th:each="au: ${activeUsers}"> <th:block th:each="au: ${activeUsers}">
<li name="user-box" class="user-box"> <li name="user-box" class="user-box">
<div class="d-flex bd-highlight"> <div class="d-flex bd-highlight">
@ -89,7 +95,7 @@
<div th:switch="${au.online}"> <div th:switch="${au.online}">
<p th:case="true" th:text="${au.userName} + ' is online'">Khalid is online</p> <p th:case="true" th:text="${au.userName} + ' is online'">Khalid is online</p>
<th:block th:case="false"> <th:block th:case="false">
<th:block th:if="${au.lastActive == null}" > <th:block th:if="${au.lastActive == null}">
<p th:text="'User has not logged in yet'"></p> <p th:text="'User has not logged in yet'"></p>
</th:block> </th:block>
<th:block th:if="${au.lastActive != null}"> <th:block th:if="${au.lastActive != null}">
@ -106,7 +112,6 @@
<div style="color: rgba(255,255,255,0.7);">Hello how are you</div> <div style="color: rgba(255,255,255,0.7);">Hello how are you</div>
</div> </div>
</div> </div>
</li> </li>
</th:block> </th:block>
</ui> </ui>
@ -255,6 +260,42 @@
</div> </div>
</template> </template>
<template id="user-contact-online-template">
<li name="user-box" class="user-box">
<div class="d-flex bd-highlight">
<div class="img_cont">
<img src="https://static.turbosquid.com/Preview/001292/481/WV/_D.jpg" class="rounded-circle user_img">
<span class="online_icon"></span>
</div>
<div class="user_info">
<span class="to-user-span">{{userName}}</span>
<p>{{userName}} is online</p>
</div>
<div class="d-flex flex-column ml-auto">
<div class="text-right">Dec 25</div>
<div style="color: rgba(255,255,255,0.7);">Hello how are you</div>
</div>
</div>
</li>
</template>
<template id="user-contact-offline-template">
<li name="user-box" class="user-box">
<div class="d-flex bd-highlight">
<div class="img_cont">
<img src="https://static.turbosquid.com/Preview/001292/481/WV/_D.jpg" class="rounded-circle user_img">
</div>
<div class="user_info">
<span class="to-user-span">{{userName}}</span>
<p>Last active {{lastActive}}</p>
</div>
<div class="d-flex flex-column ml-auto">
<div class="text-right">Dec 25</div>
<div style="color: rgba(255,255,255,0.7);">Hello how are you</div>
</div>
</div>
</li>
</template>
</body> </body>
<script th:src="@{js/chat.js}" type="text/javascript"></script> <script th:src="@{js/chat.js}" type="text/javascript"></script>
<script src="../static/js/chatStatic.js" th:if="false"></script> <script src="../static/js/chatStatic.js" th:if="false"></script>

View File

@ -59,7 +59,7 @@
<div class="form-group"> <div class="form-group">
<label for="captcha">Enter this captcha: <label for="captcha">Enter this captcha:
<img th:src="@{'/img/' + ${userRegistrationDTO.captchaID}}" /> <img th:src="@{'/img/captcha/' + ${userRegistrationDTO.captchaID}}" />
</label> </label>
<input class="form-control" type="text" id="captcha" th:field="*{captchaInput}" required> <input class="form-control" type="text" id="captcha" th:field="*{captchaInput}" required>
</div> </div>