Fixed some bugs in nytl, een9 ad chat, wrote a skeleton for list-rooms, chat pages, finished login, view-profile, edit-profile-pages. chat-members page still needs attention
This commit is contained in:
parent
c009b848b5
commit
07711a93b0
@ -5,25 +5,12 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Веб-Чат Members</title>
|
||||
<link rel="stylesheet" href="/assets/css/chat.css">
|
||||
</head>
|
||||
<body>
|
||||
{% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %}
|
||||
<!--TODO: ADD SOMETHING WRITE SOMETHING AAAAAA -->
|
||||
<div class="overlay" id="overlay">
|
||||
<div class="members-list" id="members-list">
|
||||
<div class="members-list-header">
|
||||
<span class="close" onclick="closeMembersList()">×</span>
|
||||
<h2 class="all-members">Все участники</h2>
|
||||
</div>
|
||||
<div class="members-list-body">
|
||||
<ul id="members-list-body">
|
||||
<!-- Список участников будет добавлен динамически -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/assets/js/chat-members.js"></script>
|
||||
<h1> Chat member list page for {% WRITE openedchat.nickname%}, not ready yet</h1>
|
||||
<!--<script src="/assets/js/chat-members.js"></script>-->
|
||||
</body>
|
||||
</html>
|
||||
{% ENDELDEF %}
|
||||
|
@ -9,17 +9,36 @@
|
||||
|
||||
{% ELDEF main JSON pres JSON userinfo JSON openedchat JSON initial_chatUpdResp %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Веб-Чат</title>
|
||||
<link rel="stylesheet" href="/assets/css/common.css">
|
||||
<link rel="stylesheet" href="/assets/css/chat.css">
|
||||
<title>Chat </title>
|
||||
</head>
|
||||
<body>
|
||||
{% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %}
|
||||
<!-- TODO AAAAA-->
|
||||
<script src="/assets/js/chat.js"></script>
|
||||
<!-- Write the actual chat script -->
|
||||
<!--% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %-->
|
||||
<div id="fullscreen-container">
|
||||
<div class="panel" id="navigation-info-panel">
|
||||
<a href="/list-rooms" id="go-to-chat-list" class="panel-thing">
|
||||
<img alt="Go to list of chats" src="/assets/img/list-rooms.svg" width="32px">
|
||||
</a>
|
||||
<a href="/user/{% WRITE userinfo.nickname %}" id="go-to-my-profile" class="panel-thing">
|
||||
<img alt="Go to my profile" src="/assets/img/user.svg" width="32px">
|
||||
</a>
|
||||
<p class="panel-thing panel-header-txt"> {% WRITE openedchat.name %} ({% WRITE openedchat.nickname %})</p>
|
||||
<a href="/chat-members/{% WRITE openedchat.nickname %}" id="go-to-chat-settings" class="panel-thing">
|
||||
<img alt="Settings of chat. List of members" src="/assets/img/settings-iron.svg" width="32px">
|
||||
</a>
|
||||
</div>
|
||||
<div id="chat-widget"></div>
|
||||
<div class="panel" id="input-panel">
|
||||
<div contentEditable id="message-input" class="panel-thing"></div>
|
||||
</div>
|
||||
<script src="/assets/js/chat.js"></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{% ENDELDEF %}
|
||||
|
@ -1,42 +1,68 @@
|
||||
{% ELDEF main JSON pres JSON userprofile JSON errors %}
|
||||
{% ELDEF main JSON pres JSON userinfo JSON alienprofile JSON errors %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="/assets/css/profile.css">
|
||||
<title>Профиль</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/css/common.css">
|
||||
<link rel="stylesheet" href="/assets/css/edit-profile.css">
|
||||
<title>Edit user Profile</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-container">
|
||||
|
||||
<div id="document-container">
|
||||
<div id="navigation-panel" class="panel">
|
||||
<a href="/list-rooms" id="go-to-chat-list" class="panel-thing">
|
||||
<img alt="Go to list of chats" src="/assets/img/list-rooms.svg" width="32px">
|
||||
</a>
|
||||
<a href="/user/{% WRITE userinfo.nickname %}" id="go-to-my-profile" class="panel-thing">
|
||||
<img alt="Go to my profile" src="/assets/img/user.svg" width="32px">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% FOR error IN errors %}
|
||||
<div>
|
||||
<p>{% WRITE error.text %}</p>
|
||||
<div class="server-notif-error-msg-box">
|
||||
{% WRITE error.text %}
|
||||
</div>
|
||||
{% ENDFOR %}
|
||||
<div class="profile-header">
|
||||
<h1>Редактирование профиля</h1>
|
||||
|
||||
<div class="profile-container">
|
||||
<h2 class="profile-name-text">{% WRITE alienprofile.name %}</h2>
|
||||
<h3 class="profile-nickname-text">Nickname: {% WRITE alienprofile.nickname %}</h3>
|
||||
<p class="profile-bio-text">
|
||||
{% WRITE alienprofile.bio %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="profile-container">
|
||||
<h1 class="wide-centered-header">Change user attributes</h1>
|
||||
<form action = "/user/{% WRITE alienprofile.nickname %}" method="post" enctype="application/x-www-form-urlencoded">
|
||||
<table class="logins-input-table">
|
||||
<tr>
|
||||
<td class="logins-input-td1">
|
||||
<label for="new-name-input">Enter new name:</label>
|
||||
</td>
|
||||
<td class="logins-input-td2">
|
||||
<input name="name" id="new-name-input" type="text" placeholder="New name" class="one-line-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="logins-input-td1">
|
||||
<label for="new-password-input">Enter new password: </label>
|
||||
</td>
|
||||
<td class="logins-input-td2">
|
||||
<input name="password" id="new-password-input" type="password" placeholder="New password" class="one-line-input">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<label for="input-change-bio">Change description:</label>
|
||||
<br>
|
||||
<textarea name="bio" id="input-change-bio" class="multiline-input"></textarea>
|
||||
<button class="action-button centered-block-el" type="submit">Submit changes</button>
|
||||
</form>
|
||||
</div>
|
||||
<form method="post" action="/user/{% WRITE userprofile.nickname %}">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<p>{% WRITE userprofile.name %} ( {% WRITE userprofile.nickname %} )</p>
|
||||
<label for="name"> Изменить имя </label>
|
||||
<input type="text" name="name" id="name">
|
||||
<br>
|
||||
<label for="password"> Изменить пароль </label>
|
||||
<input type="password" name="password" id="password">
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="additional-info">
|
||||
<p>О себе</p>
|
||||
<p>{% WRITE userprofile.bio %}</p><br>
|
||||
<label for="bio">Изменить</label>
|
||||
<textarea name="bio" id="bio"></textarea>
|
||||
</div>
|
||||
<button class="save" type="submit">Сохранить изменения</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
{% ENDELDEF%}
|
||||
|
@ -4,69 +4,48 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Список Чат-Комнат</title>
|
||||
<title>List of chat rooms</title>
|
||||
<link rel="stylesheet" href="/assets/css/common.css">
|
||||
<link rel="stylesheet" href="/assets/css/common-popup.css">
|
||||
<link rel="stylesheet" href="/assets/css/list-rooms.css">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
let pres = {% PUT jsinsert pres %};
|
||||
let userinfo = {% PUT jsinsert userinfo %};
|
||||
let initial_chatListUpdResp = {% PUT jsinsert initial_chatListUpdResp %};
|
||||
</script>
|
||||
<div class="container">
|
||||
<h1 style="color: white;">Выберите Чат-Комнату</h1>
|
||||
<ul class="room-list">
|
||||
<!-- Здесь будет список комнат -->
|
||||
</ul>
|
||||
<button class="create-room-button" onclick="openCreateRoomModal()">Создать Комнату</button>
|
||||
</div>
|
||||
<script>
|
||||
let pres = {% PUT jsinsert pres %};
|
||||
let userinfo = {% PUT jsinsert userinfo %};
|
||||
let initial_chatListUpdResp = {% PUT jsinsert initial_chatListUpdResp %};
|
||||
</script>
|
||||
<div id="popup-overlay-veil"></div>
|
||||
<div id="chat-creation-win" class="popup-window">
|
||||
<h1>Input identifying information for your new chat</h1>
|
||||
</div>
|
||||
|
||||
<!-- Модальное окно для создания комнаты -->
|
||||
<!--<div id="createRoomModal" class="modal">-->
|
||||
<!-- <div class="modal-content">-->
|
||||
<!-- <div class="modal-header">-->
|
||||
<!-- <span class="close" onclick="closeCreateRoomModal()">×</span>-->
|
||||
<!-- <h2>Создать Комнату</h2>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="modal-body">-->
|
||||
<!-- <input type="text" id="newRoomName" placeholder="Название комнаты">-->
|
||||
<!-- <input type="password" id="newRoomNickname" placeholder="Никнейм комнаты">-->
|
||||
<!-- </div>-->
|
||||
<!-- <div id="error"></div>-->
|
||||
<!-- <div class="modal-footer">-->
|
||||
<!-- <button class="join-button" onclick="createRoom()">Создать</button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!--</div>-->
|
||||
<div id="chat-renunciation-win" class="popup-window">
|
||||
<!-- header will actually be rewritten before showing the window to include chat nickname -->
|
||||
<h1 id="chat-renunciation-win-title">Are you sure you want to leave chat?</h1>
|
||||
<button class="chat-renunciation-win-yes">Yes, leave</button>
|
||||
<button class="chat-renunciation-win-no">No, cancel</button>
|
||||
</div>
|
||||
|
||||
<!--<!– Модальное окно для добавления участников –>-->
|
||||
<!--<div class="overlay" id="add_members">-->
|
||||
<!-- <div class="add-members">-->
|
||||
<!-- <div class="add-members-header">-->
|
||||
<!-- <span class="close" onclick="closeAdd()">×</span>-->
|
||||
<!-- <h2>Добавить участников</h2>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="add-members-body">-->
|
||||
<!-- <input type="text" id="newMemberLogin" placeholder="Логин пользователя">-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="add-members-footer">-->
|
||||
<!-- <button class="add-member-button" onclick="addMember()">Добавить</button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="overlay" id="delete-chat">-->
|
||||
<!-- <div class="delete-chat">-->
|
||||
<!-- <div class="delete-chat-header">-->
|
||||
<!-- <span class="delete-close" onclick="closeConfirm()">×</span>-->
|
||||
<!-- <h2>Вы уверены, что хотите удалить чат?</h2>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="delete-chat-body">-->
|
||||
<!-- <button class="confirm" onclick="deleteChat()">Да</button>-->
|
||||
<!-- <button class="cancel" onclick="closeConfirm()">Нет</button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!--</div>-->
|
||||
<script src="/assets/js/list-rooms.js"></script>
|
||||
x
|
||||
<div id="document-container">
|
||||
<div id="navigation-panel" class="panel">
|
||||
<a href="/user/{% WRITE userinfo.nickname %}" id="go-to-my-profile" class="panel-thing">
|
||||
<img alt="Go to my profile" src="/assets/img/user.svg" width="32px">
|
||||
</a>
|
||||
<p class="panel-thing panel-header-txt">
|
||||
List of available rooms
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="dynamic-block-list">
|
||||
<img id="CL-bacbe" class="button-add centered-block-el" alt="New chat" src="/assets/img/add.svg">
|
||||
<div class="dynamic-block-list-el-container" id="CL-dblec">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/assets/js/list-rooms.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
{% ENDELDEF %}
|
@ -1,29 +1,40 @@
|
||||
{% ELDEF main JSON pres JSON userinfo JSON errors %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="{% WRITE pres.lang %}">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% WRITE pres.phr.decl.page-login %}</title>
|
||||
<link rel="stylesheet" href="/assets/css/common.css">
|
||||
<link rel="stylesheet" href="/assets/css/login.css">
|
||||
<title>Login Page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{% FOR msg IN errors %}
|
||||
<div class="error-msg">
|
||||
{% WRITE msg.text %}
|
||||
{% FOR error IN errors %}
|
||||
<div class="server-notif-error-msg-box">
|
||||
{% WRITE error.text %}
|
||||
</div>
|
||||
{% ENDFOR %}
|
||||
|
||||
<div class="form-container">
|
||||
<h1 class="wide-centered-header">Login</h1>
|
||||
<form action="/login" method="post" enctype="application/x-www-form-urlencoded">
|
||||
<table class="logins-input-table">
|
||||
<tr>
|
||||
<td class="logins-input-td1"><label for="input-nickname">Enter user nickname:</label></td>
|
||||
<td class="logins-input-td2">
|
||||
<input name="nickname" id="input-nickname" type="text" placeholder="Nickname" class="one-line-input" required>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="logins-input-td1"><label for="input-password">Enter password:</label></td>
|
||||
<td class="logins-input-td2">
|
||||
<input name="password" id="input-password" type="password" placeholder="Password" class="one-line-input" required>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button class="action-button centered-block-el" type="submit">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
{% ENDFOR %}
|
||||
<div class="form-container">
|
||||
<h1 class="hide-cursor no-select">{% WRITE pres.phr.decl.enter %}</h1>
|
||||
<form action="/login" method="post" enctype="application/x-www-form-urlencoded">
|
||||
<label for="nickname">{% WRITE pres.phr.decl.nickname %}</label>
|
||||
<input type="text" name="nickname" id="nickname"><br>
|
||||
<label for="password">{% WRITE pres.phr.decl.password %}</label>
|
||||
<input type="password" name="password" id="password"><br>
|
||||
<button type="submit" class="hide-cursor no-select">{% WRITE pres.phr.act.enter %}</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,26 +1,35 @@
|
||||
{% ELDEF main JSON pres JSON userprofile %}
|
||||
{% ELDEF main JSON pres JSON userinfo JSON alienprofile %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="/assets/css/profile.css">
|
||||
<title>Профиль</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/css/common.css">
|
||||
<!-- This page is so simple, that it does not even have it's separate css file -->
|
||||
<title>User Profile</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-container">
|
||||
<div class="profile-header">
|
||||
<h1>Профиль пользователя</h1>
|
||||
|
||||
<div id="document-container">
|
||||
<div id="navigation-panel" class="panel">
|
||||
<a href="/list-rooms" id="go-to-chat-list" class="panel-thing">
|
||||
<img alt="Go to list of chats" src="/assets/img/list-rooms.svg" width="32px">
|
||||
</a>
|
||||
<a href="/user/{% WRITE userinfo.nickname %}" id="go-to-my-profile" class="panel-thing">
|
||||
<img alt="Go to my profile" src="/assets/img/user.svg" width="32px">
|
||||
</a>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<p>{% WRITE userprofile.name %} ( {% WRITE userprofile.nickname %} )</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="additional-info">
|
||||
<p>О себе</p>
|
||||
<p>{% WRITE userprofile.bio %}</p><br>
|
||||
|
||||
<div class="profile-container">
|
||||
<h2 class="profile-name-text">{% WRITE alienprofile.name %}</h2>
|
||||
<h3 class="profile-nickname-text">Nickname: {% WRITE alienprofile.nickname %}</h3>
|
||||
<p class="profile-bio-text">
|
||||
{% WRITE alienprofile.bio %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
{% ENDELDEF%}
|
||||
|
@ -0,0 +1,72 @@
|
||||
body, html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#navigation-info-panel {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#chat-widget {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
background-color: #f1f1f1;
|
||||
color: black;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#chat-widget .message-box {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
max-width: 300px;
|
||||
border: 2px solid dimgrey;
|
||||
padding: 5px;
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* in #chat-widget .message-box */
|
||||
.message-box-top{
|
||||
/* You see, each message contains a 20+2+2 px high icon that HAS TO BE LOADED FIRST.
|
||||
This happens after window.onload, so I added a crutch: loading won't update height in
|
||||
unpredictable moment. cause it will be already high enough. BUGA-GA-GA!! */
|
||||
min-height: 30px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.message-box-sender-name{
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
padding: 2px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.message-box-sender-name:hover{
|
||||
color: #1060ff
|
||||
}
|
||||
|
||||
.message-box-button{
|
||||
width: 20px;
|
||||
padding: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.message-box-msg{
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#input-panel {
|
||||
|
||||
}
|
||||
|
||||
#input-panel #message-input{
|
||||
padding: 15px;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
background-color: white;
|
||||
border: 1px solid #1000d0;
|
||||
border-radius : 7px;
|
||||
font-size: .9rem;
|
||||
margin: 10px;
|
||||
}
|
30
assets/css/common-popup.css
Normal file
30
assets/css/common-popup.css
Normal file
@ -0,0 +1,30 @@
|
||||
#popup-overlay-veil {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
|
||||
z-index: 99;
|
||||
display: none; /* Hidden by default */
|
||||
}
|
||||
|
||||
.popup-window {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: white;
|
||||
padding: 20px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
||||
|
||||
z-index: 100;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.popup-btn {
|
||||
display: inline;
|
||||
padding: 5px;
|
||||
border-bottom: 3px;
|
||||
}
|
193
assets/css/common.css
Normal file
193
assets/css/common.css
Normal file
@ -0,0 +1,193 @@
|
||||
/* Profile view elements */
|
||||
.profile-container {
|
||||
background: white;
|
||||
border-radius: 5px;
|
||||
padding: 20px;
|
||||
margin-top: 60px; /* Space below the fixed panel */
|
||||
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.profile-name-text {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.profile-nickname-text{
|
||||
color: #444;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.profile-bio-text {
|
||||
padding-top: 40px;
|
||||
text-align: left;
|
||||
line-height: 1.6;
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* Panels */
|
||||
.panel {
|
||||
width: 100%;
|
||||
border: 2px solid blue;
|
||||
background-color: #54b3ff;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.panel-thing {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.panel-header-txt{
|
||||
color: white;
|
||||
font-size: 1.9em;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/* Containers for the whole document */
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
#document-container {
|
||||
width: 80%; /* Full width of the viewport */
|
||||
margin: 0 auto; /* Center the container horizontally */
|
||||
}
|
||||
|
||||
#fullscreen-container {
|
||||
width: 80%; /* Full width of the viewport */
|
||||
height: 100vh; /* Full height of the viewport */
|
||||
display: flex;
|
||||
flex-direction: column; /* Stack children vertically */
|
||||
margin: 0 auto; /* Center the container horizontally */
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #f000f0;
|
||||
background-image: url("/assets/img/clavicle-transparent.png"), url("/assets/img/broken-clavicle.png");
|
||||
background-repeat: revert;
|
||||
background-size: 10%, 25%;
|
||||
}
|
||||
|
||||
/* Notifications, returned from server and embedded into html page at render-time */
|
||||
|
||||
.server-notif-error-msg-box{
|
||||
font-size: 1.3em;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
border: 2px solid red;
|
||||
border-radius: 30px;
|
||||
background-color: #ff5050;
|
||||
max-width: 40%;
|
||||
margin: 15px auto;
|
||||
}
|
||||
|
||||
/* Centered headers */
|
||||
|
||||
.wide-centered-header {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
}
|
||||
/* Cool buttons with text */
|
||||
|
||||
.action-button {
|
||||
padding: 10px 15px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
|
||||
.action-button:hover {
|
||||
background-color: #0056b3; /* Darker blue on hover */
|
||||
}
|
||||
|
||||
/* This is for centering non-100%wide block */
|
||||
|
||||
.centered-block-el {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* Beautiful text input */
|
||||
|
||||
.one-line-input {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin: 8px 0;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.multiline-input {
|
||||
width: 100%;
|
||||
/*max-width: 600px;*/
|
||||
height: 200px;
|
||||
padding: 10px;
|
||||
font-size: 1.15em;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 5px;
|
||||
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1); /* Subtle shadow */
|
||||
outline: none; /* Remove default outline on focus */
|
||||
resize: vertical; /* Allow resizing vertically */
|
||||
transition: border-color 0.15s, box-shadow 0.15s; /* Smooth transition for border color and shadow */
|
||||
}
|
||||
|
||||
.multiline-input:focus {
|
||||
border-color: #007bff; /* Change border color on focus */
|
||||
box-shadow: 0 0 5px rgba(0, 123, 255, 0.5); /* Shadow on focus */
|
||||
}
|
||||
|
||||
/* Handles the case of list of elements with dickanme, name, role and delete button
|
||||
For list of chats and list of users in chat */
|
||||
.dynamic-block-list {
|
||||
margin-top:12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: white;
|
||||
border: 1px solid #c7c7c7;
|
||||
align-items: stretch;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.dynamic-block-list-el {
|
||||
margin-top: 8px;
|
||||
background-color: white;
|
||||
border: 1px solid #c7c7c7;
|
||||
color: black;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.button-add{
|
||||
width: 50px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dynamic-block-list-el-container{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.entity-nickname-txt {
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.entity-reg-field-txt {
|
||||
/* For name and role */
|
||||
color: #242424;
|
||||
text-decoration: none;
|
||||
font-size: 1.5em;
|
||||
}
|
23
assets/css/edit-profile.css
Normal file
23
assets/css/edit-profile.css
Normal file
@ -0,0 +1,23 @@
|
||||
/* The morbid thing */
|
||||
table.logins-input-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse; /* Combine borders */
|
||||
}
|
||||
.logins-input-td1, .logins-input-td2 {
|
||||
border: none;
|
||||
}
|
||||
.logins-input-td1 {
|
||||
text-align: left;
|
||||
padding-right: 5px;
|
||||
white-space: nowrap; /* Prevent text wrap, keeping it in one line */
|
||||
overflow: hidden; /* Hide overflow content */
|
||||
text-overflow: ellipsis; /* Show ellipsis for overflowing text */
|
||||
}
|
||||
.logins-input-td2 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#input-change-bio{
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
@ -1,253 +1,35 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f0f0f0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
#navigation-panel {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 30px auto;
|
||||
padding: 20px;
|
||||
background-color: #007bff;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 8px;
|
||||
#CL-bacbe {
|
||||
margin: 6px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.room-list {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.room-item {
|
||||
.CL-my-chat-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
margin: 10px 0;
|
||||
background-color: #fafafa;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.3s ease;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.room-item:hover {
|
||||
background-color: #eaeaea;
|
||||
.CL-my-chat-box-nickname {
|
||||
margin-left: 8px;
|
||||
justify-self: flex-start;
|
||||
}
|
||||
|
||||
.room-name {
|
||||
font-size: 18px;
|
||||
color: #555;
|
||||
.CL-my-chat-box-name {
|
||||
margin-left: 14px;
|
||||
justify-self: flex-start;
|
||||
}
|
||||
|
||||
.join-button {
|
||||
padding: 10px 15px;
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
background-color: #007bff;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
.add-members-header {
|
||||
text-align: center;
|
||||
}
|
||||
.add-members-footer {
|
||||
text-align: right;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.add-members-button {
|
||||
background-color: #218838;
|
||||
padding: 10px 15px;
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
margin-left: 502px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
.add-members-button:hover {
|
||||
background-color: #006509
|
||||
}
|
||||
.delete-chat-button {
|
||||
background-color: #dc2e45;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
padding: 10px 15px;
|
||||
margin-left: 380px;
|
||||
}
|
||||
.delete-chat-button:hover {
|
||||
background-color: #881527;
|
||||
}
|
||||
#newMemberLogin {
|
||||
width: 93.5%;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.add-member-button {
|
||||
background-color: #218838;
|
||||
padding: 10px 15px;
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
margin-left: -105px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
.join-button:hover {
|
||||
background-color: #0056b3;
|
||||
.CL-my-chat-box-my-role {
|
||||
margin-left: auto;
|
||||
justify-self: flex-end;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #fff;
|
||||
margin: 10% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 80%;
|
||||
max-width: 400px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.modal-header, .modal-footer {
|
||||
padding: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.modal input {
|
||||
width: 93.5%;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.create-room-button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
background-color: #1609ab;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.create-room-button:hover {
|
||||
background-color: #218838;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.overlay .add-members {
|
||||
background-color: white;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
height: 18%;
|
||||
position: fixed;
|
||||
}
|
||||
.overlay .delete-chat {
|
||||
background-color: white;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
height: 18%;
|
||||
position: fixed;
|
||||
}
|
||||
.delete-close {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
.CL-my-chat-box-leave-btn {
|
||||
margin-left: 10px;
|
||||
margin-right: 8px;
|
||||
justify-self: flex-end;
|
||||
width: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.delete-chat-header {
|
||||
text-align: center;
|
||||
}
|
||||
.confirm {
|
||||
background-color: #1609ab;
|
||||
padding: 20px 70px;
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
margin-left: 20px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
.cancel {
|
||||
background-color: #1609ab;
|
||||
padding: 20px 70px;
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
margin-left: 220px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
.close {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
@ -1,59 +1,34 @@
|
||||
/* I have no idea what is going on here */
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
height: 100vh; /* Full viewport height */
|
||||
margin: 0;
|
||||
background-color: #e5e5e5;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
background-color: white;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 8px;
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
background-color: #ffffff; /* Brighter box color */
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||
width: 50%; /* Set width of the form */
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 20px;
|
||||
color: #2F4F4F;
|
||||
}
|
||||
|
||||
input {
|
||||
/* The morbid thing */
|
||||
table.logins-input-table {
|
||||
width: 100%;
|
||||
background: #f7f7f7;
|
||||
font-size: 16px;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 20px;
|
||||
margin-bottom: 15px;
|
||||
outline: none;
|
||||
border-collapse: collapse; /* Combine borders */
|
||||
}
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
.logins-input-td1, .logins-input-td2 {
|
||||
border: none;
|
||||
background-color: #0088cc;
|
||||
color: white;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
color: red;
|
||||
background-color: #ffc0c0;
|
||||
border-color: red;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.logins-input-td1 {
|
||||
padding-right: 5px;
|
||||
white-space: nowrap; /* Prevent text wrap, keeping it in one line */
|
||||
overflow: hidden; /* Hide overflow content */
|
||||
text-overflow: ellipsis; /* Show ellipsis for overflowing text */
|
||||
}
|
||||
.logins-input-td2 {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -1,129 +0,0 @@
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 90vh;
|
||||
background-color: #e5e5e5;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
.main-container {
|
||||
width: 700px;
|
||||
height: 700px;
|
||||
border-color: antiquewhite;
|
||||
background-color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.profile-header {
|
||||
width: 700px;
|
||||
height: 160px;
|
||||
border-color: antiquewhite;
|
||||
background-color: #0088cc;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
}
|
||||
.return {
|
||||
background-color: #f0f0f0;
|
||||
cursor: pointer;
|
||||
width: 100px;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
border-radius: 10px;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 25px;
|
||||
border: none;
|
||||
}
|
||||
.return:hover{
|
||||
text-decoration: underline;
|
||||
color: #0088cc;
|
||||
}
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.columns {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
.add {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
border-width: 2px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.add:hover {
|
||||
background-color: #007bb5;
|
||||
}
|
||||
.image-button:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.image-button:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
#login {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size:16px;
|
||||
width: 150px;
|
||||
height: 20px;
|
||||
border-radius: 10px;
|
||||
border-color: #2F4F4F;
|
||||
}
|
||||
#username {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size:16px;
|
||||
width: 150px;
|
||||
height: 20px;
|
||||
margin-bottom: 1px;
|
||||
margin-top: 50px;
|
||||
border-radius: 10px;
|
||||
border-color: #2F4F4F;
|
||||
}
|
||||
#bio {
|
||||
height: 150px;
|
||||
width: 500px;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size:14px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.save {
|
||||
cursor:pointer;
|
||||
font-size: 16px;
|
||||
border-radius: 15px;
|
||||
border-color: #2F4F4F;
|
||||
height: 40px;
|
||||
width: 150px;
|
||||
}
|
||||
.save:hover {
|
||||
background-color: #007bb5;
|
||||
}
|
||||
.avatar {
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
dy {
|
||||
font-family: Arial, sans-serif;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
background-color: #e5e5e5;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
background-color: white;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 8px;
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 20px;
|
||||
color: #2F4F4F;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
background: #f7f7f7;
|
||||
font-size: 16px;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 20px;
|
||||
margin-bottom: 15px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
border: none;
|
||||
background-color: #0088cc;
|
||||
color: white;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
button:hover,
|
||||
button:focus-visible {
|
||||
background-color: #007bb5;
|
||||
}
|
||||
|
||||
.hide-cursor::placeholder {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.hide-cursor {
|
||||
caret-color: transparent;
|
||||
}
|
||||
|
||||
.no-select {
|
||||
-webkit-user-select: none; /* Для Safari */
|
||||
-moz-user-select: none; /* Для Firefox */
|
||||
user-select: none; /* Для всех остальных браузеров */
|
||||
}
|
||||
|
||||
div {
|
||||
color: red;
|
||||
font-size: 15px;
|
||||
margin-top: 10px;
|
||||
display: none;
|
||||
}
|
@ -0,0 +1,227 @@
|
||||
// In real world, I would get this variables from server through nytl
|
||||
let pres = {lang: ''}
|
||||
let userinfo = {id: 2, nickname: 'pv', name: 'Pavlov Vladimir'};
|
||||
let openedchat = {id: 100, name: "Some chat", nickname: 'chat'};
|
||||
let initial_chatUpdResp = {
|
||||
LocalHistoryId: 0,
|
||||
lastMsgId: -1,
|
||||
messages: [],
|
||||
members: [
|
||||
{id: 1, name: 'grisha', nickname: 'gri', role: 'admin'},
|
||||
{id: 2, name: 'Pavlov Vladimir', nickname: 'pv', role: 'regular'},
|
||||
{id: 3, name: 'Ivan', nickname: 'ivan', role: 'read-only'}
|
||||
]
|
||||
};
|
||||
|
||||
let loadedMessages = new Map(); // messageSt objects
|
||||
let visibleMessages = new Map(); // HTMLElement objects
|
||||
|
||||
let anchoredMsg = -1;
|
||||
let visibleMsgSegStart = -1;
|
||||
let visibleMsgSegEnd = -2;
|
||||
let offsetOfAnchor = 100;
|
||||
|
||||
// Would start with true if opened `/chat/<>`
|
||||
let bumpedAtTheBottom = false;
|
||||
|
||||
let members = new Map();
|
||||
for (let memberSt of initial_chatUpdResp.members){
|
||||
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){
|
||||
visibleMessages.get(msgId).style.bottom = String(offset) + "px";
|
||||
}
|
||||
|
||||
function updateOffsetsUpToTop(){
|
||||
let offset = offsetOfAnchor;
|
||||
for (let curMsg = anchoredMsg; curMsg >= visibleMsgSegStart; curMsg--){
|
||||
updateOffsetOfVisibleMsg(curMsg, offset);
|
||||
let height = visibleMessages.get(curMsg).offsetHeight;
|
||||
offset += height + 5;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
function updateOffsetsDown(){
|
||||
let offset = offsetOfAnchor;
|
||||
for (let curMsg = anchoredMsg + 1; curMsg <= visibleMsgSegEnd; curMsg++){
|
||||
let height = visibleMessages.get(curMsg).offsetHeight;
|
||||
offset -= (height + 5);
|
||||
updateOffsetOfVisibleMsg(curMsg, offset);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
function updateOffsetsSane(){
|
||||
let highest_point = updateOffsetsUpToTop();
|
||||
let lowest_point = updateOffsetsDown();
|
||||
return [highest_point, lowest_point];
|
||||
}
|
||||
|
||||
function updateOffsets(){
|
||||
if (anchoredMsg < 0)
|
||||
return;
|
||||
let [highest_point, lowest_point] = updateOffsetsSane();
|
||||
let winTop = document.getElementById("chat-widget").offsetHeight;
|
||||
if (lowest_point > 5 || (highest_point - lowest_point) <= winTop){
|
||||
bumpedAtTheBottom = true;
|
||||
anchoredMsg = visibleMsgSegEnd;
|
||||
offsetOfAnchor = 5;
|
||||
updateOffsetsSane();
|
||||
} else if (highest_point < winTop - 5){
|
||||
console.log("Adancing by " + (winTop - 5 - highest_point))
|
||||
offsetOfAnchor += (winTop - 5 - highest_point);
|
||||
updateOffsetsSane();
|
||||
}
|
||||
}
|
||||
|
||||
function makeMessageBox(messageSt){
|
||||
if (!messageSt.exists || messageSt.isSystem)
|
||||
throw new Error("Not ready for this");
|
||||
const parentDiv = document.getElementById("chat-widget");
|
||||
let box = document.createElement("div");
|
||||
parentDiv.appendChild(box);
|
||||
box.className = "message-box";
|
||||
|
||||
let topPart = document.createElement("div");
|
||||
box.appendChild(topPart);
|
||||
topPart.className = "message-box-top";
|
||||
|
||||
let inTopPartSenderName = document.createElement("a");
|
||||
topPart.appendChild(inTopPartSenderName);
|
||||
inTopPartSenderName.className = "message-box-sender-name";
|
||||
if (!members.has(messageSt.senderUserId))
|
||||
throw new Error("MMMHMMMMGMHMMMM. First - update members. Then messages");
|
||||
let memberSt = members.get(messageSt.senderUserId);
|
||||
inTopPartSenderName.innerText = memberSt.name + " (" + memberSt.nickname + ")";
|
||||
inTopPartSenderName.href = "/user/" + memberSt.nickname;
|
||||
|
||||
let ID = messageSt.id;
|
||||
|
||||
let inTopPartButtonDelete = document.createElement("img");
|
||||
topPart.appendChild(inTopPartButtonDelete);
|
||||
inTopPartButtonDelete.className = "message-box-button";
|
||||
inTopPartButtonDelete.src = "/assets/img/delete.svg";
|
||||
inTopPartButtonDelete.onclick = (ev) => {
|
||||
if (ev.button === 0){
|
||||
console.log("Tried to delete message " + ID);
|
||||
}
|
||||
};
|
||||
|
||||
let inTopPartButtonGetLink = document.createElement("img");
|
||||
topPart.appendChild(inTopPartButtonGetLink);
|
||||
inTopPartButtonGetLink.className = "message-box-button";
|
||||
inTopPartButtonGetLink.src = "/assets/img/link.svg";
|
||||
inTopPartButtonGetLink.onclick = (ev) => {
|
||||
if (ev.button === 0){
|
||||
console.log("Tried to get link on message " + ID);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let msgPart = document.createElement("p");
|
||||
box.appendChild(msgPart);
|
||||
msgPart.className = "message-box-msg";
|
||||
msgPart.innerText = messageSt.text;
|
||||
return box;
|
||||
}
|
||||
|
||||
function makeVisible(msgId){
|
||||
visibleMessages.set(msgId, makeMessageBox(loadedMessages.get(msgId)))
|
||||
}
|
||||
|
||||
function opaNewMessage(messageSt){
|
||||
let msgId = messageSt.id;
|
||||
let text = messageSt.text;
|
||||
const chatWin = document.getElementById("chat-widget");
|
||||
if (loadedMessages.has(msgId)){
|
||||
throw new Error("Not ready yet");
|
||||
// loadedMessages.get(msgId).text = text;
|
||||
// if (visibleMessages.has(msgId)){
|
||||
// visibleMessages.get(msgId).textContent = text;
|
||||
// updateOffsets();
|
||||
// }
|
||||
} else {
|
||||
loadedMessages.set(msgId, messageSt);
|
||||
if (anchoredMsg < 0){
|
||||
anchoredMsg = msgId;
|
||||
visibleMsgSegStart = msgId;
|
||||
visibleMsgSegEnd = msgId;
|
||||
makeVisible(msgId);
|
||||
updateOffsets();
|
||||
} else if (msgId + 1 === visibleMsgSegStart) {
|
||||
visibleMsgSegStart--;
|
||||
makeVisible(msgId);
|
||||
while (loadedMessages.has(visibleMsgSegStart - 1)){
|
||||
visibleMsgSegStart--;
|
||||
makeVisible(visibleMsgSegStart);
|
||||
}
|
||||
updateOffsets();
|
||||
} else if (msgId - 1 === visibleMsgSegEnd){
|
||||
visibleMsgSegEnd++;
|
||||
makeVisible(msgId);
|
||||
while (loadedMessages.has(visibleMsgSegEnd + 1)){
|
||||
visibleMsgSegEnd++;
|
||||
makeVisible(visibleMsgSegEnd);
|
||||
}
|
||||
updateOffsets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function test(id, uid){
|
||||
opaNewMessage({
|
||||
id: id, text: "Message number " + String(id), senderUserId: uid, exists: true, isSystem: false}
|
||||
);
|
||||
}
|
||||
|
||||
let mainloopTimeout = null;
|
||||
|
||||
let mainloopPoller = null;
|
||||
|
||||
function setMainloopTimeout(){
|
||||
mainloopTimeout = setTimeout(mainloopPoller, 1000);
|
||||
}
|
||||
|
||||
mainloopPoller = function(){
|
||||
try {
|
||||
console.log("Hello, World!");
|
||||
} catch (error){}
|
||||
setMainloopTimeout();
|
||||
}
|
||||
|
||||
|
||||
window.onload = function (){
|
||||
console.log("Everything was loaded");
|
||||
test(6, 1);
|
||||
test(1, 2);
|
||||
test(3, 3);
|
||||
test(2, 1);
|
||||
test(4, 2);
|
||||
test(0, 3);
|
||||
test(5, 2);
|
||||
test(8, 1);
|
||||
test(9, 2);
|
||||
test(7, 3);
|
||||
for (let i = 10; i < 30; i++){
|
||||
test(i, 2);
|
||||
}
|
||||
document.body.addEventListener("wheel", (event) => {
|
||||
event.preventDefault();
|
||||
bumpedAtTheBottom = false;
|
||||
console.log("Scroll of " + String(event.deltaY));
|
||||
offsetOfAnchor += event.deltaY / 5;
|
||||
updateOffsets();
|
||||
});
|
||||
mainloopPoller();
|
||||
document.getElementById("message-input").addEventListener("keyup", (event) => {
|
||||
if (event.ctrlKey && event.key === 'Enter'){
|
||||
let textarea = document.getElementById("message-input");
|
||||
console.log(textarea.value);
|
||||
}
|
||||
});
|
||||
}
|
@ -1,186 +1,72 @@
|
||||
let rooms = {};
|
||||
let roomToDelete = null;
|
||||
let currentRoom = null;
|
||||
let currentHistoryId = 0;
|
||||
let LocalHistoryId = 0;
|
||||
|
||||
function openRoom(currentRoom) {
|
||||
alert('Вы вошли в комнату: ' + currentRoom);
|
||||
}
|
||||
let myChats = new Map();
|
||||
let chatBoxes = new Map();
|
||||
|
||||
function closeAdd() {
|
||||
document.getElementById('add_members').style.display = 'none';
|
||||
}
|
||||
const roleDeleted = "not-a-member";
|
||||
|
||||
function openAdd() {
|
||||
document.getElementById('add_members').style.display = 'flex';
|
||||
}
|
||||
function convertStToBox(myMembershipSt){
|
||||
let chatURI = "/user/" + myMembershipSt.chatNickname;
|
||||
|
||||
function openConfirm(roomNickname) {
|
||||
roomToDelete = roomNickname;
|
||||
document.getElementById("delete-chat").style.display = "flex";
|
||||
}
|
||||
let box = document.createElement("div");
|
||||
chatBoxes.set(myMembershipSt.chatId, box);
|
||||
box.className = "dynamic-block-list-el CL-my-chat-box";
|
||||
|
||||
function closeConfirm() {
|
||||
roomToDelete = null;
|
||||
document.getElementById("delete-chat").style.display = "none";
|
||||
}
|
||||
let inBoxNickname = document.createElement("a");
|
||||
box.appendChild(inBoxNickname);
|
||||
inBoxNickname.className = "entity-nickname-txt CL-my-chat-box-nickname";
|
||||
console.log(myMembershipSt);
|
||||
console.log(myMembershipSt.chatNickname);
|
||||
inBoxNickname.innerText = myMembershipSt.chatNickname;
|
||||
inBoxNickname.href = chatURI;
|
||||
|
||||
function deleteChat() {
|
||||
if (roomToDelete && rooms[roomToDelete]) {
|
||||
delete rooms[roomToDelete];
|
||||
removeRoomFromList(roomToDelete);
|
||||
closeConfirm();
|
||||
} else {
|
||||
alert("Не удалось найти выбранную комнату.");
|
||||
}
|
||||
}
|
||||
let inBoxName = document.createElement("a");
|
||||
box.appendChild(inBoxName);
|
||||
inBoxName.className = "entity-reg-field-txt CL-my-chat-box-name";
|
||||
inBoxName.innerText = myMembershipSt.chatName;
|
||||
inBoxName.href = chatURI;
|
||||
|
||||
function addMember() {
|
||||
const login = document.getElementById('newMemberLogin').value;
|
||||
if (login) {
|
||||
alert(`Участник с никнеймом '${login}' добавлен`);
|
||||
closeAdd();
|
||||
} else {
|
||||
alert('Пожалуйста, введите логин участника');
|
||||
}
|
||||
}
|
||||
let inBoxMyRoleHere = document.createElement("p");
|
||||
box.appendChild(inBoxMyRoleHere);
|
||||
inBoxMyRoleHere.className = "entity-reg-field-txt CL-my-chat-box-my-role";
|
||||
inBoxMyRoleHere.innerText = "You are " + myMembershipSt.myRoleHere + " here";
|
||||
|
||||
function openCreateRoomModal() {
|
||||
document.getElementById('createRoomModal').style.display = 'block';
|
||||
}
|
||||
let ID = myMembershipSt.chatId;
|
||||
|
||||
function closeCreateRoomModal() {
|
||||
document.getElementById('createRoomModal').style.display = 'none';
|
||||
}
|
||||
|
||||
async function createRoom() {
|
||||
const errorElement = document.getElementById('error');
|
||||
const roomName = document.getElementById('newRoomName').value.trim();
|
||||
const roomNickname = document.getElementById('newRoomNickname').value.trim();
|
||||
|
||||
|
||||
errorElement.style.display = 'none';
|
||||
errorElement.textContent = '';
|
||||
|
||||
if (roomName === '' || roomNickname === '') {
|
||||
errorElement.textContent = 'Пожалуйста, заполните все поля';
|
||||
errorElement.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
|
||||
const request = {
|
||||
LocalHistoryId: currentHistoryId,
|
||||
content: {
|
||||
name: roomName,
|
||||
nickname: roomNickname
|
||||
let inBoxLeaveBtn = document.createElement("img");
|
||||
box.appendChild(inBoxLeaveBtn);
|
||||
inBoxLeaveBtn.className = "CL-my-chat-box-leave-btn";
|
||||
inBoxLeaveBtn.src = "/assets/img/delete.svg";
|
||||
inBoxLeaveBtn.onclick = function (ev) {
|
||||
if (ev.button === 0){
|
||||
console.log("Tried to leave chat" + ID);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch('/internalapi/createChat', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(request)
|
||||
});
|
||||
|
||||
const res = await response.json();
|
||||
|
||||
if (res.status === 0) {
|
||||
addRoomToList(roomName, roomNickname);
|
||||
rooms[roomNickname] = true;
|
||||
closeCreateRoomModal();
|
||||
currentHistoryId = res.update.LocalHistoryId;
|
||||
window.location.href = '/chat/' + roomNickname;
|
||||
} else {
|
||||
throw new Error(res.error || 'Ошибка');
|
||||
}
|
||||
} catch (error) {
|
||||
alert('Ошибка создания чата: ' + error.message);
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
function addRoomToList(roomName) {
|
||||
const roomList = document.querySelector('.room-list');
|
||||
const existingRoomItem = Array.from(roomList.children).find(item => item.querySelector('.room-name').textContent === roomName);
|
||||
if (existingRoomItem) {
|
||||
existingRoomItem.remove();
|
||||
}
|
||||
window.onload = function () {
|
||||
console.log("Loading complete");
|
||||
LocalHistoryId = initial_chatListUpdResp.HistoryId;
|
||||
|
||||
const roomItem = document.createElement('li');
|
||||
roomItem.classList.add('room-item');
|
||||
console.log(initial_chatListUpdResp);
|
||||
|
||||
roomItem.innerHTML = `
|
||||
<span class="room-name">${roomName}</span>
|
||||
<button class="delete-chat-button" onclick="openConfirm('${roomNickname}')">Удалить чат</button>
|
||||
<button class="add-members-button" onclick="openAdd()">Добавить участников</button>
|
||||
<button class="join-button" onclick="window.location.href = '/chat/${roomNickname}'">Войти</button>
|
||||
`;
|
||||
let literalChatList = document.getElementById("CL-dblec");
|
||||
|
||||
roomList.appendChild(roomItem);
|
||||
}
|
||||
|
||||
function removeRoomFromList(roomName, roomNickname) {
|
||||
const roomList = document.querySelector('.room-list');
|
||||
const roomItem = Array.from(roomList.children).find(item => item.querySelector('.room-name').textContent === roomName);
|
||||
if (roomItem) {
|
||||
roomList.removeChild(roomItem);
|
||||
}
|
||||
}
|
||||
|
||||
async function initializeRoomList() {
|
||||
try {
|
||||
const response = await fetch('/internalapi/getChatList', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({})
|
||||
});
|
||||
|
||||
const res = await response.json();
|
||||
|
||||
if (res.status === 0) {
|
||||
res.chats.forEach(chat => {
|
||||
addRoomToList(chat.content.name, chat.content.nickname);
|
||||
});
|
||||
} else {
|
||||
throw new Error(res.error || 'Неизвестная ошибка');
|
||||
}
|
||||
} catch (error) {
|
||||
alert('Ошибка загрузки списка чатов: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function getChatID() {
|
||||
const chatNickname = window.location.pathname.split('/').pop();
|
||||
const response = await fetch('/internalapi/getChatList', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({})
|
||||
});
|
||||
|
||||
const res = await response.json();
|
||||
for (const chat of res.chats) {
|
||||
if (chat.content.nickname === chatNickname) {
|
||||
return chat.id;
|
||||
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);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
window.onclick = function(event) {
|
||||
if (event.target === document.getElementById('createRoomModal')) {
|
||||
closeCreateRoomModal();
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('newRoomName').addEventListener('keydown', function(event) {
|
||||
if (event.key === 'Enter') {
|
||||
createRoom();
|
||||
}
|
||||
});
|
||||
document.addEventListener('DOMContentLoaded', initializeRoomList);
|
||||
document.getElementById("CL-bacbe").onclick = function (ev){
|
||||
if (ev.button === 0){
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -112,6 +112,10 @@ namespace een9 {
|
||||
return status;
|
||||
}
|
||||
res.body.reserve(std::min(100000ul, body_size));
|
||||
if (body_size == 0) {
|
||||
status = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!res.has_body) {
|
||||
|
@ -55,13 +55,16 @@ namespace nytl {
|
||||
}
|
||||
|
||||
char skip(ParsingContext& ctx) {
|
||||
ASSERT(ctx.pos < ctx.text.size(), "Unexpected EOF");
|
||||
if (ctx.pos >= ctx.text.size())
|
||||
THROW("Unexpected EOF");
|
||||
return advance(ctx);
|
||||
}
|
||||
|
||||
void skip(ParsingContext& ctx, char ch) {
|
||||
ASSERT(ctx.pos < ctx.text.size(), "Unexpected EOF");
|
||||
ASSERT(ctx.text[ctx.pos] == ch, "Unexpected character");
|
||||
if (ctx.pos >= ctx.text.size())
|
||||
THROW("Unexpected EOF");
|
||||
if (ctx.text[ctx.pos] != ch)
|
||||
THROW("Unexpected character");
|
||||
advance(ctx);
|
||||
}
|
||||
|
||||
@ -150,7 +153,8 @@ namespace nytl {
|
||||
void parse_bare_file(const std::string& filename, const std::string& content,
|
||||
global_elem_set_t& result)
|
||||
{
|
||||
ASSERT(result.count(filename) == 0, "Repeated element " + filename);
|
||||
if (result.count(filename) != 0)
|
||||
THROW("Repeated element " + filename);
|
||||
std::string txt = clement_lstrip(content);
|
||||
rstrip(txt);
|
||||
size_t cut = 9999999999999;
|
||||
@ -170,13 +174,15 @@ namespace nytl {
|
||||
uptr<TPFrame> toMe(bool returned, ParsingContext& ctx) {
|
||||
if (!returned) {
|
||||
std::string nm = readName(ctx);
|
||||
ASSERT(!nm.empty(), "Type specification expected");
|
||||
if (nm.empty())
|
||||
THROW("Type specification expected");
|
||||
nm = make_uppercase(nm);
|
||||
if (nm == "JSON") {
|
||||
result = json::JSON(true);
|
||||
return NULL;
|
||||
}
|
||||
ASSERT(nm == "EL", "Type of argument variable is either JSON or EL(...signature)")
|
||||
if (nm != "EL")
|
||||
THROW("Type of argument variable is either JSON or EL(...signature)");
|
||||
skip(ctx, '(');
|
||||
result.asArray();
|
||||
assert(result.isArray());
|
||||
@ -217,8 +223,10 @@ namespace nytl {
|
||||
uptr<EPFrame> toMe(bool returned, ParsingContext& ctx, const arg_name_list_t& local_var_names) {
|
||||
if (!returned) {
|
||||
std::string first = readName(ctx);
|
||||
ASSERT(!first.empty(), "Expression should start with 'root' name of global package or local variable");
|
||||
ASSERT(first != "_", "_ ??? ARE YOU KIDDING???");
|
||||
if (first.empty())
|
||||
THROW("Expression should start with 'root' name of global package or local variable");
|
||||
if (first == "_")
|
||||
THROW("Expression root can't be _");
|
||||
if (local_var_names.count(first) == 1) {
|
||||
result["V"].asInteger() = json::Integer((int64_t)local_var_names.at(first));
|
||||
} else {
|
||||
@ -243,7 +251,8 @@ namespace nytl {
|
||||
t = readUint(ctx);
|
||||
if (!t.empty()) {
|
||||
size_t v = std::stoul(t);
|
||||
ASSERT(v < INT64_MAX, "Index is too big");
|
||||
if (v >= INT64_MAX)
|
||||
THROW("Index is too big");
|
||||
chain.back() = json::JSON((int64_t)v);
|
||||
continue;
|
||||
}
|
||||
@ -352,7 +361,8 @@ namespace nytl {
|
||||
ElementPart::when_for_put_S& P = result.parts.back().when_for_put;
|
||||
skipWhitespace(ctx);
|
||||
std::string V1 = readName(ctx);
|
||||
ASSERT(!V1.empty(), "Expected variable name");
|
||||
if (V1.empty())
|
||||
THROW("Expected variable name");
|
||||
skipWhitespace(ctx);
|
||||
bool have_colon_and_2 = false;
|
||||
std::string V2;
|
||||
@ -364,7 +374,8 @@ namespace nytl {
|
||||
skipWhitespace(ctx);
|
||||
}
|
||||
op = make_uppercase(readName(ctx));
|
||||
ASSERT(op == "IN", "Expected IN");
|
||||
if (op != "IN")
|
||||
THROW("Expected IN");
|
||||
skipWhitespace(ctx);
|
||||
P.ref_over = parse_expression(ctx, local_var_names);
|
||||
P.internal_element = el_name + ".~" + std::to_string(free_hidden++);
|
||||
@ -372,13 +383,15 @@ namespace nytl {
|
||||
newborn.is_hidden = true;
|
||||
arg_name_list_t local_var_names_of_nxt = local_var_names;
|
||||
if (V1 != "_") {
|
||||
ASSERT(local_var_names_of_nxt.count(V1) == 0, "Repeated local variable");
|
||||
if (local_var_names_of_nxt.count(V1) != 0)
|
||||
THROW("Repeated local variable");
|
||||
size_t k = local_var_names_of_nxt.size();
|
||||
local_var_names_of_nxt.emplace(V1, k);
|
||||
(have_colon_and_2 ? P.where_key_var : P.where_value_var) = (ssize_t)k;
|
||||
}
|
||||
if (have_colon_and_2 && V2 != "_") {
|
||||
ASSERT(local_var_names_of_nxt.count(V2) == 0, "Repeated local variable");
|
||||
if (local_var_names_of_nxt.count(V2) != 0)
|
||||
THROW("Repeated local variable");
|
||||
size_t k = local_var_names_of_nxt.size();
|
||||
local_var_names_of_nxt.emplace(V2, k);
|
||||
P.where_value_var = (ssize_t)k;
|
||||
@ -395,11 +408,12 @@ namespace nytl {
|
||||
ElementPart::when_ref_put_S& P = result.parts.back().when_ref_put;
|
||||
skipWhitespace(ctx);
|
||||
std::string Vn = readName(ctx);
|
||||
ASSERT(!Vn.empty(), "Expected variable name");
|
||||
ASSERT(Vn != "_", "Are you kidding???");
|
||||
if (Vn.empty() || Vn == "_")
|
||||
THROW("REF: expected variable name");
|
||||
skipWhitespace(ctx);
|
||||
op = make_uppercase(readName(ctx));
|
||||
ASSERT(op == "AS", "Expected AS");
|
||||
if (op != "AS")
|
||||
THROW("Expected AS");
|
||||
skipWhitespace(ctx);
|
||||
P.ref_over = parse_expression(ctx, local_var_names);
|
||||
P.internal_element = el_name + ".~" + std::to_string(free_hidden++);
|
||||
@ -467,13 +481,15 @@ namespace nytl {
|
||||
}
|
||||
};
|
||||
if (op == "ENDELDEF") {
|
||||
ASSERT(myself == gone_for_nothing, "Unexpected end of element");
|
||||
if (myself != gone_for_nothing)
|
||||
THROW("Unexpected ENDELDEF");
|
||||
skip_magic_block_end(ctx, syntax);
|
||||
prepare_to_depart_parts();
|
||||
return NULL;
|
||||
}
|
||||
if (op == "ENDFOR") {
|
||||
ASSERT(myself == gone_for_for, "Unexpected end of for cycle");
|
||||
if (myself != gone_for_for)
|
||||
THROW("Unexpected ENDFOR");
|
||||
skipWhitespace(ctx);
|
||||
/* Here I am using ret_data_int to return info about NOLF(1)/LF(2) decision */
|
||||
ret_data_int = 2; // Default is to do LF
|
||||
@ -491,7 +507,8 @@ namespace nytl {
|
||||
return NULL;
|
||||
}
|
||||
if (op == "ENDREF") {
|
||||
assert(myself == gone_for_ref);
|
||||
if (myself != gone_for_ref)
|
||||
THROW("Unexpected ENDREF");
|
||||
skip_magic_block_end(ctx, syntax);
|
||||
prepare_to_depart_parts();
|
||||
return NULL;
|
||||
@ -525,12 +542,15 @@ namespace nytl {
|
||||
if (peep(ctx) == EOFVAL)
|
||||
break;
|
||||
skip_magic_block_start(ctx, syntax);
|
||||
ASSERT(make_uppercase(readName(ctx)) == "ELDEF", "Expected ELDEF");
|
||||
if (make_uppercase(readName(ctx)) != "ELDEF")
|
||||
THROW("Expected ELDEF");
|
||||
skipWhitespace(ctx);
|
||||
std::string elname_postfix = readName(ctx);
|
||||
ASSERT(elname_postfix != "_", "please don't");
|
||||
if (elname_postfix == "_")
|
||||
THROW("Can't use _ as element name");
|
||||
std::string fullname = elname_postfix == "main" ? filename : filename + "." + elname_postfix;
|
||||
ASSERT(result.count(fullname) == 0, "Element " + fullname + " has been already defined");
|
||||
if (result.count(fullname) != 0)
|
||||
THROW("Element " + fullname + " has been already defined");
|
||||
Element& newborn = result[fullname];
|
||||
arg_name_list_t arglist;
|
||||
while (true) {
|
||||
@ -540,9 +560,11 @@ namespace nytl {
|
||||
newborn.arguments.push_back(parse_type(ctx));
|
||||
skipWhitespace(ctx);
|
||||
std::string argname = readName(ctx);
|
||||
ASSERT(!argname.empty(), "Expected argument name");
|
||||
if (argname.empty())
|
||||
THROW("Expected argument name");
|
||||
if (argname != "_") {
|
||||
ASSERT(arglist.count(argname) == 0, "Repeated argument (" + argname + ")");
|
||||
if (arglist.count(argname) != 0)
|
||||
THROW("Repeated argument (" + argname + ")");
|
||||
size_t k = arglist.size();
|
||||
arglist[argname] = k;
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ namespace nytl {
|
||||
const std::function<std::string(std::string)> &escape) {
|
||||
if (!returned)
|
||||
if (elem_ns.count(name) != 1)
|
||||
THROW("No such element");
|
||||
THROW("No such element (" + name + ")");
|
||||
const Element& el = elem_ns.at(name);
|
||||
if (!returned) {
|
||||
/* Continue to do checks */
|
||||
@ -227,7 +227,9 @@ namespace nytl {
|
||||
// If not json is expected, element must be expected
|
||||
assert(el.arguments[i].isArray());
|
||||
ASSERT(!passed_args[i].is_json, "Expected element element arguemnt, got json");
|
||||
ASSERT(elem_ns.count(passed_args[i].EL_name), "No such element, can't compare signatures of argument value");
|
||||
const std::string& passed_el_as_arg = passed_args[i].EL_name;
|
||||
if (elem_ns.count(passed_el_as_arg) != 1)
|
||||
THROW("No such element, can't compare signatures of argument value (" + passed_el_as_arg + ")");
|
||||
const Element& arg_element = elem_ns.at(passed_args[i].EL_name);
|
||||
// ASSERT(passed_args);
|
||||
if(el.arguments[i].asArray() != arg_element.arguments)
|
||||
|
@ -8,7 +8,7 @@ namespace iu9cawebchat {
|
||||
SqliteStatement my_membership_changes(conn,
|
||||
"SELECT `chatId`, `role` FROM `user_chat_membership` WHERE `userId` = ?1 "
|
||||
"AND `user_chatList_IncHistoryId` > ?2", {{1, userId}, {2, LocalHistoryId}});
|
||||
json::jarr myChats = chatListUpdResp["myChats"].asArray();
|
||||
json::jarr& myChats = chatListUpdResp["myChats"].asArray();
|
||||
while (true) {
|
||||
fsql_integer_or_null ev_chatId, usersRoleHere;
|
||||
int status = sqlite_stmt_step(my_membership_changes, {{0, &ev_chatId}, {1, &usersRoleHere}}, {});
|
||||
@ -73,7 +73,7 @@ namespace iu9cawebchat {
|
||||
json::jarr members;
|
||||
|
||||
SqliteStatement membership_changes(conn,
|
||||
"SELECT `userId`, `role`, FROM `user_chat_membership` WHERE `chatId` = ?1 "
|
||||
"SELECT `userId`, `role` FROM `user_chat_membership` WHERE `chatId` = ?1 "
|
||||
"AND `chat_IncHistoryId` > ?2", {{1, chatId}, {2, LocalHistoryId}}, {});
|
||||
while (true) {
|
||||
fsql_integer_or_null alienUserId;
|
||||
|
@ -7,8 +7,10 @@ namespace iu9cawebchat {
|
||||
std::string when_page_chat(WorkerGuestData& wgd, const json::JSON& config_presentation,
|
||||
const een9::ClientRequest& req, const json::JSON& userinfo) {
|
||||
|
||||
std::vector<std::string> path_segs = {""};
|
||||
std::vector<std::string> path_segs = {};
|
||||
path_segs.reserve(4);
|
||||
if (req.uri_path.empty() || req.uri_path[0] != '/')
|
||||
return page_E404(wgd);
|
||||
for (char ch: req.uri_path) {
|
||||
if (ch == '/')
|
||||
path_segs.emplace_back();
|
||||
@ -31,16 +33,18 @@ namespace iu9cawebchat {
|
||||
return page_E404(wgd);
|
||||
} else
|
||||
return page_E404(wgd);
|
||||
|
||||
bool chat_members = (path_segs[0] == "chat-members");
|
||||
|
||||
if (userinfo.isNull())
|
||||
return een9::form_http_server_response_303("/");
|
||||
|
||||
RowChat_Content chatInfo;
|
||||
try {
|
||||
chatInfo = lookup_chat_content_by_nickname(*wgd.db, chat_nickname);
|
||||
} catch (const std::exception& e) {
|
||||
return page_E404(wgd);
|
||||
}
|
||||
if (get_role_of_user_in_chat(*wgd.db, userinfo["id"].asInteger().get_int(), chatInfo.id) == user_chat_role_deleted) {
|
||||
if (get_role_of_user_in_chat(*wgd.db, userinfo["uid"].asInteger().get_int(), chatInfo.id) == user_chat_role_deleted) {
|
||||
return page_E404(wgd);
|
||||
}
|
||||
|
||||
@ -52,7 +56,7 @@ namespace iu9cawebchat {
|
||||
openedchat["selectedMessageId"].asInteger() = json::Integer(selected_message_id);
|
||||
json::JSON initial_chatUpdResp = poll_update_chat_ONE_MSG_resp(*wgd.db, chatInfo.id, selected_message_id);
|
||||
if (chat_members)
|
||||
return http_R200("chat", wgd, {&config_presentation, &userinfo, &openedchat, &initial_chatUpdResp});
|
||||
return http_R200("chat-members", wgd, {&config_presentation, &userinfo, &openedchat, &initial_chatUpdResp});
|
||||
return http_R200("chat", wgd, {&config_presentation, &userinfo, &openedchat, &initial_chatUpdResp});
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ namespace iu9cawebchat {
|
||||
}
|
||||
json::JSON initial_chatListUpdResp = poll_update_chat_list_resp(*wgd.db,
|
||||
userinfo["uid"].asInteger().get_int(), 0);
|
||||
printf("%s\n", json::generate_str(initial_chatListUpdResp, json::print_pretty).c_str());
|
||||
return http_R200("list-rooms", wgd, {&config_presentation, &userinfo, &initial_chatListUpdResp});
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,10 @@ namespace iu9cawebchat {
|
||||
if (cmp.first == "password")
|
||||
password = cmp.second;
|
||||
}
|
||||
een9_ASSERT(check_nickname(nickname), "/login/accpet-data rejected impossible nickname");
|
||||
een9_ASSERT(check_password(password), "/login/accpet-data rejected impossible password");
|
||||
if (!check_nickname(nickname))
|
||||
een9_THROW("/login/accpet-data rejected impossible nickname");
|
||||
if (!check_password(password))
|
||||
een9_THROW("/login/accpet-data rejected impossible password");
|
||||
uid = find_user_by_credentials(*wgd.db, nickname, password);
|
||||
|
||||
} catch(const std::exception& e){}
|
||||
|
@ -39,6 +39,8 @@ namespace iu9cawebchat {
|
||||
|
||||
std::string when_page_user(WorkerGuestData& wgd, const json::JSON& config_presentation,
|
||||
const een9::ClientRequest& req, const std::vector<LoginCookie>& login_cookies, const json::JSON& userinfo) {
|
||||
if (userinfo.isNull())
|
||||
return een9::form_http_server_response_303("/");
|
||||
SqliteConnection& conn = *wgd.db;
|
||||
if (!is_page_of_certain_user(req.uri_path))
|
||||
return page_E404(wgd);
|
||||
@ -104,7 +106,7 @@ namespace iu9cawebchat {
|
||||
json::JSON msg_list = jsonify_html_message_list({{"",
|
||||
config_presentation["phr"]["decl"]["incorrect-profile-data"].asString()}});
|
||||
json::JSON alien_userprofile = user_row_to_userprofile_obj(conn, alien);
|
||||
return http_R200("edit-profile", wgd, {&config_presentation, &alien_userprofile, &msg_list});
|
||||
return http_R200("edit-profile", wgd, {&config_presentation, &userinfo, &alien_userprofile, &msg_list});
|
||||
}
|
||||
return een9::form_http_server_response_303_spec_head("/user/" + alien_nickname, response_hlines);
|
||||
}
|
||||
@ -112,9 +114,9 @@ namespace iu9cawebchat {
|
||||
json::JSON alien_userprofile = user_row_to_userprofile_obj(conn, alien);
|
||||
if (can_edit) {
|
||||
json::JSON empty_msg_list = jsonify_html_message_list({});
|
||||
return http_R200("edit-profile", wgd, {&config_presentation, &alien_userprofile, &empty_msg_list});
|
||||
return http_R200("edit-profile", wgd, {&config_presentation, &userinfo, &alien_userprofile, &empty_msg_list});
|
||||
}
|
||||
return http_R200("view-profile", wgd, {&config_presentation, &alien_userprofile});
|
||||
return http_R200("view-profile", wgd, {&config_presentation, &userinfo, &alien_userprofile});
|
||||
}
|
||||
een9_THROW("Bad method");
|
||||
}
|
||||
|
@ -36,7 +36,8 @@ int main(int argc, char** argv){
|
||||
iu9cawebchat::run_website(config);
|
||||
} else
|
||||
een9_THROW("unknown action (known are 'run', 'initialize')");
|
||||
} catch (std::exception& e) {
|
||||
// todo: put back execption after debug
|
||||
} catch (std::bad_weak_ptr& e) {
|
||||
printf("System failure\n%s\n", e.what());
|
||||
}
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user