Переделана страница профиля, добавлена страница просмотра чужого профиля, страница настроек чата
This commit is contained in:
parent
29e06059d5
commit
24e11e0d3d
61
assets/HypertextPages/chat-members.nytl.html
Normal file
61
assets/HypertextPages/chat-members.nytl.html
Normal file
@ -0,0 +1,61 @@
|
||||
{% ELDEF main JSON pres JSON userinfo JSON openedchat JSON initial_chatUpdResp %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" type="image/png" href="/assets/img/favicon.png">
|
||||
<link rel="stylesheet" href="/assets/css/common.css">
|
||||
<link rel="stylesheet" href="/assets/css/common-popup.css">
|
||||
<link rel="stylesheet" href="/assets/css/chat-members.css">
|
||||
<title>{%w pres.chat-members.members-of %} {%w openedchat.name %}</title>
|
||||
</head>
|
||||
<body>
|
||||
{% PUT chat.pass pres userinfo openedchat initial_chatUpdResp %}
|
||||
|
||||
<div id="user-summoning-win" class="popup-window">
|
||||
<h1 class="popup-window-msg">{%w pres.chat-members.summon-label-nickname %}</h1>
|
||||
<input class="one-line-input" id="summoned-user-nickname">
|
||||
<input type="checkbox" id="summoned-user-is-read-only">
|
||||
<label>{%w pres.chat-members.summon-label-ro %}</label><br>
|
||||
<button class="popup-window-btn-yes" id="user-summoning-yes">{%w pres.chat-members.yes-summon %}</button>
|
||||
<button class="popup-window-btn-no" id="user-summoning-no">{%w pres.chat-members.no-summon %}</button>
|
||||
</div>
|
||||
|
||||
<div id="user-deletion-win" class="popup-window">
|
||||
<!-- header will actually be rewritten before showing the window to include user nickname -->
|
||||
<h1 id="user-deletion-win-title" class="popup-window-msg"> ||||||||| </h1>
|
||||
<button class="popup-window-btn-yes" id="user-deletion-yes">{%w pres.chat-members.yes-kick %}</button>
|
||||
<button class="popup-window-btn-no" id="user-deletion-no">{%w pres.chat-members.no-kick %}</button>
|
||||
</div>
|
||||
|
||||
<div class="document-container resp-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/{% W 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">
|
||||
{%w pres.chat-members.members-list-of %} {% W openedchat.name %} ({% W openedchat.nickname %})
|
||||
</p>
|
||||
<a href="/chat/{% W openedchat.nickname %}" id="go-to-chat-settings" class="panel-thing">
|
||||
<img alt="Back to chat" src="/assets/img/return.svg" width="32px">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="dynamic-block-list">
|
||||
<img id="CM-btn-add" class="button-add centered-block-el" alt="New chat" src="/assets/img/add.svg">
|
||||
<div class="dynamic-block-list-el-container" id="CM-list">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/assets/js/common.js"></script>
|
||||
<script src="/assets/js/common-popup.js"></script>
|
||||
<script src="/assets/js/chat-members.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
{% ENDELDEF %}
|
@ -1,46 +0,0 @@
|
||||
{% ELDEF main JSON pres JSON userinfo %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/css/chatSettings.css">
|
||||
<title>Настройки комнаты</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="chat-settings-container">
|
||||
<div class="chat-settings-container-header">
|
||||
<input class="room-name" id="room-name" placeholder="Введите название комнаты..." value="Название комнаты">
|
||||
<button class="changeName" onclick="handleChangeName()">Изменить название</button>
|
||||
</div>
|
||||
<div class="chat-settings-container-body">
|
||||
<ul id="chat-settings-container-body">
|
||||
<!-- Пример списка участников -->
|
||||
<li id="member-1">Участник 1<button class="remove-member-button" onclick="handleRemoveMember(1)">Удалить</button></li>
|
||||
<li id="member-2">Участник 2<button class="remove-member-button" onclick="handleRemoveMember(2)">Удалить</button></li>
|
||||
<li id="member-3">Участник 3<button class="remove-member-button" onclick="handleRemoveMember(3)">Удалить</button></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="chat-settings-container-invite">
|
||||
<button class="invite-member" onclick="openInvite()">Добавить участника</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overlay" id="add_members">
|
||||
<div class="add-members">
|
||||
<div class="add-members-header">
|
||||
<span class="close" onclick="closeAdd()">×</span>
|
||||
<h2>Добавить участников</h2>
|
||||
</div>
|
||||
<div class="add-members-body">
|
||||
<input type="text" id="newMemberLogin" placeholder="Логин пользователя">
|
||||
</div>
|
||||
<div class="add-members-footer">
|
||||
<button class="add-member-button" onclick="handleAddMember()">Добавить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/assets/js/chatSettings.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
{% ENDELDEF%}
|
71
assets/HypertextPages/edit-profile.nytl.html
Normal file
71
assets/HypertextPages/edit-profile.nytl.html
Normal file
@ -0,0 +1,71 @@
|
||||
{% ELDEF main JSON pres JSON userinfo JSON alienprofile JSON errors %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" type="image/png" href="/assets/img/favicon.png">
|
||||
<link rel="stylesheet" href="/assets/css/common.css">
|
||||
<link rel="stylesheet" href="/assets/css/edit-profile.css">
|
||||
<title>{%w pres.edit-profile.header-profile-of %} {%w alienprofile.name %}</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="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/{% W userinfo.nickname %}" id="go-to-my-profile" class="panel-thing">
|
||||
<img alt="Go to my profile" src="/assets/img/user.svg" width="32px">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% FOR error IN errors %}
|
||||
<div class="server-notif-error-msg-box">
|
||||
{% W error.text %}
|
||||
</div>
|
||||
{% ENDFOR %}
|
||||
|
||||
<div class="profile-container">
|
||||
<h2 class="profile-name-text">{% W alienprofile.name %}</h2>
|
||||
<h3 class="profile-nickname-text">{%w pres.edit-profile.directive-nickname %} {% W alienprofile.nickname %}</h3>
|
||||
<p class="profile-bio-text">
|
||||
{% W alienprofile.bio %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="profile-container">
|
||||
<h1 class="wide-centered-header">{%w pres.edit-profile.change-user-attributes %}</h1>
|
||||
<form action = "/user/{% W 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">{%w pres.edit-profile.directive-name %}</label>
|
||||
</td>
|
||||
<td class="logins-input-td2">
|
||||
<input name="name" id="new-name-input" type="text"
|
||||
placeholder="{%w pres.edit-profile.placeholder-name %}" class="one-line-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="logins-input-td1">
|
||||
<label for="new-password-input">{%w pres.edit-profile.directive-password %}</label>
|
||||
</td>
|
||||
<td class="logins-input-td2">
|
||||
<input name="password" id="new-password-input" type="password"
|
||||
placeholder="{%w pres.edit-profile.placeholder-password %}" class="one-line-input">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<label for="input-change-bio">{%w pres.edit-profile.directive-bio %}</label>
|
||||
<br>
|
||||
<textarea name="bio" id="input-change-bio" class="multiline-input"></textarea>
|
||||
<button class="action-button centered-block-el" type="submit">{%w pres.edit-profile.act-submit %}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
{% ENDELDEF%}
|
@ -1,6 +0,0 @@
|
||||
{% ELDEF main JSON pres JSON userinfo %}
|
||||
<script>
|
||||
let pres = {% PUT jsinsert pres %};
|
||||
let userinfo = {% PUT jsinsert userinfo %};
|
||||
</script>
|
||||
{% ENDELDEF %}
|
@ -1,39 +0,0 @@
|
||||
{% ELDEF main JSON pres JSON userinfo %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="/assets/css/profile.css">
|
||||
<title>Профиль</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-container">
|
||||
<div class="profile-header">
|
||||
<h1 style="color: white; text-align: center;">Профиль пользователя</h1>
|
||||
<a class="return" href="chat.nytl.html">Назад</a>
|
||||
</div>
|
||||
<form>
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<img class="avatar" src="/assets/img/empty_avatar.png" id="avatar" height="200" width="200"><br>
|
||||
<input type="file" id="fileInput" style="display:none">
|
||||
<button class="add" type="button" onclick="document.getElementById('fileInput').click();">Изменить фото</button><br>
|
||||
</div>
|
||||
<div class="column">
|
||||
<input type="text" name="username" placeholder = "Имя пользователя" value="Some Name" id="username"><br>
|
||||
<input type="text" name="login" placeholder="Логин" value="some_login123" id="login" readonly><br>
|
||||
</div>
|
||||
</div>
|
||||
<h3 style="color:#007bb5;">О себе</h3>
|
||||
<div class="additional-info">
|
||||
<textarea name="bio" placeholder="Напишите о себе..." id="bio"></textarea>
|
||||
</div>
|
||||
<button class="save" type="submit">Сохранить изменения</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script src="/assets/js/list-rooms.js"> </script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
{% ENDELDEF%}
|
@ -1,27 +0,0 @@
|
||||
{% ELDEF main JSON pres JSON userinfo %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Страница Регистрации</title>
|
||||
<link rel="stylesheet" href="/assets/css/registration.css">
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="form-container">
|
||||
<h1 class="hide-cursor no-select">Вход</h1>
|
||||
<form action="assets/html/list-rooms.html" method="post">
|
||||
<input type="text" name="username" placeholder="Имя пользователя" id="username"><br>
|
||||
<input type="text" name="login" placeholder="Логин" id="login"><br>
|
||||
<input type="password" name="password" placeholder="Пароль" id="password"><br>
|
||||
<button type="submit" class="hide-cursor no-select">Зарегистрироваться</button>
|
||||
<div id="error"></div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script src="assets/js/registration.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
{% ENDELDEF %}
|
36
assets/HypertextPages/view-profile.nytl.html
Normal file
36
assets/HypertextPages/view-profile.nytl.html
Normal file
@ -0,0 +1,36 @@
|
||||
{% ELDEF main JSON pres JSON userinfo JSON alienprofile %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" type="image/png" href="/assets/img/favicon.png">
|
||||
<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>{%w pres.view-profile.header-profile-of %} {%w alienprofile.name %}</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="document-container resp-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/{% W userinfo.nickname %}" id="go-to-my-profile" class="panel-thing">
|
||||
<img alt="Go to my profile" src="/assets/img/user.svg" width="32px">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="profile-container">
|
||||
<h2 class="profile-name-text">{%w alienprofile.name %}</h2>
|
||||
<h3 class="profile-nickname-text">{%w pres.view-profile.directive-nickname%} {%w alienprofile.nickname %}</h3>
|
||||
<p class="profile-bio-text">
|
||||
{%w alienprofile.bio %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
{% ENDELDEF%}
|
33
assets/css/chat-members.css
Normal file
33
assets/css/chat-members.css
Normal file
@ -0,0 +1,33 @@
|
||||
#CM-btn-add {
|
||||
margin-top: 6px;
|
||||
margin-bottom: 4px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.CM-member-box {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.CL-member-box-nickname {
|
||||
margin-left: 8px;
|
||||
justify-self: flex-start;
|
||||
}
|
||||
|
||||
.CM-member-box-name {
|
||||
margin-left: 14px;
|
||||
justify-self: flex-start;
|
||||
}
|
||||
|
||||
.CM-member-box-role {
|
||||
margin-left: auto;
|
||||
justify-self: flex-end;
|
||||
}
|
||||
|
||||
.CM-member-box-leave-btn {
|
||||
margin-left: 10px;
|
||||
margin-right: 8px;
|
||||
justify-self: flex-end;
|
||||
width: 16px;
|
||||
cursor: pointer;
|
||||
}
|
@ -1,163 +0,0 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
background-color: #e5e5e5;
|
||||
}
|
||||
|
||||
.chat-settings-container {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
background-color: white;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-settings-container-header {
|
||||
background-color: #007bb5;
|
||||
color: white;
|
||||
padding: 25px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.room-name {
|
||||
font-size: 24px;
|
||||
width: 80%;
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
border: none;
|
||||
}
|
||||
.changeName {
|
||||
padding: 8px 10px;
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.changeName:hover {
|
||||
background-color: #005f8c;
|
||||
}
|
||||
.chat-settings-container-body {
|
||||
padding: 15px;
|
||||
background-color: #f7f7f7;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#chat-settings-container-body {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#chat-settings-container-body li {
|
||||
margin-bottom: 10px;
|
||||
background-color: white;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.remove-member-button {
|
||||
background-color: red;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.remove-member-button:hover {
|
||||
background-color: darkred;
|
||||
}
|
||||
.chat-settings-container-invite {
|
||||
padding: 15px;
|
||||
background-color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.invite-member {
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.invite-member: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;
|
||||
}
|
||||
|
||||
.add-members {
|
||||
background-color: white;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.add-members-header {
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.add-members-header h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 0;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.add-members-body input {
|
||||
width: 95%;
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
margin-right: 15%;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.add-member-button {
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
background-color: #007bb5;
|
||||
color: white;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.add-member-button:hover {
|
||||
background-color: #005f8c;
|
||||
}
|
50
assets/css/common-popup.css
Normal file
50
assets/css/common-popup.css
Normal file
@ -0,0 +1,50 @@
|
||||
.popup-overlay-veil {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
.popup-window-btn-yes {
|
||||
background-color: #0c7f0e;
|
||||
border-radius: 5px;
|
||||
padding: 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.popup-window-btn-no {
|
||||
background-color: #ff0005;
|
||||
border-radius: 5px;
|
||||
padding: 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.popup-window-msg {
|
||||
padding-left: 20px;
|
||||
font-weight: bold;
|
||||
font-size: 1.3em;
|
||||
}
|
206
assets/css/common.css
Normal file
206
assets/css/common.css
Normal file
@ -0,0 +1,206 @@
|
||||
/* 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;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.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 */
|
||||
}
|
||||
|
||||
@media (orientation: landscape) {
|
||||
.resp-container{
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (orientation: portrait){
|
||||
.resp-container{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
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,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;
|
||||
}
|
20
assets/img/add.svg
Normal file
20
assets/img/add.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="128"
|
||||
height="128"
|
||||
viewBox="0 0 3.84 3.84"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="m 1.9142674,3.7842088 c -0.8814997,0 -1.32224859,0 -1.59609402,-0.2738529 C 0.04432607,3.2365216 0.04432607,2.7957577 0.04432607,1.9142674 c 0,-0.8814997 0,-1.32224859 0.27384731,-1.59609402 C 0.59201881,0.04432607 1.0327677,0.04432607 1.9142674,0.04432607 c 0.8814903,0 1.3222542,0 1.5960885,0.27384731 0.2738529,0.27384543 0.2738529,0.71459432 0.2738529,1.59609402 0,0.8814903 0,1.3222542 -0.2738529,1.5960885 C 3.2365216,3.7842088 2.7957577,3.7842088 1.9142674,3.7842088 Z m 0,-2.5711694 c 0.077453,0 0.1402457,0.062791 0.1402457,0.1402456 v 0.4207368 h 0.4207367 c 0.077453,0 0.1402456,0.062793 0.1402456,0.1402456 0,0.077453 -0.062793,0.1402457 -0.1402456,0.1402457 H 2.0545131 v 0.4207367 c 0,0.077453 -0.062793,0.1402456 -0.1402457,0.1402456 -0.077453,0 -0.1402456,-0.062793 -0.1402456,-0.1402456 V 2.0545131 H 1.353285 c -0.077455,0 -0.1402456,-0.062793 -0.1402456,-0.1402457 0,-0.077453 0.062791,-0.1402456 0.1402456,-0.1402456 H 1.7740218 V 1.353285 c 0,-0.077455 0.062793,-0.1402456 0.1402456,-0.1402456 z"
|
||||
fill="#1c274c"
|
||||
id="path1"
|
||||
style="stroke-width:0.186994" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 81 KiB |
BIN
assets/img/favicon.png
Normal file
BIN
assets/img/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 824 B |
28
assets/img/list-rooms.svg
Normal file
28
assets/img/list-rooms.svg
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
|
||||
<svg
|
||||
width="127.99999"
|
||||
height="127.99999"
|
||||
viewBox="0 0 33.866664 33.866664"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 6.2911505,3.4844006 V 6.6404405 H 3.0362141 V 28.776832 h 4.7418555 v 2.929792 H 0.58956039 V 3.438992 Z"
|
||||
id="path63" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 27.557741,31.386555 v -3.15604 h 3.254937 V 6.0941238 h -4.741856 v -2.929792 h 7.188509 V 31.431963 Z"
|
||||
id="path63-2" />
|
||||
<path
|
||||
id="rect63"
|
||||
style="fill:#fdffff;fill-opacity:1;fill-rule:nonzero;stroke:#e1e1e1;stroke-width:0.529167;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 8.7183307,8.3901854 c -2.467802,0 -4.4545084,1.9867066 -4.4545084,4.4545086 v 5.357812 c 0,2.467802 1.9867064,4.454509 4.4545084,4.454509 0,0 6.6668103,0 10.2365843,0 1.184667,0 1.8523,1.573101 2.973462,1.946651 1.827305,0.608823 5.758305,0.474906 5.758305,0.474906 0,0 -1.204106,-0.984163 -2.336589,-2.042039 -0.307888,-0.287603 -0.182877,-1.488944 0.134028,-1.896921 0.674916,-0.868872 0.918918,-1.680982 0.918918,-2.937106 v -5.357812 c 0,-2.467802 -1.986706,-4.4545086 -4.454508,-4.4545086 z" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
20
assets/img/return.svg
Normal file
20
assets/img/return.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
|
||||
<svg
|
||||
width="128"
|
||||
height="127.99999"
|
||||
viewBox="0 0 33.866667 33.866664"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.294159;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 0.65443061,23.377766 10.20536539,-7.351693 -0.06427,3.749871 c 0,0 6.384296,0.115304 9.607291,0.115304 1.824632,0 4.010317,0.117998 5.361398,-1.065432 0.797635,-0.698657 1.041209,-1.943308 0.954461,-2.97946 -0.118465,-1.414973 -0.417733,-2.830021 -1.492491,-3.799298 -0.964892,-0.870193 -2.338758,-1.449022 -3.659301,-1.465666 -1.347581,-0.01698 -4.311633,-0.01476 -4.311633,-0.01476 l 0.02678,-6.0468658 c 0,0 5.209174,-0.1269759 7.836958,-0.1269759 2.090574,0 3.730335,0.2813604 5.374446,1.5274776 1.165995,0.8837399 2.874757,2.1212447 2.874757,3.8971142 0,3.5737799 -0.03341,6.8479459 -0.03341,10.6502529 0,3.155641 -2.159421,4.126978 -3.036427,4.888332 -1.783594,1.548393 -4.069763,1.553329 -6.468859,1.553329 -4.709142,0 -13.295569,0 -13.295569,0 v 3.244296 z"
|
||||
id="path1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
24
assets/img/user.svg
Normal file
24
assets/img/user.svg
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
|
||||
<svg
|
||||
width="127.99999"
|
||||
height="127.99999"
|
||||
viewBox="0 0 33.866664 33.866664"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#000080;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.465;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="M 9.3745975,32.81176 H 25.632941 c 0,0 0.08996,-6.044498 -0.03778,-10.988966 0.0321,-3.524476 -1.327193,-6.290541 -8.363226,-6.155275 -7.036034,0.135265 -7.7455423,2.805955 -7.7693511,5.331649 -0.034594,3.669826 -0.087981,11.812592 -0.087981,11.812592 z"
|
||||
id="path7" />
|
||||
<path
|
||||
id="path8"
|
||||
style="fill:#000080;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.965;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="M 17.963761,1.3260172 A 11.612947,6.192831 0 0 0 6.3510334,7.5189208 11.612947,6.192831 0 0 0 17.963761,13.711824 11.612947,6.192831 0 0 0 29.576489,7.5189208 11.612947,6.192831 0 0 0 17.963761,1.3260172 Z m -3.947046,2.876827 a 1.5186517,3.4351659 0 0 1 1.518771,3.4349323 1.5186517,3.4351659 0 0 1 -1.518771,3.4354495 1.5186517,3.4351659 0 0 1 -1.518253,-3.4354495 1.5186517,3.4351659 0 0 1 1.518253,-3.4349323 z m 6.47299,0.2160074 a 1.5186517,3.4351659 0 0 1 1.518254,3.4349324 1.5186517,3.4351659 0 0 1 -1.518254,3.435449 1.5186517,3.4351659 0 0 1 -1.51877,-3.435449 1.5186517,3.4351659 0 0 1 1.51877,-3.4349324 z" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
188
assets/js/chat-members.js
Normal file
188
assets/js/chat-members.js
Normal file
@ -0,0 +1,188 @@
|
||||
let LocalHistoryId = 0;
|
||||
|
||||
function genSentBase(){
|
||||
return {
|
||||
'chatUpdReq': {
|
||||
'LocalHistoryId': LocalHistoryId,
|
||||
'chatId': openedchat.id
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let members = new Map();
|
||||
let memberBoxes = new Map();
|
||||
let myRoleHere = null; // Dung local state updates should be updated first
|
||||
|
||||
let userDeletionWinStoredUId = -1;
|
||||
|
||||
function shouldShowDeleteButton(memberSt){
|
||||
return userinfo.uid !== memberSt.userId && myRoleHere === userChatRoleAdmin && memberSt.roleHere !== userChatRoleDeleted;
|
||||
}
|
||||
|
||||
function updateBoxWithSt(box, memberSt){
|
||||
let ID = memberSt.userId;
|
||||
let roleP = box.querySelector(".CM-member-box-role");
|
||||
roleP.innerText = memberSt.roleHere;
|
||||
box.style.backgroundColor = roleToColor(memberSt.roleHere);
|
||||
box.querySelector(".CM-member-box-leave-btn").style.display =
|
||||
(shouldShowDeleteButton(memberSt) ? "block" : "none");
|
||||
}
|
||||
|
||||
function convertMemberStToBox(memberSt){
|
||||
let ID = memberSt.userId;
|
||||
let userProfileURI = "/user/" + memberSt.nickname;
|
||||
|
||||
let box = document.createElement("div");
|
||||
box.className = "dynamic-block-list-el CM-member-box";
|
||||
box.style.backgroundColor = roleToColor(memberSt.roleHere);
|
||||
|
||||
let inBoxNickname = document.createElement("a");
|
||||
box.appendChild(inBoxNickname);
|
||||
inBoxNickname.className = "entity-nickname-txt CM-member-box-nickname";
|
||||
inBoxNickname.innerText = memberSt.nickname;
|
||||
inBoxNickname.href = userProfileURI;
|
||||
|
||||
let inBoxName = document.createElement("a");
|
||||
box.appendChild(inBoxName);
|
||||
inBoxName.className = "entity-reg-field-txt CM-member-box-name";
|
||||
inBoxName.innerText = memberSt.name;
|
||||
inBoxName.href = userProfileURI;
|
||||
|
||||
let inBoxUserRoleHere = document.createElement("p");
|
||||
box.appendChild(inBoxUserRoleHere);
|
||||
inBoxUserRoleHere.className = "entity-reg-field-txt CM-member-box-role";
|
||||
inBoxUserRoleHere.innerText = memberSt.roleHere;
|
||||
|
||||
let inBoxLeaveBtn = document.createElement("img");
|
||||
box.appendChild(inBoxLeaveBtn);
|
||||
inBoxLeaveBtn.className = "CM-member-box-leave-btn";
|
||||
inBoxLeaveBtn.src = "/assets/img/delete.svg";
|
||||
inBoxLeaveBtn.onclick = function (ev) {
|
||||
if (ev.button !== 0)
|
||||
return;
|
||||
userDeletionWinStoredUId = ID;
|
||||
document.getElementById("user-deletion-win-title").innerText =
|
||||
pres['chat-members']['reask-kick-user-X'] + " " + memberSt.nickname + "?";
|
||||
activatePopupWindowById("user-deletion-win");
|
||||
};
|
||||
box.querySelector(".CM-member-box-leave-btn").style.display =
|
||||
(shouldShowDeleteButton(memberSt) ? "block" : "none");
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
function updateLocalStateFromChatUpdResp(chatUpdResp){
|
||||
LocalHistoryId = chatUpdResp.HistoryId;
|
||||
// If my role is updated, we need to update all the boes of already set users (kick button can appear and disappear)
|
||||
let literalMemberList = document.getElementById("CM-list");
|
||||
// We ignore messages and everything related to them. Dang, I really should add an argument to disable message lookup here
|
||||
for (let memberSt of chatUpdResp.members){
|
||||
console.log([memberSt, userinfo.uid, myRoleHere]);
|
||||
if (memberSt.userId === userinfo.uid && myRoleHere !== memberSt.roleHere){
|
||||
myRoleHere = memberSt.roleHere;
|
||||
for (let [id, memberSt] of members){
|
||||
let box = memberBoxes.get(id);
|
||||
updateBoxWithSt(box, memberSt);
|
||||
}
|
||||
document.getElementById("CM-btn-add").style.display =
|
||||
(memberSt.roleHere === userChatRoleAdmin ? "block" : "none");
|
||||
console.log("DEBUG " + (memberSt.roleHere === userChatRoleAdmin ? "block" : "none"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (let memberSt of chatUpdResp.members){
|
||||
let id = memberSt.userId;
|
||||
if (members.has(id)){
|
||||
updateBoxWithSt(memberBoxes.get(id), memberSt);
|
||||
} else {
|
||||
if (memberSt.roleHere !== userChatRoleDeleted){
|
||||
members.set(id, memberSt);
|
||||
let box = convertMemberStToBox(memberSt);
|
||||
memberBoxes.set(id, box);
|
||||
literalMemberList.appendChild(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateLocalStateFromRecv(Recv){
|
||||
updateLocalStateFromChatUpdResp(Recv.chatUpdResp);
|
||||
}
|
||||
|
||||
function configureSummonUserInterface(){
|
||||
document.getElementById("user-summoning-yes").onclick = function(ev ){
|
||||
if (ev.button !==0)
|
||||
return;
|
||||
let nickname = String(document.getElementById("summoned-user-nickname").value);
|
||||
let isReadOnly = document.getElementById("summoned-user-is-read-only").checked;
|
||||
deactivateActivePopup();
|
||||
let Sent = genSentBase();
|
||||
Sent.nickname = nickname;
|
||||
Sent.makeReadOnly = Boolean(isReadOnly);
|
||||
apiRequest("addMemberToChat", Sent).
|
||||
then((Recv) => {
|
||||
updateLocalStateFromRecv(Recv);
|
||||
}).catch((e) => {
|
||||
console.log(e);
|
||||
alert(pres['chat-members']["failed-summon-member"]);
|
||||
});
|
||||
};
|
||||
|
||||
document.getElementById("user-summoning-no").onclick = function (ev) {
|
||||
if (ev.button !== 0)
|
||||
return;
|
||||
deactivateActivePopup();
|
||||
};
|
||||
|
||||
document.getElementById("CM-btn-add").onclick = function(ev) {
|
||||
if (ev.button !== 0)
|
||||
return;
|
||||
document.getElementById("summoned-user-nickname").value = "";
|
||||
// read-only flag persists throughout user summoning sessions, and IT IS NOT A BUG
|
||||
activatePopupWindowById("user-summoning-win");
|
||||
};
|
||||
}
|
||||
|
||||
/* Popup activation button is configured for each box separately */
|
||||
function configureKickUserInterfaceWinPart(){
|
||||
document.getElementById("user-deletion-yes").onclick = function (ev){
|
||||
if (ev.button !== 0)
|
||||
return;
|
||||
deactivateActivePopup();
|
||||
if (userDeletionWinStoredUId < 0)
|
||||
throw new Error("Karaul");
|
||||
let Sent = genSentBase();
|
||||
Sent.userId = userDeletionWinStoredUId;
|
||||
apiRequest("removeMemberFromChat", Sent).
|
||||
then((Recv) => {
|
||||
updateLocalStateFromRecv(Recv);
|
||||
}).catch((e) => {
|
||||
console.log(e);
|
||||
alert(pres['chat-members']["failed-kick-member"]);
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById("user-deletion-no").onclick = function (ev) {
|
||||
if (ev.button !== 0)
|
||||
return;
|
||||
deactivateActivePopup();
|
||||
};
|
||||
}
|
||||
|
||||
__mainloopDelayMS = 5000;
|
||||
__guestMainloopPollerAction = function (){
|
||||
console.log("Hello, world");
|
||||
apiRequest("chatPollEvents", genSentBase()).
|
||||
then((Recv) => {
|
||||
console.log(Recv);
|
||||
updateLocalStateFromRecv(Recv);
|
||||
});
|
||||
}
|
||||
|
||||
window.onload = function(){
|
||||
console.log("Page loaded");
|
||||
configureSummonUserInterface();
|
||||
configureKickUserInterfaceWinPart();
|
||||
updateLocalStateFromChatUpdResp(initial_chatUpdResp);
|
||||
mainloopPoller();
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
const chatId = 123;
|
||||
let localHistoryId = 0;
|
||||
|
||||
function handleChangeName() {
|
||||
const newName = document.getElementById('room-name').value;
|
||||
changeChatName(chatId, localHistoryId, newName).then(() => {
|
||||
});
|
||||
}
|
||||
function handleAddMember() {
|
||||
const login = document.getElementById('newMemberLogin').value;
|
||||
if (login) {
|
||||
addMemberToChat(chatId, localHistoryId, login).then(() => {
|
||||
const list = document.getElementById("chat-settings-container-body");
|
||||
const listItem = document.createElement("li");
|
||||
listItem.textContent = login;
|
||||
list.appendChild(listItem);
|
||||
closeAdd();
|
||||
});
|
||||
}
|
||||
}
|
||||
function handleRemoveMember(userId) {
|
||||
removeMemberFromChat(chatId, localHistoryId, userId).then(() => {
|
||||
const listItem = document.getElementById(`member-${userId}`);
|
||||
if (listItem) {
|
||||
listItem.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
function openInvite() {
|
||||
document.getElementById("add_members").style.display = "flex";
|
||||
}
|
||||
|
||||
function closeAdd() {
|
||||
document.getElementById("add_members").style.display = "none";
|
||||
}
|
||||
|
||||
function updateChat() {
|
||||
pollChatEvents(chatId, localHistoryId).then(() => {
|
||||
});
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
updateChat();
|
||||
});
|
||||
async function changeChatName(chatId, localHistoryId, newName) {
|
||||
try {
|
||||
const response = await fetch('/api/changeChatName', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
chatUpdReq: {
|
||||
chatId: chatId,
|
||||
LocalHistoryId: localHistoryId
|
||||
},
|
||||
content: {
|
||||
name: newName
|
||||
}
|
||||
})
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.status === 0) {
|
||||
console.log('Название комнаты успешно изменено');
|
||||
} else {
|
||||
console.error('Ошибка при изменении названия комнаты:', data.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка сети при изменении названия комнаты:', error);
|
||||
}
|
||||
}
|
||||
async function addMemberToChat(chatId, localHistoryId, nickname) {
|
||||
try {
|
||||
const response = await fetch('/api/addMemberToChat', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
chatUpdReq: {
|
||||
chatId: chatId,
|
||||
LocalHistoryId: localHistoryId
|
||||
},
|
||||
nickname: nickname
|
||||
})
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.status === 0) {
|
||||
console.log('Участник успешно добавлен');
|
||||
} else {
|
||||
console.error('Ошибка при добавлении участника:', data.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка сети при добавлении участника:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function removeMemberFromChat(chatId, localHistoryId, userId) {
|
||||
try {
|
||||
const response = await fetch('/api/removeMemberFromChat', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
chatUpdReq: {
|
||||
chatId: chatId,
|
||||
LocalHistoryId: localHistoryId
|
||||
},
|
||||
userId: userId
|
||||
})
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.status === 0) {
|
||||
console.log('Участник успешно удален');
|
||||
} else {
|
||||
console.error('Ошибка при удалении участника:', data.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка сети при удалении участника:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function pollChatEvents(chatId, localHistoryId) {
|
||||
try {
|
||||
const response = await fetch('/api/chatPollEvents', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
chatUpdReq: {
|
||||
chatId: chatId,
|
||||
LocalHistoryId: localHistoryId
|
||||
}
|
||||
})
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.status === 0) {
|
||||
console.log('События чата успешно обновлены');
|
||||
} else {
|
||||
console.error('Ошибка при обновлении событий чата:', data.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка сети при обновлении событий чата:', error);
|
||||
}
|
||||
}
|
26
assets/js/common-popup.js
Normal file
26
assets/js/common-popup.js
Normal file
@ -0,0 +1,26 @@
|
||||
let activePopupWinId = "";
|
||||
|
||||
function activatePopupWindow__(el){
|
||||
let veil = document.createElement("div");
|
||||
veil.id = "popup-overlay-veil-OBJ"
|
||||
veil.className = "popup-overlay-veil";
|
||||
veil.style.display = "block";
|
||||
document.body.appendChild(veil);
|
||||
el.style.display = "block";
|
||||
}
|
||||
|
||||
function activatePopupWindowById(id){
|
||||
if (activePopupWinId !== "")
|
||||
return;
|
||||
/* Lmao, this thing is just... SO unsafe */
|
||||
activePopupWinId = id;
|
||||
activatePopupWindow__(document.getElementById(id))
|
||||
}
|
||||
|
||||
function deactivateActivePopup(){
|
||||
if (activePopupWinId === "")
|
||||
return
|
||||
document.getElementById("popup-overlay-veil-OBJ").remove();
|
||||
document.getElementById(activePopupWinId).style.display = "none";
|
||||
activePopupWinId = "";
|
||||
}
|
77
assets/js/common.js
Normal file
77
assets/js/common.js
Normal file
@ -0,0 +1,77 @@
|
||||
let dopDopYesYes = (ign) => {};
|
||||
|
||||
function sleep(ms){
|
||||
return new Promise(res => setTimeout(res, ms));
|
||||
}
|
||||
|
||||
async function apiRequest(type, req){
|
||||
let A = await fetch("/api/" + type,
|
||||
{method: 'POST', body: JSON.stringify(req)});
|
||||
let B = await A.json();
|
||||
if (B.status !== 0)
|
||||
throw Error("Server returned non-zero status");
|
||||
return B;
|
||||
}
|
||||
|
||||
/* Framework for pages with mainloop (it can be npt only polling, but also literally anything else */
|
||||
let __mainloopDelayMs = 3000;
|
||||
let mainloopTimeout = null;
|
||||
let __guestMainloopPollerAction = null;
|
||||
function setMainloopTimeout(){
|
||||
if (mainloopTimeout !== null)
|
||||
return;
|
||||
mainloopTimeout = setTimeout(mainloopPoller, __mainloopDelayMs);
|
||||
}
|
||||
function cancelMainloopTimeout(){
|
||||
if (mainloopTimeout === null){
|
||||
console.log("cancelling nothing")
|
||||
return;
|
||||
}
|
||||
clearTimeout(mainloopTimeout);
|
||||
mainloopTimeout = null;
|
||||
}
|
||||
function mainloopPoller(){
|
||||
mainloopTimeout = null;
|
||||
try {
|
||||
if (__guestMainloopPollerAction)
|
||||
__guestMainloopPollerAction();
|
||||
} catch (error){
|
||||
console.log(error)
|
||||
}
|
||||
setMainloopTimeout();
|
||||
}
|
||||
|
||||
// 1
|
||||
const userChatRoleAdmin = "admin";
|
||||
// 2
|
||||
const userChatRoleRegular = "regular";
|
||||
// 3
|
||||
const userChatRoleReadOnly = "read-only";
|
||||
// 4
|
||||
const userChatRoleDeleted = "not-a-member";
|
||||
|
||||
function roleToColor(role) {
|
||||
if (role === userChatRoleAdmin) {
|
||||
return "#aafff3";
|
||||
} else if (role === userChatRoleRegular){
|
||||
return "#ffffff";
|
||||
|
||||
} else if (role === userChatRoleReadOnly){
|
||||
return "#bfb2b2";
|
||||
} else if (role === userChatRoleDeleted) {
|
||||
return "#fb4a4a";
|
||||
}
|
||||
return "#286500" // Bug
|
||||
}
|
||||
|
||||
function hideHTMLElement(el){
|
||||
el.style.display = "none";
|
||||
}
|
||||
|
||||
function showHTMLElement(el){
|
||||
el.style.display = "block";
|
||||
}
|
||||
|
||||
function setElementVisibility(el, isVisible, howVisible = "block"){
|
||||
el.style.display = isVisible ? howVisible : "none";
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
document.getElementById('fileInput').addEventListener('change', function(event) {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
document.getElementById('avatar').src = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue
Block a user