master #6
| @ -5,25 +5,12 @@ | |||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> |     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|     <title>Веб-Чат Members</title> |     <title>Веб-Чат Members</title> | ||||||
|     <link rel="stylesheet" href="/assets/css/chat.css"> |  | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
| {% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %} | {% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %} | ||||||
| <!--TODO: ADD SOMETHING WRITE SOMETHING AAAAAA --> | <!--TODO: ADD SOMETHING WRITE SOMETHING AAAAAA --> | ||||||
| <div class="overlay" id="overlay"> | <h1> Chat member list page for {% WRITE openedchat.nickname%}, not ready yet</h1> | ||||||
|     <div class="members-list" id="members-list"> | <!--<script src="/assets/js/chat-members.js"></script>--> | ||||||
|         <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> |  | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
| {% ENDELDEF %} | {% ENDELDEF %} | ||||||
|  | |||||||
| @ -9,17 +9,36 @@ | |||||||
| 
 | 
 | ||||||
| {% ELDEF main JSON pres JSON userinfo JSON openedchat JSON initial_chatUpdResp %} | {% ELDEF main JSON pres JSON userinfo JSON openedchat JSON initial_chatUpdResp %} | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html lang="ru"> | <html lang="en"> | ||||||
| <head> | <head> | ||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> |     <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"> |     <link rel="stylesheet" href="/assets/css/chat.css"> | ||||||
|  |     <title>Chat </title> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
| {% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %} | <!-- Write the actual chat script --> | ||||||
| <!-- TODO AAAAA--> | <!--% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %--> | ||||||
| <script src="/assets/js/chat.js"></script> | <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> | </body> | ||||||
| </html> | </html> | ||||||
| {% ENDELDEF %} | {% 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> | <!DOCTYPE html> | ||||||
| <html lang="en"> | <html lang="en"> | ||||||
| <head> | <head> | ||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <link rel="stylesheet" href="/assets/css/profile.css"> |     <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/edit-profile.css"> | ||||||
|  |     <title>Edit user Profile</title> | ||||||
| </head> | </head> | ||||||
| <body> | <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 %} |         {% FOR error IN errors %} | ||||||
|             <div> |             <div class="server-notif-error-msg-box"> | ||||||
|                 <p>{% WRITE error.text %}</p> |                 {% WRITE error.text %} | ||||||
|             </div> |             </div> | ||||||
|         {% ENDFOR %} |         {% 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> |         </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> |     </div> | ||||||
|  | 
 | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
| {% ENDELDEF%} | {% ENDELDEF%} | ||||||
|  | |||||||
| @ -4,69 +4,48 @@ | |||||||
| <head> | <head> | ||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> |     <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"> |     <link rel="stylesheet" href="/assets/css/list-rooms.css"> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
| <script> |     <script> | ||||||
|     let pres = {% PUT jsinsert pres %}; |         let pres = {% PUT jsinsert pres %}; | ||||||
|     let userinfo = {% PUT jsinsert userinfo %}; |         let userinfo = {% PUT jsinsert userinfo %}; | ||||||
|     let initial_chatListUpdResp = {% PUT jsinsert initial_chatListUpdResp %}; |         let initial_chatListUpdResp = {% PUT jsinsert initial_chatListUpdResp %}; | ||||||
| </script> |     </script> | ||||||
| <div class="container"> |     <div id="popup-overlay-veil"></div> | ||||||
|     <h1 style="color: white;">Выберите Чат-Комнату</h1> |     <div id="chat-creation-win" class="popup-window"> | ||||||
|     <ul class="room-list"> |         <h1>Input identifying information for your new chat</h1> | ||||||
|         <!-- Здесь будет список комнат --> |     </div> | ||||||
|     </ul> |  | ||||||
|     <button class="create-room-button" onclick="openCreateRoomModal()">Создать Комнату</button> |  | ||||||
| </div> |  | ||||||
| 
 | 
 | ||||||
| <!-- Модальное окно для создания комнаты --> |     <div id="chat-renunciation-win" class="popup-window"> | ||||||
| <!--<div id="createRoomModal" class="modal">--> |         <!-- header will actually be rewritten before showing the window to include chat nickname --> | ||||||
| <!--    <div class="modal-content">--> |         <h1 id="chat-renunciation-win-title">Are you sure you want to leave chat?</h1> | ||||||
| <!--        <div class="modal-header">--> |         <button class="chat-renunciation-win-yes">Yes, leave</button> | ||||||
| <!--            <span class="close" onclick="closeCreateRoomModal()">×</span>--> |         <button class="chat-renunciation-win-no">No, cancel</button> | ||||||
| <!--            <h2>Создать Комнату</h2>--> |     </div> | ||||||
| <!--        </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>--> |  | ||||||
| 
 | 
 | ||||||
| <!--<!– Модальное окно для добавления участников –>--> | x | ||||||
| <!--<div class="overlay" id="add_members">--> |     <div id="document-container"> | ||||||
| <!--    <div class="add-members">--> |         <div id="navigation-panel" class="panel"> | ||||||
| <!--        <div class="add-members-header">--> |             <a href="/user/{% WRITE userinfo.nickname %}" id="go-to-my-profile" class="panel-thing"> | ||||||
| <!--            <span class="close" onclick="closeAdd()">×</span>--> |                 <img alt="Go to my profile" src="/assets/img/user.svg" width="32px"> | ||||||
| <!--            <h2>Добавить участников</h2>--> |             </a> | ||||||
| <!--        </div>--> |             <p class="panel-thing panel-header-txt"> | ||||||
| <!--        <div class="add-members-body">--> |                 List of available rooms | ||||||
| <!--            <input type="text" id="newMemberLogin" placeholder="Логин пользователя">--> |             </p> | ||||||
| <!--        </div>--> |         </div> | ||||||
| <!--        <div class="add-members-footer">--> | 
 | ||||||
| <!--            <button class="add-member-button" onclick="addMember()">Добавить</button>--> |         <div class="dynamic-block-list"> | ||||||
| <!--        </div>--> |             <img id="CL-bacbe" class="button-add centered-block-el" alt="New chat" src="/assets/img/add.svg"> | ||||||
| <!--    </div>--> |             <div class="dynamic-block-list-el-container" id="CL-dblec"> | ||||||
| <!--</div>--> | 
 | ||||||
| <!--<div class="overlay" id="delete-chat">--> |             </div> | ||||||
| <!--    <div class="delete-chat">--> |         </div> | ||||||
| <!--        <div class="delete-chat-header">--> |     </div> | ||||||
| <!--            <span class="delete-close" onclick="closeConfirm()">×</span>--> |     <script src="/assets/js/list-rooms.js"></script> | ||||||
| <!--            <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> |  | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
| {% ENDELDEF %} | {% ENDELDEF %} | ||||||
| @ -1,29 +1,40 @@ | |||||||
| {% ELDEF main JSON pres JSON userinfo JSON errors %} | {% ELDEF main JSON pres JSON userinfo JSON errors %} | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html lang="{% WRITE pres.lang %}"> | <html lang="en"> | ||||||
| <head> | <head> | ||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> |     <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"> |     <link rel="stylesheet" href="/assets/css/login.css"> | ||||||
|  |     <title>Login Page</title> | ||||||
| </head> | </head> | ||||||
| 
 |  | ||||||
| <body> | <body> | ||||||
| {% FOR msg IN errors %} |     {% FOR error IN errors %} | ||||||
|     <div class="error-msg"> |         <div class="server-notif-error-msg-box"> | ||||||
|         {% WRITE msg.text %} |             {% 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> |     </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> | </body> | ||||||
| </html> | </html> | ||||||
|  | |||||||
| @ -1,26 +1,35 @@ | |||||||
| {% ELDEF main JSON pres JSON userprofile %} | {% ELDEF main JSON pres JSON userinfo JSON alienprofile %} | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html lang="en"> | <html lang="en"> | ||||||
| <head> | <head> | ||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <link rel="stylesheet" href="/assets/css/profile.css"> |     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|     <title>Профиль</title> |     <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> | </head> | ||||||
| <body> | <body> | ||||||
|     <div class="main-container"> | 
 | ||||||
|         <div class="profile-header"> |     <div id="document-container"> | ||||||
|             <h1>Профиль пользователя</h1> |         <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> | ||||||
|         <div class="columns"> | 
 | ||||||
|             <div class="column"> |         <div class="profile-container"> | ||||||
|                 <p>{% WRITE userprofile.name %} ( {% WRITE userprofile.nickname %} )</p> |             <h2 class="profile-name-text">{% WRITE alienprofile.name %}</h2> | ||||||
|             </div> |             <h3 class="profile-nickname-text">Nickname: {% WRITE alienprofile.nickname %}</h3> | ||||||
|         </div> |             <p class="profile-bio-text"> | ||||||
|         <div class="additional-info"> |                 {% WRITE alienprofile.bio %} | ||||||
|             <p>О себе</p> |             </p> | ||||||
|             <p>{% WRITE userprofile.bio %}</p><br> |  | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|  | 
 | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|  | 
 | ||||||
| {% ENDELDEF%} | {% 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 { | #navigation-panel { | ||||||
|     font-family: Arial, sans-serif; |     align-items: center; | ||||||
|     background-color: #f0f0f0; |  | ||||||
|     margin: 0; |  | ||||||
|     padding: 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .container { | #CL-bacbe { | ||||||
|     max-width: 800px; |     margin: 6px; | ||||||
|     margin: 30px auto; |  | ||||||
|     padding: 20px; |  | ||||||
|     background-color: #007bff; |  | ||||||
|     box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |  | ||||||
|     border-radius: 8px; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| h1 { | .CL-my-chat-box { | ||||||
|     text-align: center; |  | ||||||
|     color: #fff; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .room-list { |  | ||||||
|     list-style-type: none; |  | ||||||
|     padding: 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .room-item { |  | ||||||
|     display: flex; |     display: flex; | ||||||
|     justify-content: space-between; |     flex-direction: row; | ||||||
|     align-items: center; |  | ||||||
|     padding: 15px; |  | ||||||
|     margin: 10px 0; |  | ||||||
|     background-color: #fafafa; |  | ||||||
|     border: 1px solid #ddd; |  | ||||||
|     border-radius: 5px; |  | ||||||
|     transition: background-color 0.3s ease; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .room-item:hover { | .CL-my-chat-box-nickname { | ||||||
|     background-color: #eaeaea; |     margin-left: 8px; | ||||||
|  |     justify-self: flex-start; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .room-name { | .CL-my-chat-box-name { | ||||||
|     font-size: 18px; |     margin-left: 14px; | ||||||
|     color: #555; |     justify-self: flex-start; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .join-button { | .CL-my-chat-box-my-role { | ||||||
|     padding: 10px 15px; |     margin-left: auto; | ||||||
|     font-size: 16px; |     justify-self: flex-end; | ||||||
|     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; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .modal { | .CL-my-chat-box-leave-btn { | ||||||
|     display: none; |     margin-left: 10px; | ||||||
|     position: fixed; |     margin-right: 8px; | ||||||
|     z-index: 1; |     justify-self: flex-end; | ||||||
|     left: 0; |     width: 16px; | ||||||
|     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; |  | ||||||
|     cursor: pointer; |     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 { | body { | ||||||
|     font-family: Arial, sans-serif; |  | ||||||
|     display: flex; |     display: flex; | ||||||
|  |     flex-direction: column; | ||||||
|     justify-content: center; |     justify-content: center; | ||||||
|     align-items: center; |     align-items: center; | ||||||
|     height: 100vh; |     height: 100vh; /* Full viewport height */ | ||||||
|     margin: 0; |     margin: 0; | ||||||
|     background-color: #e5e5e5; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .form-container { | .form-container { | ||||||
|     width: 100%; |     background-color: #ffffff; /* Brighter box color */ | ||||||
|     max-width: 400px; |     padding: 20px; | ||||||
|     background-color: white; |     border-radius: 10px; | ||||||
|     box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |     box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); | ||||||
|     display: flex; |     width: 50%; /* Set width of the form */ | ||||||
|     flex-direction: column; |  | ||||||
|     border-radius: 8px; |  | ||||||
|     padding: 40px; |  | ||||||
|     text-align: center; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| h1 { | /* The morbid thing */ | ||||||
|     margin-bottom: 20px; | table.logins-input-table { | ||||||
|     color: #2F4F4F; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| input { |  | ||||||
|     width: 100%; |     width: 100%; | ||||||
|     background: #f7f7f7; |     border-collapse: collapse; /* Combine borders */ | ||||||
|     font-size: 16px; |  | ||||||
|     padding: 10px; |  | ||||||
|     border: 1px solid #ddd; |  | ||||||
|     border-radius: 20px; |  | ||||||
|     margin-bottom: 15px; |  | ||||||
|     outline: none; |  | ||||||
| } | } | ||||||
| 
 | .logins-input-td1, .logins-input-td2 { | ||||||
| button { |  | ||||||
|     width: 100%; |  | ||||||
|     padding: 15px; |  | ||||||
|     border: none; |     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; |  | ||||||
| } | } | ||||||
| 
 | .logins-input-td1 { | ||||||
| .error-msg { |     padding-right: 5px; | ||||||
|     color: red; |     white-space: nowrap; /* Prevent text wrap, keeping it in one line */ | ||||||
|     background-color: #ffc0c0; |     overflow: hidden; /* Hide overflow content */ | ||||||
|     border-color: red; |     text-overflow: ellipsis; /* Show ellipsis for overflowing text */ | ||||||
|     border-radius: 5px; | } | ||||||
| } | .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 LocalHistoryId = 0; | ||||||
| let roomToDelete = null; |  | ||||||
| let currentRoom = null; |  | ||||||
| let currentHistoryId = 0; |  | ||||||
| 
 | 
 | ||||||
| function openRoom(currentRoom) { | let myChats = new Map(); | ||||||
|     alert('Вы вошли в комнату: ' + currentRoom); | let chatBoxes = new Map(); | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| function closeAdd() { | const roleDeleted = "not-a-member"; | ||||||
|     document.getElementById('add_members').style.display = 'none'; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| function openAdd() { | function convertStToBox(myMembershipSt){ | ||||||
|     document.getElementById('add_members').style.display = 'flex'; |     let chatURI = "/user/" + myMembershipSt.chatNickname; | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| function openConfirm(roomNickname) { |     let box = document.createElement("div"); | ||||||
|     roomToDelete = roomNickname; |     chatBoxes.set(myMembershipSt.chatId, box); | ||||||
|     document.getElementById("delete-chat").style.display = "flex"; |     box.className = "dynamic-block-list-el CL-my-chat-box"; | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| function closeConfirm() { |     let inBoxNickname = document.createElement("a"); | ||||||
|     roomToDelete = null; |     box.appendChild(inBoxNickname); | ||||||
|     document.getElementById("delete-chat").style.display = "none"; |     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() { |     let inBoxName = document.createElement("a"); | ||||||
|     if (roomToDelete && rooms[roomToDelete]) { |     box.appendChild(inBoxName); | ||||||
|         delete rooms[roomToDelete]; |     inBoxName.className = "entity-reg-field-txt CL-my-chat-box-name"; | ||||||
|         removeRoomFromList(roomToDelete); |     inBoxName.innerText = myMembershipSt.chatName; | ||||||
|         closeConfirm(); |     inBoxName.href = chatURI; | ||||||
|     } else { |  | ||||||
|         alert("Не удалось найти выбранную комнату."); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| function addMember() { |     let inBoxMyRoleHere = document.createElement("p"); | ||||||
|     const login = document.getElementById('newMemberLogin').value; |     box.appendChild(inBoxMyRoleHere); | ||||||
|     if (login) { |     inBoxMyRoleHere.className = "entity-reg-field-txt CL-my-chat-box-my-role"; | ||||||
|         alert(`Участник с никнеймом '${login}' добавлен`); |     inBoxMyRoleHere.innerText = "You are " + myMembershipSt.myRoleHere + " here"; | ||||||
|         closeAdd(); |  | ||||||
|     } else { |  | ||||||
|         alert('Пожалуйста, введите логин участника'); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| function openCreateRoomModal() { |     let ID = myMembershipSt.chatId; | ||||||
|     document.getElementById('createRoomModal').style.display = 'block'; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| function closeCreateRoomModal() { |     let inBoxLeaveBtn = document.createElement("img"); | ||||||
|     document.getElementById('createRoomModal').style.display = 'none'; |     box.appendChild(inBoxLeaveBtn); | ||||||
| } |     inBoxLeaveBtn.className = "CL-my-chat-box-leave-btn"; | ||||||
| 
 |     inBoxLeaveBtn.src = "/assets/img/delete.svg"; | ||||||
| async function createRoom() { |     inBoxLeaveBtn.onclick = function (ev) { | ||||||
|     const errorElement = document.getElementById('error'); |         if (ev.button === 0){ | ||||||
|     const roomName = document.getElementById('newRoomName').value.trim(); |             console.log("Tried to leave chat" + ID); | ||||||
|     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 |  | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     try { |     return box; | ||||||
|         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); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function addRoomToList(roomName) { | window.onload = function () { | ||||||
|     const roomList = document.querySelector('.room-list'); |     console.log("Loading complete"); | ||||||
|     const existingRoomItem = Array.from(roomList.children).find(item => item.querySelector('.room-name').textContent === roomName); |     LocalHistoryId = initial_chatListUpdResp.HistoryId; | ||||||
|     if (existingRoomItem) { |  | ||||||
|         existingRoomItem.remove(); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     const roomItem = document.createElement('li'); |     console.log(initial_chatListUpdResp); | ||||||
|     roomItem.classList.add('room-item'); |  | ||||||
| 
 | 
 | ||||||
|     roomItem.innerHTML = ` |     let literalChatList = document.getElementById("CL-dblec"); | ||||||
|         <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> |  | ||||||
|     `;
 |  | ||||||
| 
 | 
 | ||||||
|     roomList.appendChild(roomItem); |     for (let myMembershipSt of initial_chatListUpdResp.myChats){ | ||||||
| } |         console.log(myMembershipSt); | ||||||
| 
 |         if (myMembershipSt.myRoleHere !== roleDeleted){ | ||||||
| function removeRoomFromList(roomName, roomNickname) { |             myChats.set(myMembershipSt.chatId, myMembershipSt); | ||||||
|     const roomList = document.querySelector('.room-list'); |             let box = convertStToBox(myMembershipSt) | ||||||
|     const roomItem = Array.from(roomList.children).find(item => item.querySelector('.room-name').textContent === roomName); |             chatBoxes.set(myMembershipSt.chatId, box); | ||||||
|     if (roomItem) { |             literalChatList.appendChild(box); | ||||||
|         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; |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return -1; |  | ||||||
| } |  | ||||||
| window.onclick = function(event) { |  | ||||||
|     if (event.target === document.getElementById('createRoomModal')) { |  | ||||||
|         closeCreateRoomModal(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| document.getElementById('newRoomName').addEventListener('keydown', function(event) { |     document.getElementById("CL-bacbe").onclick = function (ev){ | ||||||
|     if (event.key === 'Enter') { |         if (ev.button === 0){ | ||||||
|         createRoom(); | 
 | ||||||
|     } |         } | ||||||
| }); |     }; | ||||||
| document.addEventListener('DOMContentLoaded', initializeRoomList); | }; | ||||||
|  | |||||||
| @ -112,6 +112,10 @@ namespace een9 { | |||||||
|                             return status; |                             return status; | ||||||
|                         } |                         } | ||||||
|                         res.body.reserve(std::min(100000ul, body_size)); |                         res.body.reserve(std::min(100000ul, body_size)); | ||||||
|  |                         if (body_size == 0) { | ||||||
|  |                             status = 1; | ||||||
|  |                         } | ||||||
|  |                         break; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 if (!res.has_body) { |                 if (!res.has_body) { | ||||||
|  | |||||||
| @ -55,13 +55,16 @@ namespace nytl { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     char skip(ParsingContext& ctx) { |     char skip(ParsingContext& ctx) { | ||||||
|         ASSERT(ctx.pos < ctx.text.size(), "Unexpected EOF"); |         if (ctx.pos >= ctx.text.size()) | ||||||
|  |             THROW("Unexpected EOF"); | ||||||
|         return advance(ctx); |         return advance(ctx); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void skip(ParsingContext& ctx, char ch) { |     void skip(ParsingContext& ctx, char ch) { | ||||||
|         ASSERT(ctx.pos < ctx.text.size(), "Unexpected EOF"); |         if (ctx.pos >= ctx.text.size()) | ||||||
|         ASSERT(ctx.text[ctx.pos] == ch, "Unexpected character"); |             THROW("Unexpected EOF"); | ||||||
|  |         if (ctx.text[ctx.pos] != ch) | ||||||
|  |             THROW("Unexpected character"); | ||||||
|         advance(ctx); |         advance(ctx); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -150,7 +153,8 @@ namespace nytl { | |||||||
|     void parse_bare_file(const std::string& filename, const std::string& content, |     void parse_bare_file(const std::string& filename, const std::string& content, | ||||||
|                              global_elem_set_t& result) |                              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); |         std::string txt = clement_lstrip(content); | ||||||
|         rstrip(txt); |         rstrip(txt); | ||||||
|         size_t cut = 9999999999999; |         size_t cut = 9999999999999; | ||||||
| @ -170,13 +174,15 @@ namespace nytl { | |||||||
|         uptr<TPFrame> toMe(bool returned, ParsingContext& ctx) { |         uptr<TPFrame> toMe(bool returned, ParsingContext& ctx) { | ||||||
|             if (!returned) { |             if (!returned) { | ||||||
|                 std::string nm = readName(ctx); |                 std::string nm = readName(ctx); | ||||||
|                 ASSERT(!nm.empty(), "Type specification expected"); |                 if (nm.empty()) | ||||||
|  |                     THROW("Type specification expected"); | ||||||
|                 nm = make_uppercase(nm); |                 nm = make_uppercase(nm); | ||||||
|                 if (nm == "JSON") { |                 if (nm == "JSON") { | ||||||
|                     result = json::JSON(true); |                     result = json::JSON(true); | ||||||
|                     return NULL; |                     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, '('); |                 skip(ctx, '('); | ||||||
|                 result.asArray(); |                 result.asArray(); | ||||||
|                 assert(result.isArray()); |                 assert(result.isArray()); | ||||||
| @ -217,8 +223,10 @@ namespace nytl { | |||||||
|         uptr<EPFrame> toMe(bool returned, ParsingContext& ctx, const arg_name_list_t& local_var_names) { |         uptr<EPFrame> toMe(bool returned, ParsingContext& ctx, const arg_name_list_t& local_var_names) { | ||||||
|             if (!returned) { |             if (!returned) { | ||||||
|                 std::string first = readName(ctx); |                 std::string first = readName(ctx); | ||||||
|                 ASSERT(!first.empty(), "Expression should start with 'root' name of global package or local variable"); |                 if (first.empty()) | ||||||
|                 ASSERT(first != "_", "_ ??? ARE YOU KIDDING???"); |                     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) { |                 if (local_var_names.count(first) == 1) { | ||||||
|                     result["V"].asInteger() = json::Integer((int64_t)local_var_names.at(first)); |                     result["V"].asInteger() = json::Integer((int64_t)local_var_names.at(first)); | ||||||
|                 } else { |                 } else { | ||||||
| @ -243,7 +251,8 @@ namespace nytl { | |||||||
|                     t = readUint(ctx); |                     t = readUint(ctx); | ||||||
|                     if (!t.empty()) { |                     if (!t.empty()) { | ||||||
|                         size_t v = std::stoul(t); |                         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); |                         chain.back() = json::JSON((int64_t)v); | ||||||
|                         continue; |                         continue; | ||||||
|                     } |                     } | ||||||
| @ -352,7 +361,8 @@ namespace nytl { | |||||||
|                 ElementPart::when_for_put_S& P = result.parts.back().when_for_put; |                 ElementPart::when_for_put_S& P = result.parts.back().when_for_put; | ||||||
|                 skipWhitespace(ctx); |                 skipWhitespace(ctx); | ||||||
|                 std::string V1 = readName(ctx); |                 std::string V1 = readName(ctx); | ||||||
|                 ASSERT(!V1.empty(), "Expected variable name"); |                 if (V1.empty()) | ||||||
|  |                     THROW("Expected variable name"); | ||||||
|                 skipWhitespace(ctx); |                 skipWhitespace(ctx); | ||||||
|                 bool have_colon_and_2 = false; |                 bool have_colon_and_2 = false; | ||||||
|                 std::string V2; |                 std::string V2; | ||||||
| @ -364,7 +374,8 @@ namespace nytl { | |||||||
|                     skipWhitespace(ctx); |                     skipWhitespace(ctx); | ||||||
|                 } |                 } | ||||||
|                 op = make_uppercase(readName(ctx)); |                 op = make_uppercase(readName(ctx)); | ||||||
|                 ASSERT(op == "IN", "Expected IN"); |                 if (op != "IN") | ||||||
|  |                     THROW("Expected IN"); | ||||||
|                 skipWhitespace(ctx); |                 skipWhitespace(ctx); | ||||||
|                 P.ref_over = parse_expression(ctx, local_var_names); |                 P.ref_over = parse_expression(ctx, local_var_names); | ||||||
|                 P.internal_element = el_name + ".~" + std::to_string(free_hidden++); |                 P.internal_element = el_name + ".~" + std::to_string(free_hidden++); | ||||||
| @ -372,13 +383,15 @@ namespace nytl { | |||||||
|                 newborn.is_hidden = true; |                 newborn.is_hidden = true; | ||||||
|                 arg_name_list_t local_var_names_of_nxt = local_var_names; |                 arg_name_list_t local_var_names_of_nxt = local_var_names; | ||||||
|                 if (V1 != "_") { |                 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(); |                     size_t k = local_var_names_of_nxt.size(); | ||||||
|                     local_var_names_of_nxt.emplace(V1, k); |                     local_var_names_of_nxt.emplace(V1, k); | ||||||
|                     (have_colon_and_2 ? P.where_key_var : P.where_value_var) = (ssize_t)k; |                     (have_colon_and_2 ? P.where_key_var : P.where_value_var) = (ssize_t)k; | ||||||
|                 } |                 } | ||||||
|                 if (have_colon_and_2 && V2 != "_") { |                 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(); |                     size_t k = local_var_names_of_nxt.size(); | ||||||
|                     local_var_names_of_nxt.emplace(V2, k); |                     local_var_names_of_nxt.emplace(V2, k); | ||||||
|                     P.where_value_var = (ssize_t)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; |                 ElementPart::when_ref_put_S& P = result.parts.back().when_ref_put; | ||||||
|                 skipWhitespace(ctx); |                 skipWhitespace(ctx); | ||||||
|                 std::string Vn = readName(ctx); |                 std::string Vn = readName(ctx); | ||||||
|                 ASSERT(!Vn.empty(), "Expected variable name"); |                 if (Vn.empty() || Vn == "_") | ||||||
|                 ASSERT(Vn != "_", "Are you kidding???"); |                     THROW("REF: expected variable name"); | ||||||
|                 skipWhitespace(ctx); |                 skipWhitespace(ctx); | ||||||
|                 op = make_uppercase(readName(ctx)); |                 op = make_uppercase(readName(ctx)); | ||||||
|                 ASSERT(op == "AS", "Expected AS"); |                 if (op != "AS") | ||||||
|  |                     THROW("Expected AS"); | ||||||
|                 skipWhitespace(ctx); |                 skipWhitespace(ctx); | ||||||
|                 P.ref_over = parse_expression(ctx, local_var_names); |                 P.ref_over = parse_expression(ctx, local_var_names); | ||||||
|                 P.internal_element = el_name + ".~" + std::to_string(free_hidden++); |                 P.internal_element = el_name + ".~" + std::to_string(free_hidden++); | ||||||
| @ -467,13 +481,15 @@ namespace nytl { | |||||||
|                 } |                 } | ||||||
|             }; |             }; | ||||||
|             if (op == "ENDELDEF") { |             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); |                 skip_magic_block_end(ctx, syntax); | ||||||
|                 prepare_to_depart_parts(); |                 prepare_to_depart_parts(); | ||||||
|                 return NULL; |                 return NULL; | ||||||
|             } |             } | ||||||
|             if (op == "ENDFOR") { |             if (op == "ENDFOR") { | ||||||
|                 ASSERT(myself == gone_for_for, "Unexpected end of for cycle"); |                 if (myself != gone_for_for) | ||||||
|  |                     THROW("Unexpected ENDFOR"); | ||||||
|                 skipWhitespace(ctx); |                 skipWhitespace(ctx); | ||||||
|                 /* Here I am using ret_data_int to return info about NOLF(1)/LF(2) decision */ |                 /* 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
 |                 ret_data_int = 2;  // Default is to do LF
 | ||||||
| @ -491,7 +507,8 @@ namespace nytl { | |||||||
|                 return NULL; |                 return NULL; | ||||||
|             } |             } | ||||||
|             if (op == "ENDREF") { |             if (op == "ENDREF") { | ||||||
|                 assert(myself == gone_for_ref); |                 if (myself != gone_for_ref) | ||||||
|  |                     THROW("Unexpected ENDREF"); | ||||||
|                 skip_magic_block_end(ctx, syntax); |                 skip_magic_block_end(ctx, syntax); | ||||||
|                 prepare_to_depart_parts(); |                 prepare_to_depart_parts(); | ||||||
|                 return NULL; |                 return NULL; | ||||||
| @ -525,12 +542,15 @@ namespace nytl { | |||||||
|             if (peep(ctx) == EOFVAL) |             if (peep(ctx) == EOFVAL) | ||||||
|                 break; |                 break; | ||||||
|             skip_magic_block_start(ctx, syntax); |             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); |             skipWhitespace(ctx); | ||||||
|             std::string elname_postfix = readName(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; |             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]; |             Element& newborn = result[fullname]; | ||||||
|             arg_name_list_t arglist; |             arg_name_list_t arglist; | ||||||
|             while (true) { |             while (true) { | ||||||
| @ -540,9 +560,11 @@ namespace nytl { | |||||||
|                 newborn.arguments.push_back(parse_type(ctx)); |                 newborn.arguments.push_back(parse_type(ctx)); | ||||||
|                 skipWhitespace(ctx); |                 skipWhitespace(ctx); | ||||||
|                 std::string argname = readName(ctx); |                 std::string argname = readName(ctx); | ||||||
|                 ASSERT(!argname.empty(), "Expected argument name"); |                 if (argname.empty()) | ||||||
|  |                     THROW("Expected argument name"); | ||||||
|                 if (argname != "_") { |                 if (argname != "_") { | ||||||
|                     ASSERT(arglist.count(argname) == 0, "Repeated argument (" + argname + ")"); |                     if (arglist.count(argname) != 0) | ||||||
|  |                         THROW("Repeated argument (" + argname + ")"); | ||||||
|                     size_t k = arglist.size(); |                     size_t k = arglist.size(); | ||||||
|                     arglist[argname] = k; |                     arglist[argname] = k; | ||||||
|                 } |                 } | ||||||
|  | |||||||
| @ -212,7 +212,7 @@ namespace nytl { | |||||||
|         const std::function<std::string(std::string)> &escape) { |         const std::function<std::string(std::string)> &escape) { | ||||||
|         if (!returned) |         if (!returned) | ||||||
|             if (elem_ns.count(name) != 1) |             if (elem_ns.count(name) != 1) | ||||||
|                 THROW("No such element"); |                 THROW("No such element (" + name + ")"); | ||||||
|         const Element& el = elem_ns.at(name); |         const Element& el = elem_ns.at(name); | ||||||
|         if (!returned) { |         if (!returned) { | ||||||
|             /* Continue to do checks */ |             /* Continue to do checks */ | ||||||
| @ -227,7 +227,9 @@ namespace nytl { | |||||||
|                         // If not json is expected, element must be expected
 |                         // If not json is expected, element must be expected
 | ||||||
|                         assert(el.arguments[i].isArray()); |                         assert(el.arguments[i].isArray()); | ||||||
|                         ASSERT(!passed_args[i].is_json, "Expected element element arguemnt, got json"); |                         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); |                         const Element& arg_element = elem_ns.at(passed_args[i].EL_name); | ||||||
|                         // ASSERT(passed_args);
 |                         // ASSERT(passed_args);
 | ||||||
|                         if(el.arguments[i].asArray() != arg_element.arguments) |                         if(el.arguments[i].asArray() != arg_element.arguments) | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ namespace iu9cawebchat { | |||||||
|         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 " | ||||||
|            "AND `user_chatList_IncHistoryId` > ?2", {{1, userId}, {2, LocalHistoryId}}); |            "AND `user_chatList_IncHistoryId` > ?2", {{1, userId}, {2, LocalHistoryId}}); | ||||||
|         json::jarr myChats = chatListUpdResp["myChats"].asArray(); |         json::jarr& myChats = chatListUpdResp["myChats"].asArray(); | ||||||
|         while (true) { |         while (true) { | ||||||
|             fsql_integer_or_null ev_chatId, usersRoleHere; |             fsql_integer_or_null ev_chatId, usersRoleHere; | ||||||
|             int status = sqlite_stmt_step(my_membership_changes, {{0, &ev_chatId}, {1, &usersRoleHere}}, {}); |             int status = sqlite_stmt_step(my_membership_changes, {{0, &ev_chatId}, {1, &usersRoleHere}}, {}); | ||||||
| @ -73,7 +73,7 @@ namespace iu9cawebchat { | |||||||
|         json::jarr members; |         json::jarr members; | ||||||
| 
 | 
 | ||||||
|         SqliteStatement membership_changes(conn, |         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}}, {}); |                    "AND `chat_IncHistoryId` > ?2", {{1, chatId}, {2, LocalHistoryId}}, {}); | ||||||
|         while (true) { |         while (true) { | ||||||
|             fsql_integer_or_null alienUserId; |             fsql_integer_or_null alienUserId; | ||||||
|  | |||||||
| @ -7,8 +7,10 @@ namespace iu9cawebchat { | |||||||
|     std::string when_page_chat(WorkerGuestData& wgd, const json::JSON& config_presentation, |     std::string when_page_chat(WorkerGuestData& wgd, const json::JSON& config_presentation, | ||||||
|         const een9::ClientRequest& req, const json::JSON& userinfo) { |         const een9::ClientRequest& req, const json::JSON& userinfo) { | ||||||
| 
 | 
 | ||||||
|         std::vector<std::string> path_segs = {""}; |         std::vector<std::string> path_segs = {}; | ||||||
|         path_segs.reserve(4); |         path_segs.reserve(4); | ||||||
|  |         if (req.uri_path.empty() || req.uri_path[0] != '/') | ||||||
|  |             return page_E404(wgd); | ||||||
|         for (char ch: req.uri_path) { |         for (char ch: req.uri_path) { | ||||||
|             if (ch == '/') |             if (ch == '/') | ||||||
|                 path_segs.emplace_back(); |                 path_segs.emplace_back(); | ||||||
| @ -31,16 +33,18 @@ namespace iu9cawebchat { | |||||||
|             return page_E404(wgd); |             return page_E404(wgd); | ||||||
|         } else |         } else | ||||||
|             return page_E404(wgd); |             return page_E404(wgd); | ||||||
| 
 |  | ||||||
|         bool chat_members = (path_segs[0] == "chat-members"); |         bool chat_members = (path_segs[0] == "chat-members"); | ||||||
| 
 | 
 | ||||||
|  |         if (userinfo.isNull()) | ||||||
|  |             return een9::form_http_server_response_303("/"); | ||||||
|  | 
 | ||||||
|         RowChat_Content chatInfo; |         RowChat_Content chatInfo; | ||||||
|         try { |         try { | ||||||
|             chatInfo = lookup_chat_content_by_nickname(*wgd.db, chat_nickname); |             chatInfo = lookup_chat_content_by_nickname(*wgd.db, chat_nickname); | ||||||
|         } catch (const std::exception& e) { |         } catch (const std::exception& e) { | ||||||
|             return page_E404(wgd); |             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); |             return page_E404(wgd); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -52,7 +56,7 @@ namespace iu9cawebchat { | |||||||
|         openedchat["selectedMessageId"].asInteger() = json::Integer(selected_message_id); |         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); |         json::JSON initial_chatUpdResp = poll_update_chat_ONE_MSG_resp(*wgd.db, chatInfo.id, selected_message_id); | ||||||
|         if (chat_members) |         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}); |         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, |         json::JSON initial_chatListUpdResp = poll_update_chat_list_resp(*wgd.db, | ||||||
|             userinfo["uid"].asInteger().get_int(), 0); |             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}); |         return http_R200("list-rooms", wgd, {&config_presentation, &userinfo, &initial_chatListUpdResp}); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -18,8 +18,10 @@ namespace iu9cawebchat { | |||||||
|                     if (cmp.first == "password") |                     if (cmp.first == "password") | ||||||
|                         password = cmp.second; |                         password = cmp.second; | ||||||
|                 } |                 } | ||||||
|                 een9_ASSERT(check_nickname(nickname), "/login/accpet-data rejected impossible nickname"); |                 if (!check_nickname(nickname)) | ||||||
|                 een9_ASSERT(check_password(password), "/login/accpet-data rejected impossible password"); |                     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); |                 uid = find_user_by_credentials(*wgd.db, nickname, password); | ||||||
| 
 | 
 | ||||||
|             } catch(const std::exception& e){} |             } catch(const std::exception& e){} | ||||||
|  | |||||||
| @ -39,6 +39,8 @@ namespace iu9cawebchat { | |||||||
| 
 | 
 | ||||||
|     std::string when_page_user(WorkerGuestData& wgd, const json::JSON& config_presentation, |     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) { |                 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; |         SqliteConnection& conn = *wgd.db; | ||||||
|         if (!is_page_of_certain_user(req.uri_path)) |         if (!is_page_of_certain_user(req.uri_path)) | ||||||
|             return page_E404(wgd); |             return page_E404(wgd); | ||||||
| @ -104,7 +106,7 @@ namespace iu9cawebchat { | |||||||
|                 json::JSON msg_list = jsonify_html_message_list({{"", |                 json::JSON msg_list = jsonify_html_message_list({{"", | ||||||
|                     config_presentation["phr"]["decl"]["incorrect-profile-data"].asString()}}); |                     config_presentation["phr"]["decl"]["incorrect-profile-data"].asString()}}); | ||||||
|                 json::JSON alien_userprofile = user_row_to_userprofile_obj(conn, alien); |                 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); |             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); |             json::JSON alien_userprofile = user_row_to_userprofile_obj(conn, alien); | ||||||
|             if (can_edit) { |             if (can_edit) { | ||||||
|                 json::JSON empty_msg_list = jsonify_html_message_list({}); |                 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"); |         een9_THROW("Bad method"); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -36,7 +36,8 @@ 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')"); | ||||||
|     } catch (std::exception& e) { |         // todo: put back execption after debug
 | ||||||
|  |     } 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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user