fixed some backend bugs. Finished /list-rooms. Now we have these cool popup windows before serious actions
This commit is contained in:
parent
21a23be96e
commit
9283590122
@ -65,8 +65,9 @@ x
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script src="/assets/js/common.js"></script>
|
||||||
<script src="/assets/js/common-popup.js"></script>
|
<script src="/assets/js/common-popup.js"></script>
|
||||||
<script src="/assets/js/list-rooms.js"></script>
|
<script src="/assets/js/list-rooms.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
{% ENDELDEF %}
|
{% ENDELDEF %}
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#CL-bacbe {
|
#CL-bacbe {
|
||||||
margin: 6px;
|
margin-top: 6px;
|
||||||
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CL-my-chat-box {
|
.CL-my-chat-box {
|
||||||
|
@ -28,9 +28,6 @@ let members = new Map();
|
|||||||
for (let memberSt of initial_chatUpdResp.members){
|
for (let memberSt of initial_chatUpdResp.members){
|
||||||
members.set(memberSt.id, memberSt);
|
members.set(memberSt.id, memberSt);
|
||||||
}
|
}
|
||||||
// members.set(1, {id: 1, name: 'grisha', nickname: 'gri', role: 'admin'});
|
|
||||||
// members.set(2, {id: 2, name: 'Pavlov Vladimir', nickname: 'pv', role: 'regular'});
|
|
||||||
// members.set(3, {id: 3, name: 'Ivan', nickname: 'ivan', role: 'read-only'});
|
|
||||||
|
|
||||||
function updateOffsetOfVisibleMsg(msgId, offset){
|
function updateOffsetOfVisibleMsg(msgId, offset){
|
||||||
visibleMessages.get(msgId).style.bottom = String(offset) + "px";
|
visibleMessages.get(msgId).style.bottom = String(offset) + "px";
|
||||||
@ -180,13 +177,10 @@ function test(id, uid){
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mainloopTimeout = null;
|
let mainloopTimeout = null;
|
||||||
|
|
||||||
let mainloopPoller = null;
|
let mainloopPoller = null;
|
||||||
|
|
||||||
function setMainloopTimeout(){
|
function setMainloopTimeout(){
|
||||||
mainloopTimeout = setTimeout(mainloopPoller, 1000);
|
mainloopTimeout = setTimeout(mainloopPoller, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
mainloopPoller = function(){
|
mainloopPoller = function(){
|
||||||
try {
|
try {
|
||||||
console.log("Hello, World!");
|
console.log("Hello, World!");
|
||||||
|
52
assets/js/common.js
Normal file
52
assets/js/common.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
async function apiRequest(type, req){
|
||||||
|
let A = await fetch("/api/" + type,
|
||||||
|
{method: 'POST', body: JSON.stringify(req)});
|
||||||
|
let B = await A.json();
|
||||||
|
if (B.status !== 0)
|
||||||
|
throw Error("Server returned non-zero status");
|
||||||
|
return B;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Framework for pages with mainloop (it can be npt only polling, but also literally anything else */
|
||||||
|
let __mainloopDelayMs = 3000;
|
||||||
|
let mainloopTimeout = null;
|
||||||
|
let mainloopPoller = null;
|
||||||
|
let __guestMainloopPollerAction = null;
|
||||||
|
function setMainloopTimeout(){
|
||||||
|
mainloopTimeout = setTimeout(mainloopPoller, __mainloopDelayMs);
|
||||||
|
}
|
||||||
|
function cancelMainloopTimeout(){
|
||||||
|
clearTimeout(mainloopTimeout);
|
||||||
|
}
|
||||||
|
mainloopPoller = function(){
|
||||||
|
try {
|
||||||
|
console.log("Hello, World!");
|
||||||
|
__guestMainloopPollerAction();
|
||||||
|
} catch (error){
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
setMainloopTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1
|
||||||
|
const userChatRoleAdmin = "admin";
|
||||||
|
// 2
|
||||||
|
const userChatRoleRegular = "regular";
|
||||||
|
// 3
|
||||||
|
const userChatRoleReadOnly = "read-only";
|
||||||
|
// 4
|
||||||
|
const userChatRoleDeleted = "not-a-member";
|
||||||
|
|
||||||
|
function roleToColor(role) {
|
||||||
|
if (role === userChatRoleAdmin) {
|
||||||
|
return "#aafff3";
|
||||||
|
} else if (role === userChatRoleRegular){
|
||||||
|
return "#ffffff";
|
||||||
|
|
||||||
|
} else if (role === userChatRoleReadOnly){
|
||||||
|
return "#bfb2b2";
|
||||||
|
} else if (role === userChatRoleDeleted) {
|
||||||
|
return "#fb4a4a";
|
||||||
|
}
|
||||||
|
return "#286500" // Bug
|
||||||
|
}
|
@ -1,12 +1,35 @@
|
|||||||
let LocalHistoryId = 0;
|
let LocalHistoryId = 0;
|
||||||
|
|
||||||
|
function genSentBase(){
|
||||||
|
return {
|
||||||
|
'chatListUpdReq': {
|
||||||
|
'LocalHistoryId': LocalHistoryId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let myChats = new Map();
|
let myChats = new Map();
|
||||||
let chatBoxes = new Map();
|
let chatBoxes = new Map();
|
||||||
|
|
||||||
const roleDeleted = "not-a-member";
|
/* Generate text that is displayed on the right side of chat intro box */
|
||||||
|
function youAreXHere(myRoleHere){
|
||||||
|
return "You are " + myRoleHere + " here";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let chatRenunciationWinStoredId = -1;
|
||||||
|
|
||||||
|
/* Updating chat html box after myMembershipSt in it was updated */
|
||||||
|
function updateBoxWithNewSt(box, myMembershipSt){
|
||||||
|
let ID = myMembershipSt.chatId;
|
||||||
|
let roleP = box.querySelector(".CL-my-chat-box-my-role");
|
||||||
|
roleP.innerText = youAreXHere(myMembershipSt.myRoleHere);
|
||||||
|
box.style.backgroundColor = roleToColor(myMembershipSt.myRoleHere);
|
||||||
|
}
|
||||||
|
|
||||||
function convertStToBox(myMembershipSt){
|
function convertStToBox(myMembershipSt){
|
||||||
let chatURI = "/user/" + myMembershipSt.chatNickname;
|
let chatURI = "/user/" + myMembershipSt.chatNickname;
|
||||||
|
let ID = myMembershipSt.chatId;
|
||||||
|
|
||||||
let box = document.createElement("div");
|
let box = document.createElement("div");
|
||||||
chatBoxes.set(myMembershipSt.chatId, box);
|
chatBoxes.set(myMembershipSt.chatId, box);
|
||||||
@ -15,10 +38,9 @@ function convertStToBox(myMembershipSt){
|
|||||||
let inBoxNickname = document.createElement("a");
|
let inBoxNickname = document.createElement("a");
|
||||||
box.appendChild(inBoxNickname);
|
box.appendChild(inBoxNickname);
|
||||||
inBoxNickname.className = "entity-nickname-txt CL-my-chat-box-nickname";
|
inBoxNickname.className = "entity-nickname-txt CL-my-chat-box-nickname";
|
||||||
console.log(myMembershipSt);
|
|
||||||
console.log(myMembershipSt.chatNickname);
|
|
||||||
inBoxNickname.innerText = myMembershipSt.chatNickname;
|
inBoxNickname.innerText = myMembershipSt.chatNickname;
|
||||||
inBoxNickname.href = chatURI;
|
inBoxNickname.href = chatURI;
|
||||||
|
box.style.backgroundColor = roleToColor(myMembershipSt.myRoleHere);
|
||||||
|
|
||||||
let inBoxName = document.createElement("a");
|
let inBoxName = document.createElement("a");
|
||||||
box.appendChild(inBoxName);
|
box.appendChild(inBoxName);
|
||||||
@ -29,9 +51,7 @@ function convertStToBox(myMembershipSt){
|
|||||||
let inBoxMyRoleHere = document.createElement("p");
|
let inBoxMyRoleHere = document.createElement("p");
|
||||||
box.appendChild(inBoxMyRoleHere);
|
box.appendChild(inBoxMyRoleHere);
|
||||||
inBoxMyRoleHere.className = "entity-reg-field-txt CL-my-chat-box-my-role";
|
inBoxMyRoleHere.className = "entity-reg-field-txt CL-my-chat-box-my-role";
|
||||||
inBoxMyRoleHere.innerText = "You are " + myMembershipSt.myRoleHere + " here";
|
inBoxMyRoleHere.innerText = youAreXHere(myMembershipSt.myRoleHere);
|
||||||
|
|
||||||
let ID = myMembershipSt.chatId;
|
|
||||||
|
|
||||||
let inBoxLeaveBtn = document.createElement("img");
|
let inBoxLeaveBtn = document.createElement("img");
|
||||||
box.appendChild(inBoxLeaveBtn);
|
box.appendChild(inBoxLeaveBtn);
|
||||||
@ -40,19 +60,62 @@ function convertStToBox(myMembershipSt){
|
|||||||
inBoxLeaveBtn.onclick = function (ev) {
|
inBoxLeaveBtn.onclick = function (ev) {
|
||||||
if (ev.button !== 0)
|
if (ev.button !== 0)
|
||||||
return;
|
return;
|
||||||
console.log("Tried to leave chat" + ID);
|
chatRenunciationWinStoredId = ID;
|
||||||
activatePopupWindowById("chat-renunciation-win");
|
activatePopupWindowById("chat-renunciation-win");
|
||||||
|
document.getElementById("chat-renunciation-win-title").innerText =
|
||||||
|
"Do you really want to leave chat " + myMembershipSt.chatNickname + "?";
|
||||||
};
|
};
|
||||||
|
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateLocalStateFromChatListUpdResp(chatListUpdResp){
|
||||||
|
LocalHistoryId = chatListUpdResp.HistoryId;
|
||||||
|
|
||||||
|
let literalChatList = document.getElementById("CL-dblec");
|
||||||
|
|
||||||
|
for (let myMembershipSt of chatListUpdResp.myChats){
|
||||||
|
let chatId = myMembershipSt.chatId;
|
||||||
|
console.log(myMembershipSt);
|
||||||
|
if (myChats.has(chatId)){
|
||||||
|
myChats.set(chatId, myMembershipSt);
|
||||||
|
updateBoxWithNewSt(chatBoxes.get(chatId), myMembershipSt);
|
||||||
|
} else {
|
||||||
|
if (myMembershipSt.myRoleHere === userChatRoleDeleted)
|
||||||
|
continue;
|
||||||
|
myChats.set(chatId, myMembershipSt);
|
||||||
|
let box = convertStToBox(myMembershipSt)
|
||||||
|
chatBoxes.set(chatId, box);
|
||||||
|
literalChatList.appendChild(box);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use it ONLY if `Recv` reported success */
|
||||||
|
function updateLocalStateFromRecv(Recv){
|
||||||
|
updateLocalStateFromChatListUpdResp(Recv.chatListUpdResp);
|
||||||
|
}
|
||||||
|
|
||||||
function configureChatCreationInterface(){
|
function configureChatCreationInterface(){
|
||||||
document.getElementById("chat-creation-win-yes").onclick = function (ev) {
|
document.getElementById("chat-creation-win-yes").onclick = function (ev) {
|
||||||
if (ev.button !== 0)
|
if (ev.button !== 0)
|
||||||
return;
|
return;
|
||||||
|
let chatNicknameInput = document.getElementById("chat-nickname-input");
|
||||||
|
let chatNameInput = document.getElementById("chat-name-input");
|
||||||
|
let nickname = chatNicknameInput.value;
|
||||||
|
let name = chatNameInput.value;
|
||||||
deactivateActivePopup();
|
deactivateActivePopup();
|
||||||
// todo: create chat, send request
|
let Sent = genSentBase();
|
||||||
|
Sent.content = {};
|
||||||
|
Sent.content.nickname = nickname;
|
||||||
|
Sent.content.name = name;
|
||||||
|
apiRequest("createChat", Sent
|
||||||
|
).then((Recv) => {
|
||||||
|
updateLocalStateFromRecv(Recv);
|
||||||
|
}).catch((e) => {
|
||||||
|
alert("Failed to create chat");
|
||||||
|
console.log(e);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
document.getElementById("chat-creation-win-no").onclick = function (ev) {
|
document.getElementById("chat-creation-win-no").onclick = function (ev) {
|
||||||
@ -64,6 +127,10 @@ function configureChatCreationInterface(){
|
|||||||
document.getElementById("CL-bacbe").onclick = function (ev){
|
document.getElementById("CL-bacbe").onclick = function (ev){
|
||||||
if (ev.button !== 0)
|
if (ev.button !== 0)
|
||||||
return;
|
return;
|
||||||
|
let chatNicknameInput = document.getElementById("chat-nickname-input");
|
||||||
|
let chatNameInput = document.getElementById("chat-name-input");
|
||||||
|
chatNicknameInput.value = "";
|
||||||
|
chatNameInput.value = "";
|
||||||
activatePopupWindowById("chat-creation-win");
|
activatePopupWindowById("chat-creation-win");
|
||||||
console.log("Tried to show chat creation window");
|
console.log("Tried to show chat creation window");
|
||||||
};
|
};
|
||||||
@ -74,7 +141,18 @@ function configureChatRenunciationInterfaceWinPart(){
|
|||||||
if (ev.button !== 0)
|
if (ev.button !== 0)
|
||||||
return;
|
return;
|
||||||
deactivateActivePopup();
|
deactivateActivePopup();
|
||||||
// todo: actually leave chat
|
if (chatRenunciationWinStoredId < 0)
|
||||||
|
throw new Error("chatRenunciationWinStoredId < 0");
|
||||||
|
let chatId = chatRenunciationWinStoredId;
|
||||||
|
let Sent = genSentBase();
|
||||||
|
Sent.chatId = chatId;
|
||||||
|
apiRequest("leaveChat", Sent
|
||||||
|
).then((Recv) => {
|
||||||
|
updateLocalStateFromRecv(Recv);
|
||||||
|
}).catch((e) => {
|
||||||
|
alert("Failed to leave chat");
|
||||||
|
console.log(e);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("chat-renunciation-win-no").onclick = function(ev) {
|
document.getElementById("chat-renunciation-win-no").onclick = function(ev) {
|
||||||
@ -84,24 +162,21 @@ function configureChatRenunciationInterfaceWinPart(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__mainloopDelayMs = 3000;
|
||||||
|
__guestMainloopPollerAction = function(){
|
||||||
|
let Sent = genSentBase();
|
||||||
|
apiRequest("chatListPollEvents", Sent
|
||||||
|
).then((Recv) => {
|
||||||
|
console.log("Got a response");
|
||||||
|
console.log(Recv);
|
||||||
|
updateLocalStateFromRecv(Recv);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
window.onload = function () {
|
window.onload = function () {
|
||||||
console.log("Loading complete");
|
console.log("Loading complete");
|
||||||
LocalHistoryId = initial_chatListUpdResp.HistoryId;
|
updateLocalStateFromChatListUpdResp(initial_chatListUpdResp);
|
||||||
|
|
||||||
console.log(initial_chatListUpdResp);
|
|
||||||
|
|
||||||
let literalChatList = document.getElementById("CL-dblec");
|
|
||||||
|
|
||||||
for (let myMembershipSt of initial_chatListUpdResp.myChats){
|
|
||||||
console.log(myMembershipSt);
|
|
||||||
if (myMembershipSt.myRoleHere !== roleDeleted){
|
|
||||||
myChats.set(myMembershipSt.chatId, myMembershipSt);
|
|
||||||
let box = convertStToBox(myMembershipSt)
|
|
||||||
chatBoxes.set(myMembershipSt.chatId, box);
|
|
||||||
literalChatList.appendChild(box);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configureChatCreationInterface();
|
configureChatCreationInterface();
|
||||||
configureChatRenunciationInterfaceWinPart();
|
configureChatRenunciationInterfaceWinPart();
|
||||||
|
mainloopPoller();
|
||||||
};
|
};
|
||||||
|
@ -10,10 +10,13 @@ namespace iu9cawebchat {
|
|||||||
return json::JSON(json::jdict{{"status", json::JSON(-1l)}});
|
return json::JSON(json::jdict{{"status", json::JSON(-1l)}});
|
||||||
if (is_nickname_taken(conn, new_chat_nickname))
|
if (is_nickname_taken(conn, new_chat_nickname))
|
||||||
return json::JSON(json::jdict{{"status", json::JSON(-2l)}});
|
return json::JSON(json::jdict{{"status", json::JSON(-2l)}});
|
||||||
|
if (is_nickname_taken(conn, new_chat_nickname))
|
||||||
|
return json::JSON(json::jdict{{"status", json::JSON(-3l)}});
|
||||||
reserve_nickname(conn, new_chat_nickname);
|
reserve_nickname(conn, new_chat_nickname);
|
||||||
|
|
||||||
sqlite_nooutput(conn,
|
sqlite_nooutput(conn,
|
||||||
"INSERT INTO `chat` (`nickname`, `name`, `it_HistoryId`, `lastMsgId`) VALUES (?1, ?2, 0, -1)");
|
"INSERT INTO `chat` (`nickname`, `name`, `it_HistoryId`, `lastMsgId`) VALUES (?1, ?2, 0, -1)",
|
||||||
|
{}, {{1, new_chat_nickname}, {2, new_chat_name}});
|
||||||
|
|
||||||
int64_t CHAT_ID = sqlite_trsess_last_insert_rowid(conn);
|
int64_t CHAT_ID = sqlite_trsess_last_insert_rowid(conn);
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
namespace iu9cawebchat {
|
namespace iu9cawebchat {
|
||||||
json::JSON poll_update_chat_list_resp(SqliteConnection& conn, int64_t userId, int64_t LocalHistoryId) {
|
json::JSON poll_update_chat_list_resp(SqliteConnection& conn, int64_t userId, int64_t LocalHistoryId) {
|
||||||
|
printf("Userid: %ld\n", userId);
|
||||||
json::JSON chatListUpdResp;
|
json::JSON chatListUpdResp;
|
||||||
SqliteStatement my_membership_changes(conn,
|
SqliteStatement my_membership_changes(conn,
|
||||||
"SELECT `chatId`, `role` FROM `user_chat_membership` WHERE `userId` = ?1 "
|
"SELECT `chatId`, `role` FROM `user_chat_membership` WHERE `userId` = ?1 "
|
||||||
@ -32,7 +33,8 @@ namespace iu9cawebchat {
|
|||||||
void poll_update_chat_list(SqliteConnection& conn, int64_t userId, const json::JSON& Sent, json::JSON& Recv) {
|
void poll_update_chat_list(SqliteConnection& conn, int64_t userId, const json::JSON& Sent, json::JSON& Recv) {
|
||||||
Recv["status"].asInteger() = json::Integer(0l);
|
Recv["status"].asInteger() = json::Integer(0l);
|
||||||
// todo: in libjsonincpp: get rid of Integer
|
// todo: in libjsonincpp: get rid of Integer
|
||||||
poll_update_chat_list_resp(conn, userId, Sent["chatListUpdReq"]["LocalHistoryId"].asInteger().get_int());
|
printf("%s\n", json::generate_str(Sent, json::print_pretty).c_str());
|
||||||
|
Recv["chatListUpdResp"] = poll_update_chat_list_resp(conn, userId, Sent["chatListUpdReq"]["LocalHistoryId"].asInteger().get_int());
|
||||||
}
|
}
|
||||||
|
|
||||||
json::JSON make_messageSt_obj(int64_t id, int64_t senderUserId, bool exists, bool isSystem, const std::string& text) {
|
json::JSON make_messageSt_obj(int64_t id, int64_t senderUserId, bool exists, bool isSystem, const std::string& text) {
|
||||||
@ -158,6 +160,7 @@ namespace iu9cawebchat {
|
|||||||
json::JSON internalapi_chatListPollEvents(SqliteConnection& conn, int64_t uid, const json::JSON& Sent) {
|
json::JSON internalapi_chatListPollEvents(SqliteConnection& conn, int64_t uid, const json::JSON& Sent) {
|
||||||
json::JSON Recv;
|
json::JSON Recv;
|
||||||
poll_update_chat_list(conn, uid, Sent, Recv);
|
poll_update_chat_list(conn, uid, Sent, Recv);
|
||||||
|
printf("%s\n", json::generate_str(Recv, json::print_pretty).c_str());
|
||||||
return Recv;
|
return Recv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,6 @@ namespace iu9cawebchat {
|
|||||||
/* All the api calls processing is done in dedicated files.
|
/* All the api calls processing is done in dedicated files.
|
||||||
* All functions related to polling are defined in api_pollevents.cpp */
|
* All functions related to polling are defined in api_pollevents.cpp */
|
||||||
|
|
||||||
// todo: move everything to dedicated files
|
|
||||||
int64_t get_current_history_id_of_chat(SqliteConnection& conn, int64_t chatId) {
|
int64_t get_current_history_id_of_chat(SqliteConnection& conn, int64_t chatId) {
|
||||||
SqliteStatement req(conn, "SELECT `it_HistoryId` FROM `chat` WHERE `id` = ?1", {{1, chatId}}, {});
|
SqliteStatement req(conn, "SELECT `it_HistoryId` FROM `chat` WHERE `id` = ?1", {{1, chatId}}, {});
|
||||||
fsql_integer_or_null HistoryId;
|
fsql_integer_or_null HistoryId;
|
||||||
|
@ -36,8 +36,7 @@ int main(int argc, char** argv){
|
|||||||
iu9cawebchat::run_website(config);
|
iu9cawebchat::run_website(config);
|
||||||
} else
|
} else
|
||||||
een9_THROW("unknown action (known are 'run', 'initialize')");
|
een9_THROW("unknown action (known are 'run', 'initialize')");
|
||||||
// todo: put back execption after debug
|
} catch (std::exception& e) {
|
||||||
} catch (std::bad_weak_ptr& e) {
|
|
||||||
printf("System failure\n%s\n", e.what());
|
printf("System failure\n%s\n", e.what());
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user