Added UI for group options

Added custom checkbox list for selecting users in group options
Added buttons to invoke group options
Hover on the 'more-options' (3-dot) button in the top-right corner to view group options
Note : group options will only be displayed when user is either creator or admin of respective group
This commit is contained in:
sairajzero 2019-09-13 01:15:49 +05:30
parent 2cdca59c6f
commit ebd532b608
3 changed files with 375 additions and 151 deletions

View File

@ -322,7 +322,7 @@ function userDataStartUp() {
}
});
document.getElementById("searchContact").addEventListener("input", searchContact, true);
document.getElementById("searchList").addEventListener("input", searchChecklist, true);
getDatafromAPI().then(result => {
console.log(result);
getContactsfromIDB().then(result => {
@ -1012,11 +1012,12 @@ function checkStatusInterval() {
function changeReceiver(param) {
if (receiverID !== undefined)
document.getElementById(receiverID).style.display = 'none';
console.log(param.getAttribute("name"));
//console.log(param.getAttribute("name"));
receiverID = param.getAttribute("name");
document.getElementById('recipient-floID').innerHTML = receiverID;
receiverStatus(false)
document.getElementById(receiverID).style.display = 'block';
document.getElementById("groupOptions").style.display = 'none';
if (receiverID in contacts) {
msgType = 'direct';
@ -1051,6 +1052,21 @@ function changeReceiver(param) {
if (receiverWebSocket !== undefined && receiverWebSocket.readyState === WebSocket.OPEN)
receiverWebSocket.close()
receiverWebSocket = undefined;
if (selfID == groups[receiverID].creator) {
var grpOpt = document.getElementById("groupOptions");
grpOpt.style.display = 'block';
var optList = grpOpt.querySelectorAll('li');
for (var i = 0; i < optList.length; i++)
optList[i].style.display = 'block';
} else if (groups[receiverID].admins.includes(selfID)) {
var grpOpt = document.getElementById("groupOptions");
grpOpt.style.display = 'block';
var optList = grpOpt.querySelectorAll('li');
for (var i = 0; i < 2; i++)
optList[i].style.display = 'block';
for (var i = 2; i < optList.length; i++)
optList[i].style.display = 'none';
}
}
}
@ -1291,27 +1307,29 @@ function deleteGroupFromIDB(groupID) {
}
function createGroup() {
var members = prompt("Enter Members FLO_ID : ");
var grpName = prompt("Enter Group Name : ");
var grpInfo = floOpt.genNewIDpair();
grpInfo.name = grpName;
grpInfo.members = members.split(',');
grpInfo.creator = selfID;
grpInfo.admins = [];
var grpInfoStr = JSON.stringify(grpInfo);
console.log(grpInfoStr);
var data = {
from: selfID,
newGroup: {
sign: floOpt.signData(grpInfoStr, privKey)
customCheckList(Object.keys(contacts), [selfID], 'Create Group', 'success').then(result => {
var grpInfo = floOpt.genNewIDpair();
grpInfo.name = result.grpName;
grpInfo.members = result.members;
grpInfo.members.push(selfID)
grpInfo.creator = selfID;
grpInfo.admins = [];
var grpInfoStr = JSON.stringify(grpInfo);
console.log(grpInfoStr);
var data = {
from: selfID,
newGroup: {
sign: floOpt.signData(grpInfoStr, privKey)
}
}
}
grpInfo.members.forEach(floID => {
data.to = floID;
data.newGroup.groupInfo = floOpt.encryptData(grpInfoStr, contacts[floID].pubKey),
sendData(floID, JSON.stringify(data));
});
grpInfo.members.forEach(floID => {
data.to = floID;
data.newGroup.groupInfo = floOpt.encryptData(grpInfoStr, contacts[floID].pubKey),
sendData(floID, JSON.stringify(data));
});
}).catch(error => {
console.log(error);
})
}
function deleteGroup() {
@ -1332,113 +1350,125 @@ function deleteGroup() {
}
function addGroupMembers() {
var newMembers = prompt("Enter new Members : ");
newMembers = newMembers.split(',');
var data1 = {
from: selfID,
addGroupMembers: {
group: receiverID,
members: newMembers,
sign: floOpt.signData('addGroupMembers:' + receiverID + newMembers.join('|'), privKey)
customCheckList(Object.keys(contacts), groups[receiverID].members, 'Add Members', 'success').then(result => {
var newMembers = result.members;
var data1 = {
from: selfID,
addGroupMembers: {
group: receiverID,
members: newMembers,
sign: floOpt.signData('addGroupMembers:' + receiverID + newMembers.join('|'), privKey)
}
}
}
groups[receiverID].members.forEach(floID => {
if (floID == selfID) //dont send to self
return;
data1.to = floID;
sendData(floID, JSON.stringify(data1));
});
groups[receiverID].members = groups[receiverID].members.concat(newMembers);
var grpInfoStr = JSON.stringify(groups[receiverID]);
console.log(grpInfoStr);
var data2 = {
from: selfID,
newGroup: {
sign: floOpt.signData(grpInfoStr, privKey)
groups[receiverID].members.forEach(floID => {
if (floID == selfID) //dont send to self
return;
data1.to = floID;
sendData(floID, JSON.stringify(data1));
});
groups[receiverID].members = groups[receiverID].members.concat(newMembers);
var grpInfoStr = JSON.stringify(groups[receiverID]);
console.log(grpInfoStr);
var data2 = {
from: selfID,
newGroup: {
sign: floOpt.signData(grpInfoStr, privKey)
}
}
}
newMembers.forEach(floID => {
data2.to = floID;
data2.newGroup.groupInfo = floOpt.encryptData(grpInfoStr, contacts[floID].pubKey),
sendData(floID, JSON.stringify(data2));
});
storeGroup(grpInfoStr, receiverID);
newMembers.forEach(floID => {
data2.to = floID;
data2.newGroup.groupInfo = floOpt.encryptData(grpInfoStr, contacts[floID].pubKey),
sendData(floID, JSON.stringify(data2));
});
storeGroup(grpInfoStr, receiverID);
}).catch(error => {
console.log(error);
})
}
function rmGroupMembers() {
var rmMembers = prompt("Enter Members to remove : ");
rmMembers = rmMembers.split(',');
var data1 = {
from: selfID,
rmGroupMembers: {
group: receiverID,
members: rmMembers,
sign: floOpt.signData('rmGroupMembers:' + receiverID + rmMembers.join('|'), privKey)
customCheckList(groups[receiverID].members, [], 'Remove Members', 'danger').then(result => {
var rmMembers = result.members;
var data1 = {
from: selfID,
rmGroupMembers: {
group: receiverID,
members: rmMembers,
sign: floOpt.signData('rmGroupMembers:' + receiverID + rmMembers.join('|'), privKey)
}
}
}
groups[receiverID].members = groups[receiverID].members.filter(x => !rmMembers.includes(x)); //remove member from group
storeGroup(JSON.stringify(groups[receiverID]), receiverID);
groups[receiverID].members.forEach(floID => {
if (floID == selfID)
return;
data1.to = floID;
sendData(floID, JSON.stringify(data1));
});
var data2 = {
from: selfID,
deleteGroup: {
group: receiverID,
sign: floOpt.signData('deleteGroup:' + receiverID, privKey)
}
};
rmMembers.forEach(floID => {
data2.to = floID;
sendData(floID, JSON.stringify(data2));
});
groups[receiverID].members = groups[receiverID].members.filter(x => !rmMembers.includes(x)); //remove member from group
storeGroup(JSON.stringify(groups[receiverID]), receiverID);
groups[receiverID].members.forEach(floID => {
if (floID == selfID)
return;
data1.to = floID;
sendData(floID, JSON.stringify(data1));
});
var data2 = {
from: selfID,
deleteGroup: {
group: receiverID,
sign: floOpt.signData('deleteGroup:' + receiverID, privKey)
}
};
rmMembers.forEach(floID => {
data2.to = floID;
sendData(floID, JSON.stringify(data2));
});
}).catch(error => {
console.log(error);
})
}
function addGroupAdmins() {
var newAdmins = prompt("Enter new Admins : ");
newAdmins = newAdmins.split(',');
var data = {
from: selfID,
addGroupAdmins: {
group: receiverID,
admins: newAdmins,
sign: floOpt.signData('addGroupAdmins:' + receiverID + newAdmins.join('|'), privKey)
customCheckList(groups[receiverID].members, groups[receiverID].admins, 'Add Admins', 'success').then(result => {
var newAdmins = result.members;
var data = {
from: selfID,
addGroupAdmins: {
group: receiverID,
admins: newAdmins,
sign: floOpt.signData('addGroupAdmins:' + receiverID + newAdmins.join('|'), privKey)
}
}
}
groups[receiverID].members.forEach(floID => {
if (floID == selfID) //dont send to self
return;
data.to = floID;
sendData(floID, JSON.stringify(data));
});
groups[receiverID].admins = groups[receiverID].admins.concat(newAdmins);
var grpInfoStr = JSON.stringify(groups[receiverID]);
storeGroup(grpInfoStr, receiverID);
groups[receiverID].members.forEach(floID => {
if (floID == selfID) //dont send to self
return;
data.to = floID;
sendData(floID, JSON.stringify(data));
});
groups[receiverID].admins = groups[receiverID].admins.concat(newAdmins);
var grpInfoStr = JSON.stringify(groups[receiverID]);
storeGroup(grpInfoStr, receiverID);
}).catch(error => {
console.log(error);
})
}
function rmGroupAdmins() {
var rmAdmins = prompt("Enter rmAdmins: ");
rmAdmins = rmAdmins.split(',');
var data = {
from: selfID,
rmGroupAdmins: {
group: receiverID,
admins: rmAdmins,
sign: floOpt.signData('rmGroupAdmins:' + receiverID + rmAdmins.join('|'), privKey)
customCheckList(groups[receiverID].admins, [], 'Remove Admins', 'danger').then(result => {
var rmAdmins = result.members;
var data = {
from: selfID,
rmGroupAdmins: {
group: receiverID,
admins: rmAdmins,
sign: floOpt.signData('rmGroupAdmins:' + receiverID + rmAdmins.join('|'), privKey)
}
}
}
groups[receiverID].members.forEach(floID => {
if (floID == selfID) //dont send to self
return;
data.to = floID;
sendData(floID, JSON.stringify(data));
});
groups[receiverID].admins = groups[receiverID].admins.filter(x => !rmAdmins.includes(x)); //remove admins
var grpInfoStr = JSON.stringify(groups[receiverID]);
storeGroup(grpInfoStr, receiverID);
groups[receiverID].members.forEach(floID => {
if (floID == selfID) //dont send to self
return;
data.to = floID;
sendData(floID, JSON.stringify(data));
});
groups[receiverID].admins = groups[receiverID].admins.filter(x => !rmAdmins.includes(x)); //remove admins
var grpInfoStr = JSON.stringify(groups[receiverID]);
storeGroup(grpInfoStr, receiverID);
}).catch(error => {
console.log(error);
})
}
function searchContact() {
@ -1459,3 +1489,76 @@ function searchContact() {
console.log(e);
}
}
function customCheckList(userList, ignoreList, okBtnVal = "Ok", okBtnType = "success") {
var dialog = document.getElementById('overlay');
dialog.style.display = "block";
var okButton = dialog.querySelector('button.ok');
var cancelButton = dialog.querySelector('button.cancel');
okButton.setAttribute("class", `ok btn btn-${okBtnType}`);
okButton.innerHTML = okBtnVal;
var grpNameInput = dialog.querySelector('input.grpName')
grpNameInput.style.display = (okBtnVal === "Create Group" ? "block" : "none");
grpNameInput.value = '';
var userChecklist = document.getElementById('userChecklist');
for (var i = 0; i < userList.length; i++) {
if (ignoreList.includes(userList[i]))
continue;
var listEl = document.createElement('label');
listEl.setAttribute('class', "btn btn-default listLabel");
listEl.setAttribute('name', userList[i]);
listEl.innerHTML = `
<span>${contacts[userList[i]].name}<br/>
<sub>@${userList[i]}</sub>
</span>
<input type="checkbox" class="badgebox" value="${userList[i]}">
<span class="badge">&check;</span>`;
userChecklist.appendChild(listEl);
}
return new Promise((resolve, reject) => {
dialog.addEventListener('click', function handleButtonClicks(e) {
if (e.target.tagName !== 'BUTTON') {
return;
}
dialog.removeEventListener('click', handleButtonClicks);
dialog.style.display = 'none';
if (e.target === okButton) {
var selectedList = [];
var checklist = dialog.querySelectorAll('input.badgebox');
for (var i = 0; i < checklist.length; i++)
if (checklist[i].checked)
selectedList.push(checklist[i].value);
if (selectedList.length == 0)
reject('User Didnt select Any Users!');
else
resolve({
grpName: grpNameInput.value,
members: selectedList
});
} else if (e.target === cancelButton) {
reject('User cancelled!');
} else {
reject('Some other button was clicked!');
}
});
});
}
function searchChecklist() {
try {
var searchKey = this.value;
if (!searchKey)
var searchResults = Object.keys(contacts);
else
var searchResults = searchIndex.search(searchKey);
var checklist = document.getElementById('userChecklist').children;
for (var i = 0; i < checklist.length; i++) {
if (searchResults.includes(checklist[i].getAttribute("name")))
checklist[i].style.display = 'block';
else
checklist[i].style.display = 'none';
};
} catch (e) {
console.log(e);
}
}

View File

@ -15,7 +15,25 @@
</head>
<body onload = "userDataStartUp();">
<body onload="userDataStartUp();">
<div id="overlay">
<div class="userChecklist-container">
<input type="text" class="grpName form-control" placeholder="Group Name">
<div class="row searchBox">
<div class="col-sm-12 searchBox-inner">
<div class="form-group has-feedback">
<input id="searchList" type="text" class="form-control" placeholder="Search">
<span class="glyphicon glyphicon-search form-control-feedback"></span>
</div>
</div>
</div>
<div id="userChecklist"></div>
<button class="ok btn btn-success">Ok</button>
<button class="cancel btn btn-default">Cancel</button>
</div>
</div>
<div class="container app">
<div class="row app-one">
@ -30,10 +48,10 @@
</div>
-->
<div class="col-sm-2 col-xs-2 heading-compose pull-right">
<div class="col-sm-2 col-xs-2 heading-compose pull-right">
<i class="fa fa-comments fa-2x pull-right" aria-hidden="true" onclick="createGroup();"></i>
</div>
<br/>
<br />
<span class="name-meta"><i>created by Ranchimall</i></span>
</div>
@ -63,14 +81,20 @@
<!-- Heading -->
<div class="row heading">
<div class="col-sm-8 col-xs-8 heading-name">
<span class="heading-name-meta"><span id="recipient-status">O</span> &nbsp;&nbsp;<span id="recipient-floID">Select Contact</span>
<span class="heading-name-meta"><span id="recipient-status">O</span> &nbsp;&nbsp;<span
id="recipient-floID">Select Contact</span>
</span>
</div>
<!--
<div class="col-sm-1 col-xs-1 heading-dot pull-right">
<div class="col-sm-1 col-xs-1 heading-dot pull-right dropdown" id="groupOptions">
<i class="fa fa-ellipsis-v fa-2x pull-right" aria-hidden="true"></i>
<div class="dropdown-content">
<li onclick="addGroupMembers()">Add Members</li>
<li onclick="rmGroupMembers()">Remove Members</li>
<li onclick="addGroupAdmins()">Add Admins</li>
<li onclick="rmGroupAdmins()">Remove Admins</li>
<li onclick="deleteGroup()">Delete Group</li>
</div>
</div>
-->
</div>
<!-- Heading End -->
@ -87,14 +111,15 @@
</div>
-->
<div class="col-sm-9 col-xs-9 reply-main">
<input class="form-control" rows="1" id="sendMsgInput" placeholder="Type message" autocomplete="off" ></input>
<input class="form-control" rows="1" id="sendMsgInput" placeholder="Type message"
autocomplete="off"></input>
</div>
<!--
<div class="col-sm-1 col-xs-1 reply-recording">
<i class="fa fa-microphone fa-2x" aria-hidden="true"></i>
</div>
-->
<div class="col-sm-1 col-xs-1 reply-send" onclick = "sendMsg()">
<div class="col-sm-1 col-xs-1 reply-send" onclick="sendMsg()">
<i class="fa fa-send fa-2x" aria-hidden="true"></i>
</div>
</div>

View File

@ -43,6 +43,7 @@ body {
margin: 0 !important;
height: 100%;
}
.side-one {
padding: 0;
margin: 0;
@ -68,7 +69,6 @@ body {
}
.heading {
padding: 10px 16px 10px 15px;
margin: 0 !important;
@ -107,19 +107,21 @@ body {
display: block;
}
#recipient-status{
#recipient-status {
border-radius: 50%;
background: none;
height: 25px;
width: 25px;
color:white;
color: white;
}
.heading-online {
display: none;
padding: 0 5px;
font-size: 12px;
color: #93918f;
}
.heading-compose {
padding: 0;
}
@ -157,7 +159,6 @@ body {
background-color: #fbfbfb;
}
/*#searchBox-inner input {
box-shadow: none;
}*/
@ -244,6 +245,7 @@ body {
position: relative;
left: -100%;
}
.newMessage-heading {
padding: 10px 16px 10px 15px !important;
margin: 0 !important;
@ -268,6 +270,7 @@ body {
font-weight: 700;
padding: 10px 5px !important;
}
.newMessage-back {
text-align: center;
vertical-align: baseline;
@ -275,6 +278,7 @@ body {
display: block;
cursor: pointer;
}
.newMessage-back i {
margin: auto !important;
}
@ -328,25 +332,9 @@ body {
border: 1px solid #f7f7f7;
height: calc(100% - 120px);
}
.message-inner{
overflow-y: auto;
}
.message-previous {
margin : 0 !important;
padding: 0 !important;
height: auto;
width: 100%;
}
.previous {
font-size: 15px;
text-align: center;
padding: 10px !important;
cursor: pointer;
}
.previous a {
text-decoration: none;
font-weight: 700;
.message-inner {
overflow-y: auto;
}
.message-body {
@ -372,7 +360,7 @@ body {
.message-text {
margin: 0 !important;
padding: 5px !important;
word-wrap:break-word;
word-wrap: break-word;
font-weight: 200;
font-size: 14px;
padding-bottom: 0 !important;
@ -386,7 +374,6 @@ body {
text-align: right;
color: #9a9a9a;
height: auto;
}
.receiver {
@ -399,7 +386,6 @@ body {
word-wrap: break-word;
display: inline-block;
height: auto;
}
.sender {
@ -414,7 +400,6 @@ body {
word-wrap: break-word;
}
/*Reply*/
.reply {
@ -488,66 +473,84 @@ body {
top: 0;
height: 100%;
}
.heading {
height: 70px;
background-color: #009688;
}
.fa-2x {
font-size: 2.3em !important;
}
.heading-avatar {
padding: 0 !important;
}
.heading-avatar-icon img {
height: 50px;
width: 50px;
}
.heading-compose {
padding: 5px !important;
}
.heading-compose i {
color: #fff;
cursor: pointer;
}
.heading-dot {
padding: 5px !important;
margin-left: 10px !important;
}
.heading-dot i {
color: #fff;
cursor: pointer;
}
.sideBar {
height: calc(100% - 130px);
}
.sideBar-body {
height: 80px;
}
.sideBar-avatar {
text-align: left;
padding: 0 8px !important;
}
.avatar-icon img {
height: 55px;
width: 55px;
}
.sideBar-main {
padding: 0 !important;
}
.sideBar-main .row {
padding: 0 !important;
margin: 0 !important;
}
.sideBar-name {
padding: 10px 5px !important;
}
.name-meta {
font-size: 16px;
padding: 5% !important;
}
.sideBar-time {
padding: 10px !important;
}
.time-meta {
text-align: right;
font-size: 14px;
@ -555,6 +558,7 @@ body {
color: rgba(0, 0, 0, .4);
vertical-align: baseline;
}
/*Conversation*/
.conversation {
padding: 0 !important;
@ -564,38 +568,130 @@ body {
border-left: 1px solid rgba(0, 0, 0, .08);
/*overflow-y: auto;*/
}
.message {
height: calc(100% - 140px);
}
.reply {
height: 70px;
}
.reply-emojis {
padding: 5px 0 !important;
}
.reply-emojis i {
padding: 5px 2px !important;
font-size: 1.8em !important;
}
.reply-main {
padding: 2px 8px !important;
}
.reply-main input {
padding: 8px !important;
font-size: 18px;
}
.reply-recording {
padding: 5px 0 !important;
}
.reply-recording i {
padding: 5px 0 !important;
font-size: 1.8em !important;
}
.reply-send {
padding: 5px 0 !important;
}
.reply-send i {
padding: 5px 2px 5px 0 !important;
font-size: 1.8em !important;
}
}
.badgebox {
opacity: 0;
}
.badgebox+.badge {
height: 14px;
width: 20px;
font-size: 0px;
padding: 2px;
float: right;
}
.badgebox:focus+.badge {
box-shadow: inset 0px 0px 3px;
}
.badgebox:checked+.badge {
font-size: inherit;
}
.listLabel {
margin: 5px;
text-align: left;
line-height: 50%;
padding: 10px;
display: block;
}
#overlay {
width: 100%;
height: 100%;
text-align: center;
position: fixed;
top: 0;
z-index: 2;
background-color: rgba(0, 0, 0, .5);
display: none;
}
.userChecklist-container {
margin-top: 25px;
width: 300px;
height: 400px;
background-color: #eee;
display: inline-block;
}
#userChecklist {
height: 275px;
overflow-y: auto;
}
.dropdown-content {
display: none;
position: absolute;
min-width: 150px;
z-index: 1;
cursor: pointer;
margin-left: -75px;
}
.dropdown-content li {
color: rgb(95, 95, 95);
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: right;
background-color: #ddd;
}
.dropdown-content li:hover {
background-color: #aaa;
}
.dropdown:hover .dropdown-content {
display: block;
}
#groupOptions {
display: none;
}