Added a lot of things

- Added "Add user to conversation"
-- Added a window to search for users to add
-- And made it all working
- Fixed the unread indicator
- Removed older TODOs
This commit is contained in:
Norbi Peti 2016-08-18 22:35:23 +02:00
parent 15470f9369
commit 1938a9f1db
13 changed files with 228 additions and 37 deletions

View file

@ -4,6 +4,8 @@ body {
#errormsg, #successmsg { #errormsg, #successmsg {
display: none; display: none;
box-shadow: 5px 5px 3px #888888;
z-index: 999;
} }
#errormsg { #errormsg {
@ -26,7 +28,7 @@ body {
color: #00ff00; color: #00ff00;
} }
#sidebar { #sidebarr {
float: right; float: right;
width: 20%; width: 20%;
} }
@ -64,18 +66,48 @@ html, body {
margin: 0; margin: 0;
} }
#conversations #sidebarl
{ {
width: 20%; width: 20%;
float: left; float: left;
} }
#conversation .chmessage
{ {
} }
#unreadmsg .unreadmsg
{ {
background-color: #DDD; background-color: #DDD;
} }
#hoverdialogcont
{
display: none;
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
#hoverdialogmid {
display: table-cell;
vertical-align: middle;
}
#hoverdialog
{
width: 30%;
background-color: #EEE;
margin-left: auto;
margin-right: auto;
box-shadow: 5px 5px 3px #888888;
}
.list
{
width: 100%;
}

View file

@ -13,23 +13,25 @@
<link rel="stylesheet" href="css/style.css" /> <link rel="stylesheet" href="css/style.css" />
<script src="js/index.js"></script> <script src="js/index.js"></script>
<script src="js/conversations.js"></script> <script src="js/conversations.js"></script>
<script src="js/users.js"></script>
</head> </head>
<body> <body>
<div id="errormsg"> <div id="errormsg">
</div> </div>
<div id="sidebarl">
<div id="conversations"> <div id="conversations">
<div id="addconv">
<a href="#" onclick="return addConversation();">Add conversation</a>
</div> </div>
</div> </div>
<div id="sidebar"> <div id="sidebarr">
<div id="userbox"> <div id="userbox">
<p>Logged in as <p>Logged in as
<username/> <username/>
</p> </p>
<a href="/logout">Logout</a> <a href="/logout">Logout</a>
</div> </div>
<div id="usersinconv">
</div>
</div> </div>
<div id="loginregisterbox"> <div id="loginregisterbox">
<div id="loginbox"> <div id="loginbox">
@ -97,4 +99,11 @@
<div id="channelmessages"></div> <div id="channelmessages"></div>
<textarea id="msginput" autofocus="autofocus"></textarea> <textarea id="msginput" autofocus="autofocus"></textarea>
</div> </div>
<div id="hoverdialogcont">
<div id="hoverdialogmid">
<div id="hoverdialog">
<p>Loading...</p>
</div>
</div>
</div>
</body> </body>

View file

@ -3,9 +3,34 @@ function addConversation() {
$.ajax({ $.ajax({
url: "/conversations", data: json, method: "POST", success: function (result) { url: "/conversations", data: json, method: "POST", success: function (result) {
document.getElementById("conversations").innerHTML += result; document.getElementById("conversations").innerHTML += result;
showAddUserToConv();
}, error: function (result) { }, error: function (result) {
showError(result.responseText); showError(result.responseText);
} }
}); });
return false; return false;
} }
function showAddUserToConv() {
var json = JSON.stringify({ "action": "adduserdialog" });
$.ajax({
url: "/conversations", data: json, method: "POST", success: function (result) {
document.getElementById("hoverdialog").innerHTML = result;
document.getElementById("hoverdialogcont").style.display = "table";
}, error: function (result) {
showError(result.responseText);
}
});
}
function addUserToConv() {
var liste = document.getElementById("searchuserlist");
var json = JSON.stringify({ "action": "adduser", "userid": liste.options[liste.selectedIndex].value });
$.ajax({
url: "/conversations", data: json, method: "POST", success: function (result) {
document.getElementById("hoverdialogcont").style.display = "none";
}, error: function (result) {
showError(result.responseText);
}
});
}

View file

@ -41,3 +41,4 @@ function changeConversation(convid) {
convidp.innerText = convid; convidp.innerText = convid;
conversationChanged(); conversationChanged();
} }

View file

@ -31,6 +31,8 @@ var updateUnreadCount = function () {
}; };
var addUnread = function addUnread() { var addUnread = function addUnread() {
if (shouldread || document.getElementById("msginput").disabled)
return;
unreadCount++; unreadCount++;
updateUnreadCount(); updateUnreadCount();
}; };
@ -54,9 +56,6 @@ function poll() {
handlereceivedmessage(msgelement); handlereceivedmessage(msgelement);
console.log("Can switch conversations now"); console.log("Can switch conversations now");
canswitchconversations = true; canswitchconversations = true;
if (justsentmsgread)
justsentmsgread = false;
else
addUnread(); addUnread();
}, error: function (data) { }, error: function (data) {
@ -85,8 +84,17 @@ function stopPoll() {
} }
var readTimer = null; var readTimer = null;
var shouldread = false;
$(document).ready(function () { $(document).ready(function () {
$('#msginput').on("focus", function () { readTimer == null ? readTimer = setTimeout(function () { resetUnread(); }, 3000) : readTimer; }); $('#msginput').on("focus", function () {
readTimer == null ? readTimer = setTimeout(function () {
resetUnread();
}, 3000) : readTimer;
shouldread = true;
});
$('#msginput').on("keydown", resetUnread); $('#msginput').on("keydown", resetUnread);
$('#msginput').on("blur", function () { readTimer != null ? clearTimeout(readTimer) : readTimer; }); $('#msginput').on("blur", function () {
readTimer != null ? clearTimeout(readTimer) : readTimer;
shouldread = false;
});
}); });

View file

@ -6,7 +6,6 @@ var sendmsg = function sendmsg(msginputta) {
}); });
}; };
var justsentmsgread = false;
var respfunc = function respfunc(result) { var respfunc = function respfunc(result) {
var msginput = document.getElementById("msginput"); var msginput = document.getElementById("msginput");
if (result != "Success") { //on success result is string if (result != "Success") { //on success result is string
@ -26,7 +25,6 @@ var respfunc = function respfunc(result) {
msginput.value = ""; msginput.value = "";
msginput.disabled = false; msginput.disabled = false;
msginput.focus(); msginput.focus();
justsentmsgread = true;
} }
}; };

10
pages/js/users.js Normal file
View file

@ -0,0 +1,10 @@
function userSearch() {
var json = JSON.stringify({ "action": "search", "searchstr": document.getElementById("searchtext").value });
$.ajax({
url: "/users", data: json, method: "POST", success: function (result) {
document.getElementById("searchuserlist").innerHTML = result;
}, error: function (result) {
showError(result.responseText);
}
});
}

View file

@ -55,7 +55,7 @@ public class Main {
* conversation.getUsers().add(loggedinuser); loggedinuser.getConversations().add(conversation); DataManager.save(user); DataManager.save(user2); DataManager.save(loggedinuser); * conversation.getUsers().add(loggedinuser); loggedinuser.getConversations().add(conversation); DataManager.save(user); DataManager.save(user2); DataManager.save(loggedinuser);
* DataManager.save(conversation); * DataManager.save(conversation);
*/ */
LogManager.getLogger().log(Level.INFO, "Starting webserver..."); // TODO: Separate IDs for conversations and users LogManager.getLogger().log(Level.INFO, "Starting webserver...");
HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLocalHost(), 8080), 10); HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLocalHost(), 8080), 10);
rf = new Reflections( rf = new Reflections(
new ConfigurationBuilder().setUrls(ClasspathHelper.forClassLoader(Page.class.getClassLoader())) new ConfigurationBuilder().setUrls(ClasspathHelper.forClassLoader(Page.class.getClassLoader()))
@ -75,16 +75,10 @@ public class Main {
} }
} }
server.start(); server.start();
/*
* LogManager.getLogger().info("Starting websocket server..."); Vertx vertx = Vertx.vertx(); io.vertx.core.http.HttpServer socketserver = vertx.createHttpServer();
* socketserver.websocketHandler(websocket -> { websocket.writeFinalTextFrame("Hello"); // TODO }); socketserver.listen(8180);
*/
LogManager.getLogger().log(Level.INFO, "Ready... Press Enter to stop."); LogManager.getLogger().log(Level.INFO, "Ready... Press Enter to stop.");
System.in.read(); System.in.read();
LogManager.getLogger().log(Level.INFO, "Stopping..."); LogManager.getLogger().log(Level.INFO, "Stopping...");
server.stop(1); server.stop(1);
// socketserver.close();
// vertx.close();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View file

@ -6,6 +6,8 @@ import java.util.UUID;
import javax.persistence.*; import javax.persistence.*;
import org.jsoup.nodes.Element;
import io.github.norbipeti.chat.server.data.LoaderCollection; import io.github.norbipeti.chat.server.data.LoaderCollection;
import io.github.norbipeti.chat.server.data.LoaderRef; import io.github.norbipeti.chat.server.data.LoaderRef;

View file

@ -3,10 +3,12 @@ package io.github.norbipeti.chat.server.page;
import java.io.IOException; import java.io.IOException;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpExchange;
import io.github.norbipeti.chat.server.data.DataManager;
import io.github.norbipeti.chat.server.db.domain.Conversation; import io.github.norbipeti.chat.server.db.domain.Conversation;
import io.github.norbipeti.chat.server.db.domain.ManagedData; import io.github.norbipeti.chat.server.db.domain.ManagedData;
import io.github.norbipeti.chat.server.db.domain.User; import io.github.norbipeti.chat.server.db.domain.User;
@ -39,13 +41,55 @@ public class ConversationsAjaxPage extends Page {
switch (post.get("action").getAsString()) { switch (post.get("action").getAsString()) {
case "add": { case "add": {
Conversation conv = ManagedData.create(Conversation.class); Conversation conv = ManagedData.create(Conversation.class);
conv.getUsers().add(user); // TODO: Option to invite people conv.getUsers().add(user);
user.getConversations().add(conv); user.getConversations().add(conv);
Document doc = new Document(""); Document doc = new Document("");
conv.getAsHtml(doc); conv.getAsHtml(doc);
IOHelper.SendResponse(200, doc.toString(), exchange); IOHelper.SendResponse(200, doc.toString(), exchange);
break; break;
} }
case "adduserdialog": {
Document doc = new Document("");
Element form = doc.appendElement("form");
form.attr("method", "POST");
form.appendElement("h3").text("Add user to conversation");
form.appendElement("input").attr("type", "text").attr("id", "searchtext");
form.appendElement("input").attr("type", "button").attr("value", "Search").attr("onclick", "userSearch()");
form.appendElement("br");
form.appendElement("select").addClass("list").attr("id", "searchuserlist").attr("size", "10");
form.appendElement("br");
form.appendElement("input").attr("type", "button").attr("value", "Add user").attr("onclick",
"addUserToConv()");
form.appendElement("input").attr("type", "button").attr("value", "Close").attr("onclick",
"document.getElementById(\"hoverdialogcont\").style.display = \"none\";");
IOHelper.SendResponse(200, doc.toString(), exchange);
break;
}
case "adduser": {
if (user.getCurrentConversation() == null) {
IOHelper.SendResponse(200, "<p>Not in a conversation!</p>", exchange);
return;
}
if (!post.has("userid")) {
IOHelper.SendResponse(200, "<p>User ID not found: " + post + "</p>", exchange);
return;
}
long userid = post.get("userid").getAsLong();
User adduser = DataManager.load(User.class, userid, false);
if (adduser == null) {
IOHelper.SendResponse(200, "<p>User not found: " + userid + "</p>", exchange);
return;
}
Conversation currentconversation = user.getCurrentConversation().get();
if (currentconversation.getUsers().contains(userid)) {
IOHelper.SendResponse(200, "<p>The user is already in the conversation</p>", exchange);
return;
}
currentconversation.getUsers().add(adduser);
adduser.getConversations().add(currentconversation);
IOHelper.SendResponse(200, doc -> currentconversation.getAsHtml(doc).ownerDocument(), exchange);
break;
}
default: { default: {
IOHelper.SendResponse(400, IOHelper.SendResponse(400,
"<h1>400 Bad request</h1><p>Unknown action: " + post.get("action").getAsString() + "</p>", "<h1>400 Bad request</h1><p>Unknown action: " + post.get("action").getAsString() + "</p>",
@ -54,5 +98,4 @@ public class ConversationsAjaxPage extends Page {
} }
} }
} }
} }

View file

@ -46,6 +46,12 @@ public class IndexPage extends Page {
message.getAsHTML(channelmessages); message.getAsHTML(channelmessages);
} }
} }
for (int i = 0; i < conv.getUsers().size(); i++)
doc.getElementById("usersinconv").appendElement("div").attr("id", "convuser" + i)
.addClass("convuser").appendElement("p").text(conv.getUsers().get(i).getName());
doc.getElementById("sidebarr").appendElement("div").attr("id", "addconvuser").appendElement("a")
.text("Add user to conversation").attr("href", "javascript:showAddUserToConv()");
// TODO: Update users and conversations automatically on conv change
} }
cide.attr("style", "display: none"); cide.attr("style", "display: none");
cide.attr("id", "convidp"); cide.attr("id", "convidp");
@ -53,17 +59,12 @@ public class IndexPage extends Page {
Element conversations = doc.getElementById("conversations"); Element conversations = doc.getElementById("conversations");
for (Conversation conv : user.getConversations()) for (Conversation conv : user.getConversations())
conv.getAsHtml(conversations); conv.getAsHtml(conversations);
conversations.appendElement("div").attr("id", "addconv").appendElement("a").attr("href", "#")
.attr("onclick", "return addConversation();").text("Add conversation");
return doc; return doc;
}, exchange); }, exchange);
} // TODO: } // TODO: Validation at registration (no special chars, etc.)
// Validation
// at
// registration
// (no
// special
// chars,
// etc.)
@Override @Override
public String GetName() { public String GetName() {

View file

@ -41,7 +41,7 @@ public abstract class Page implements HttpHandler {
str.print("</pre>"); str.print("</pre>");
IOHelper.SendResponse(500, baos.toString(StandardCharsets.ISO_8859_1), exchange); IOHelper.SendResponse(500, baos.toString(StandardCharsets.ISO_8859_1), exchange);
} catch (Exception e1) { } catch (Exception e1) {
e1.printStackTrace(); // TODO: Message listener JS e1.printStackTrace();
} }
} }
} }

View file

@ -0,0 +1,68 @@
package io.github.norbipeti.chat.server.page;
import java.io.IOException;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import com.google.gson.JsonObject;
import com.sun.net.httpserver.HttpExchange;
import io.github.norbipeti.chat.server.data.DataManager;
import io.github.norbipeti.chat.server.db.domain.Conversation;
import io.github.norbipeti.chat.server.db.domain.ManagedData;
import io.github.norbipeti.chat.server.db.domain.User;
import io.github.norbipeti.chat.server.io.IOHelper;
public class UsersAjaxPage extends Page {
@Override
public String GetName() {
return "users";
}
@Override
public void handlePage(HttpExchange exchange) throws IOException {
JsonObject post = IOHelper.GetPOSTJSON(exchange);
User user = IOHelper.GetLoggedInUser(exchange);
if (user == null) {
IOHelper.SendResponse(403, "<h1>403 Login required</h1>", exchange);
return;
}
if (post == null) {
IOHelper.SendResponse(400,
"<h1>400 Bad request</h1><p>Not a JSON string: " + IOHelper.GetPOST(exchange) + "</p>", exchange);
return;
}
if (!post.has("action")) {
IOHelper.SendResponse(400, "<h1>400 Bad request</h1><p>Action missing: " + post + "</p>", exchange);
return;
}
switch (post.get("action").getAsString()) {
case "search": {
if (!post.has("searchstr")) {
IOHelper.SendResponse(400, "<h1>400 Bad request</h1><p>Search string missing: " + post + "</p>",
exchange);
return;
}
String searchstr = post.get("searchstr").getAsString().toLowerCase();
Document doc = new Document("");
if (searchstr.length() != 0)
for (User suser : DataManager.getAll(User.class))
if (suser.getEmail().toLowerCase().contains(searchstr)
|| suser.getName().toLowerCase().contains(searchstr))
doc.appendElement("option").addClass("resuser").attr("value", suser.getId() + "")
.text(suser.getName());
IOHelper.SendResponse(200, doc.toString(), exchange);
break;
}
default: {
IOHelper.SendResponse(400,
"<h1>400 Bad request</h1><p>Unknown action: " + post.get("action").getAsString() + "</p>",
exchange);
break;
}
}
}
}