ComunicWeb/assets/js/components/sidebar/main.js

709 lines
15 KiB
JavaScript
Raw Normal View History

2019-05-11 14:43:55 +00:00
/**
* Sidebar main script file
*
* @author Pierre HUBERT
*/
2020-04-09 07:15:04 +00:00
const SidebarMain = {
2019-05-11 14:43:55 +00:00
show: function() {
if(byId("main-sidebar")) return;
var sideBar = createElem2({
appendTo: byId("wrapper"),
type: "aside",
2019-05-16 13:48:50 +00:00
class: "main-sidebar",
id: "main-sidebar",
2019-05-11 14:43:55 +00:00
});
var section = createElem2({
appendTo: sideBar,
type: "section",
class: "sidebar"
});
// User panel
var userPanel = createElem2({
appendTo: section,
type: "div",
2019-05-16 15:38:10 +00:00
class: "user-panel hidden-xs"
2019-05-11 14:43:55 +00:00
});
getUserInfo(userID(), function(info){
if(info.error)
return userPanel.innerHTML = "Error!";
// User account image
createElem2({
appendTo: userPanel,
type: "div",
class: "pull-left image cursor-pointer",
2019-05-16 13:48:50 +00:00
onclick: () => openUserPage(info),
2019-05-11 14:43:55 +00:00
children: [
createElem2({
type: "img",
class: "img-circle",
src: info.accountImage
})
],
});
// User name
createElem2({
appendTo: userPanel,
type: "div",
class: "pull-left info",
children: [
createElem2({
type: "p",
class: "cursor-pointer",
innerHTML: userFullName(info),
onclick: () => openUserPage(info),
2019-05-11 14:43:55 +00:00
}),
createElem2({
type: "a",
innerHTML: "Settings",
internalHref: "settings",
}),
]
});
});
2019-05-11 15:03:09 +00:00
// Search form
this.addSearchForm(section);
2019-05-16 13:48:50 +00:00
// User memberships
2020-04-09 10:02:46 +00:00
/*createElem2({
2019-05-16 15:38:10 +00:00
appendTo: section,
type: "div",
class: "intermediate-label hide-on-collapse",
innerHTML: "FRIENDS & GROUPS"
2020-04-09 10:02:46 +00:00
});*/
2019-05-16 13:48:50 +00:00
let userMemberships = createElem2({
appendTo: section,
2019-05-16 15:38:10 +00:00
type: "div",
class: "memberships-list"
2019-05-16 13:48:50 +00:00
});
this.refreshMemberships(userMemberships);
2021-04-05 14:35:43 +00:00
let interval = setInterval(() => {
2019-05-16 16:49:00 +00:00
if(userMemberships.isConnected)
this.refreshMemberships(userMemberships);
else
clearInterval(interval);
2021-04-05 14:35:43 +00:00
}, 15000);
2019-05-16 15:38:10 +00:00
2019-05-16 16:49:00 +00:00
/*// Recent conversations
2019-05-16 15:38:10 +00:00
createElem2({
appendTo: section,
type: "div",
class: "intermediate-label hide-on-collapse",
innerHTML: "CONVERSATIONS"
});
let conversationsList = createElem2({
appendTo: section,
type: "ul",
class: "sidebar-menu recents-conversations-list hide-on-collapse",
innerHTML: "<li><a>TO COME</a></li>"
2019-05-16 16:49:00 +00:00
});*/
2019-05-16 15:38:10 +00:00
2019-05-16 13:48:50 +00:00
},
// **************************************
// Search
// **************************************
/**
* Add search form to sidebar
*
* @param {HTMLElement} target The target for the search form
*/
addSearchForm: function(target) {
// Search input
/**
* @type {HTMLInputElement}
*/
let searchInput = createElem2({
type: "input",
class: "form-control",
elemType: "text",
id: "sidebarSearchInput",
placeholder: "Search...",
});
let searchForm = createElem2({
appendTo: target,
type: "form",
class: "sidebar-form",
children: [
createElem2({
type: "div",
class: "input-group",
children: [
searchInput,
createElem2({
type: "span",
class: "input-group-btn",
innerHTML: '<button type="submit" name="search" id="search-btn" class="btn btn-flat"><i class="fa fa-search"></i></button>',
}),
]
})
]
});
// Search results target
let searchResults = createElem2({
appendTo: searchForm,
type: "div",
class: "sidebar-search-results"
});
searchResults.style.display = "none";
searchInput.addEventListener("keyup", e => {
//Update UI
searchResults.style.display
= searchInput.value.length < 2 ? "none" : "unset";
if(searchInput.value.length < 2)
return;
// Perform the search on the server
ComunicWeb.components.search.interface.global(searchInput.value, results => {
if(results.error) return;
//Get information about related groups and users
getMultipleUsersInfo(ComunicWeb.components.search.utils.getUsersId(results), usersInfo => {
if(usersInfo.error) return;
getInfoMultipleGroups(ComunicWeb.components.search.utils.getGroupsId(results), groupsInfo => {
if(groupsInfo.error) return;
this.applySearchResults(searchResults, results, usersInfo, groupsInfo);
});
});
});
})
searchForm.addEventListener("submit", e => {
e.preventDefault();
openPage("search?q=" + searchForm.getElementsByTagName("input")[0].value);
});
},
/**
* Put search form back to its initial state
*/
resetSearchFrom: function(){
byId("sidebarSearchInput").value = "";
document.querySelector(".sidebar-search-results").style.display = "none";
},
/**
* Apply search results
*
* @param {HTMLElement} target
* @param {Array} results
* @param {*} users
* @param {*} groups
*/
applySearchResults: function(target, results, users, groups) {
emptyElem(target);
let resultsTarget = createElem2({
appendTo: target,
type: "div",
class: "results-container"
});
results.forEach(el => {
if(el.kind == "user")
this.applyUserResult(resultsTarget, users["user-" + el.id]);
else
this.applyGroupResult(resultsTarget, groups[el.id]);
});
$(resultsTarget).slimScroll({
height: '100%'
});
},
applyUserResult: function(target, user) {
createElem2({
appendTo: target,
type: "div",
children: [
createElem2({
type: "img",
class: "img-circle",
src: user.accountImage
}),
createElem2({
type: "span",
innerHTML: userFullName(user)
}),
],
onclick: () => {
openUserPage(user);
this.resetSearchFrom();
}
});
},
applyGroupResult: function(target, group) {
createElem2({
appendTo: target,
type: "div",
children: [
createElem2({
type: "img",
src: group.icon_url
}),
createElem2({
type: "span",
innerHTML: group.name
}),
],
onclick: () => {
openGroupPage(group);
this.resetSearchFrom();
}
});
},
// **************************************
// Memberships
// **************************************
2019-05-16 13:48:50 +00:00
/**
* Refresh user memberships
*
* @param {HTMLElement} target
*/
refreshMemberships: function(target){
2021-03-05 14:26:45 +00:00
WebAppInterface.getMemberships(
2019-05-16 13:48:50 +00:00
() => notify("Could not refresh your memberships!", "error"),
(m, u, g, c) => {
this.applyMemberships(target, m, u, g, c)
}
2019-05-16 13:48:50 +00:00
);
},
/**
* Apply memberships
*
* @param {HTMLElement} target
2021-03-05 14:26:45 +00:00
* @param {UserMembership[]} memberships
* @param {UsersList} users
2019-05-16 13:48:50 +00:00
* @param {*} groups
2020-04-09 06:57:22 +00:00
* @param {Map<number, String>} convs
2019-05-16 13:48:50 +00:00
*/
2020-04-09 06:45:03 +00:00
applyMemberships: function(target, memberships, users, groups, convs) {
2019-05-16 13:48:50 +00:00
2021-03-05 14:26:45 +00:00
// Empty list
2019-05-16 13:48:50 +00:00
target.innerHTML = "";
2019-05-16 15:38:10 +00:00
let friendsTarget = createElem2({
appendTo: target,
type: "ul",
class: "sidebar-menu"
});
2019-05-16 13:48:50 +00:00
memberships.forEach(e => {
if(e.type == "friend")
2020-04-09 06:45:03 +00:00
this.applyFriend(friendsTarget, e.friend, users.get(e.friend.ID_friend));
2019-05-16 13:48:50 +00:00
if(e.type == "group")
{
const groupConversations = memberships
.filter(el => el.type == "conversation" && el.conv.group_id == e.id)
.map(e => e.conv);
this.applyGroup(friendsTarget, groups.get(e.id), groupConversations, e.last_activity);
}
2020-04-09 06:57:22 +00:00
if(e.type == "conversation")
2021-03-05 14:26:45 +00:00
this.applyConversation(friendsTarget, e.conv, convs.get(e.conv.id));
2019-05-16 15:38:10 +00:00
});
2019-05-16 16:56:45 +00:00
createElem2({
appendTo: friendsTarget,
type: "li",
innerHTML: "<div style='height: 50px'></div>",
});
2021-04-05 14:35:43 +00:00
$.AdminLTE.layout.fixSidebar();
/*$(friendsTarget).slimscroll({
2019-05-16 15:38:10 +00:00
flex: 2,
height: "100%"
2021-04-05 14:35:43 +00:00
});*/
2020-04-09 07:19:03 +00:00
// Highlight active element
SidebarMain.refreshActiveElement()
2019-05-16 13:48:50 +00:00
},
/**
* Apply a friend object
*
* @param {HTMLElement} target
* @param {*} friend
* @param {User} user
2019-05-16 13:48:50 +00:00
*/
applyFriend: function(target, friend, user) {
let li = createElem2({
appendTo: target,
type: "li"
});
2020-04-09 07:19:03 +00:00
li.setAttribute("data-membership-user-id", user.id)
if(user.hasVirtualDirectory)
li.setAttribute("data-membership-dir", user.virtualDirectory)
2019-05-16 13:48:50 +00:00
let a = createElem2({
appendTo: li,
onclick: () => openUserPage(user),
type: "a"
});
// User icon
createElem2({
appendTo: a,
type: "img",
class: "img-circle",
2020-04-09 06:45:03 +00:00
src: user.image
2019-05-16 13:48:50 +00:00
});
// User name
createElem2({
appendTo: a,
type: "span",
innerHTML: userFullName(user)
});
// Private conversation
createElem2({
appendTo: a,
type: "span",
class: "pull-right-container",
innerHTML: "<small class='label pull-right'><i class='fa fa-comments'></i></small>",
onclick: (e) => {
e.stopImmediatePropagation();
2020-04-09 07:15:04 +00:00
ComunicWeb.components.conversations.manager.openPrivate(user.id);
}
});
// Supplementary information
let subInfoEl = createElem2({
appendTo: a,
type: "div",
class: "subinfo",
2019-05-16 16:49:00 +00:00
onclick: friend.accepted != 1 ? (e) => e.stopImmediatePropagation() : undefined
});
// Check if friendship request has been accepted or not
if(friend.accepted == 1) {
if(ComunicWeb.common.date.time() - friend.time_last_activity < 30)
subInfoEl.innerHTML = "<span style='color: green;'>Online</span>";
else
subInfoEl.innerHTML = timeDiffToStr(friend.time_last_activity);
}
else {
const respondRequest = function(accept) {
// Update UI
subInfoEl.innerHTML = accept ? lang("friends_bar_accepted")
: lang("friends_bar_rejected");
if(!accept) li.remove();
// Perform the request the server
ComunicWeb.components.friends.list.respondRequest(friend.ID_friend, accept);
}
// Offer the user to accept or reject the invitation
createElem2({
appendTo: subInfoEl,
type: "span",
class: "btn btn-success btn-xs",
innerHTML: "<i class='fa fa-check'></i>",
onclick: (e) => respondRequest(true)
});
add_space(subInfoEl);
createElem2({
appendTo: subInfoEl,
type: "span",
class: "btn btn-danger btn-xs",
innerHTML: "<i class='fa fa-close'></i>",
onclick: (e) => respondRequest(false)
});
}
2019-05-16 13:48:50 +00:00
},
/**
* Apply group information
*
* @param {HTMLElement} target
* @param {Group} group
* @param {Conversation[]} conversations Group conversations
2019-05-16 13:48:50 +00:00
* @param {*} lastactive
*/
applyGroup: function(target, group, conversations, lastactive) {
2019-05-16 13:48:50 +00:00
let li = createElem2({
appendTo: target,
type: "li"
});
2020-04-09 07:19:03 +00:00
li.setAttribute("data-membership-group-id", group.id)
2019-05-16 13:48:50 +00:00
if(group.hasVirtualDirectory)
li.setAttribute("data-membership-dir", group.virtual_directory)
2019-05-16 13:48:50 +00:00
let a = createElem2({
appendTo: li,
type: "a",
onclick: () => openGroupPage(group)
});
// Group icon
createElem2({
appendTo: a,
type: "img",
src: group.icon_url
});
// Group name
createElem2({
appendTo: a,
type: "span",
innerHTML: group.name
});
2019-05-16 16:05:21 +00:00
let subInfoEl = createElem2({
appendTo: a,
type: "div",
class: "subinfo",
2019-05-16 16:49:00 +00:00
//onclick: (e) => e.stopImmediatePropagation()
2019-05-16 16:05:21 +00:00
});
if(group.membership == "pending") {
// Show requested state
subInfoEl.innerHTML = "Requested";
}
else if(group.membership == "invited") {
// Show invited state
subInfoEl.innerHTML = "<i class='fa fa-question'></i> Invited ";
const respondRequest = (accept) => {
GroupsInterface.respondInvitation(group.id, accept);
subInfoEl.innerHTML = accept ? tr("Accepted") : tr("Rejected");
};
// Offer the user to accept or reject the invitation
createElem2({
appendTo: subInfoEl,
type: "span",
class: "btn btn-success btn-xs",
innerHTML: "<i class='fa fa-check'></i>",
onclick: (e) => respondRequest(true)
});
add_space(subInfoEl);
createElem2({
appendTo: subInfoEl,
type: "span",
class: "btn btn-danger btn-xs",
innerHTML: "<i class='fa fa-close'></i>",
onclick: (e) => respondRequest(false)
});
2019-05-16 16:05:21 +00:00
}
else
{
2019-05-16 16:05:21 +00:00
// Group last activity
subInfoEl.innerHTML = timeDiffToStr(lastactive);
// Group conversations
for(let conv of conversations) {
this.applyConversation(target, conv, conv.name, true)
}
}
2019-05-16 13:48:50 +00:00
},
2020-04-09 06:57:22 +00:00
/**
* Apply a conversation
*
* @param {HTMLElement} target
2021-03-05 14:26:45 +00:00
* @param {Conversation} conv
2020-04-09 06:57:22 +00:00
* @param {String} name
*/
applyConversation: function(target, conv, name, showGroupConversations) {
if (conv.group_id && !showGroupConversations)
return;
2020-04-09 06:57:22 +00:00
let li = createElem2({
appendTo: target,
type: "li",
class: "conversation_memberhsip"
});
2021-03-05 14:26:45 +00:00
li.setAttribute("data-membership-conv-id", conv.id)
2020-04-09 06:57:22 +00:00
if (conv.group_id)
li.classList.add("group-conversation")
2020-04-09 10:02:46 +00:00
// Check for unread messages
2021-03-05 16:55:26 +00:00
if(conv.last_activity > conv.members.find(m => m.user_id == userID()).last_access) {
2020-04-09 10:02:46 +00:00
li.classList.add("has-unread-msg");
}
2020-04-09 06:57:22 +00:00
let a = createElem2({
appendTo: li,
type: "a",
onclick: () => {
if (!conv.group_id)
openConversation(conv.id, true)
else
Page.openPage("groups/" + conv.group_id + "/conversation/" + conv.id);
}
2020-04-09 06:57:22 +00:00
});
// Icon
2021-03-07 14:35:50 +00:00
if (conv.logo == null)
createElem2({
appendTo: a,
type: "i",
class: "fa fa-comments"
});
else
createElem2({
appendTo: a,
type: "img",
src: conv.logo
});
2020-04-09 06:57:22 +00:00
// Conversation name
createElem2({
appendTo: a,
type: "span",
innerHTML: name
});
let subInfoEl = createElem2({
appendTo: a,
type: "div",
class: "subinfo",
2021-03-05 14:26:45 +00:00
innerHTML: timeDiffToStr(conv.last_activity)
2020-04-09 06:57:22 +00:00
});
2020-04-13 12:51:22 +00:00
// Check if there is an ongoing call on the conversation
if(conv.has_call_now) {
li.classList.add("with-call");
let callLi = createElem2({
appendTo: target,
type: "li",
class: "call_notice group-conversation"
2020-04-13 12:51:22 +00:00
});
let a = createElem2({
appendTo: callLi,
type: "a",
onclick: () => CallsController.Open(conv),
innerHTML: "<i class='fa fa-phone'></i> <span>Ongoing call</span>"
});
}
2020-04-09 07:15:04 +00:00
},
/**
* Refresh currently active element in the sidebar
*/
refreshActiveElement: function() {
// Search for target
const list = document.querySelector(".memberships-list");
if(!list)
return;
// Remove previously active element (if any)
const activeElem = list.querySelector("li.active");
if(activeElem)
activeElem.classList.remove("active")
// Check for target element
const currPage = ComunicWeb.common.url.getCurrentWebsiteURL();
let query = false;
2020-04-09 07:19:03 +00:00
// Friends
if(currPage.startsWith("user/"))
query = "[data-membership-user-id=\""+currPage.split("/")[1].split("#")[0]+"\"]"
// Groups
else if(currPage.startsWith("groups/"))
2020-04-09 07:19:03 +00:00
query = "[data-membership-group-id=\""+currPage.split("/")[1].split("#")[0]+"\"]"
2020-04-09 07:15:04 +00:00
// Conversations
else if(currPage.startsWith("conversations/"))
2020-04-09 07:15:04 +00:00
query = "[data-membership-conv-id=\""+currPage.split("/")[1].split("#")[0]+"\"]"
// Search by virtual directory
else {
query = "[data-membership-dir=\""+currPage.split("/")[0].split("?")[0].split("#")[0]+"\"]";
}
2020-04-09 07:15:04 +00:00
// Query element
const target = list.querySelector(query);
if(target)
target.classList.add("active");
},
}
ComunicWeb.components.sideBar.main = SidebarMain
// Register to page change events (to refresh active element)
document.addEventListener("openPage", (e) => {
SidebarMain.refreshActiveElement()
})