diff --git a/admin/group_list.php b/admin/group_list.php
index cf2385067..963608a24 100644
--- a/admin/group_list.php
+++ b/admin/group_list.php
@@ -386,6 +386,7 @@ $template->assign(
'F_ADD_ACTION' => get_root_url().'admin.php?page=group_list',
'U_HELP' => get_root_url().'admin/popuphelp.php?page=group_list',
'PWG_TOKEN' => get_pwg_token(),
+ 'CACHE_KEYS' => get_admin_client_cache_keys(array('groups', 'users')),
)
);
diff --git a/admin/themes/default/js/group_list.js b/admin/themes/default/js/group_list.js
index e949a89d4..529e1c01a 100644
--- a/admin/themes/default/js/group_list.js
+++ b/admin/themes/default/js/group_list.js
@@ -217,7 +217,6 @@ var setupGroupBox = function (groupBox) {
});
groupBox.find(".group-rename form").on("submit", function (e) {
- console.log("submit");
e.preventDefault();
if (groupBox.find(".group_name-editable").val() != groupBox.find("#group_name").html())
renameGroup(id, groupBox.find(".group_name-editable").val())
@@ -386,7 +385,7 @@ $(function () {
$(".not-in-selection-mode").hide();
$(".GroupManagerButtons").removeClass("visible");
} else {
- $(".in-selection-mode").fadeOut();
+ $(".in-selection-mode").hide();
$(".not-in-selection-mode").removeAttr("style");
$(".Group-checkbox input").attr("checked", false);
$(".Group-checkbox input[type='checkbox']").trigger("change");
@@ -416,8 +415,6 @@ var updateSelectionPanel = function (changedState = "") {
updateStatePanel(changedState)
}
- console.log(state);
-
$(".number-Selected").html(numSelect + "");
};
@@ -500,57 +497,51 @@ $('.ConfirmDeleteButton').on("click", function() {
// Initialize the research user bar
var selectize;
-// List of users
-var usersSearch = [];
+// Initialize the cache
+var usersCache = {};
+
+var usersInGroup = [];
+
+// Max offset of the user container (322 = 6 lines)
+var maxOffsetUserCont = 322;
+
+var infoUsers = $("
")
// Setup the user research bar
$(function() {
// initialize the Selectize control
- $select = $('.AddUserBlock input').selectize({
- delimiter: ',',
- persist: false,
- plugins: ['remove_button']
- });
+ $select = $('.AddUserBlock select').selectize({});
// fetch the instance
selectize = $select[0].selectize;
+
var idSearch = "";
$('.UserSearch input').on("focus", function() {
- // Import users if it is not already done
- if (usersSearch.length == 0) {
- jQuery.ajax({
- url: "ws.php?format=json&method=pwg.users.getList",
- type: "POST",
- data: "",
- success: function (raw_data) {
- data = jQuery.parseJSON(raw_data);
- if (data.stat === "ok") {
- usersSearch = data.result.users;
- updateUserSearch();
- selectize.refreshOptions();
- }
- }
- });
- } else if (idSearch != $("#UserList").attr("data-group_id")) {
+ if (idSearch != $("#UserList").attr("data-group_id")) {
updateUserSearch();
}
});
// Update User search bar (remove group users in selection)
updateUserSearch = function () {
+ selectize.clear();
+ if (usersCache = {}) {
+ usersCache = new UsersCache({
+ serverKey: serverKey,
+ serverId: serverId,
+ rootUrl: rootUrl
+ });
+ }
+ JSON.parse(usersCache.storage[usersCache.key]).data.forEach(function(u){
+ selectize.addOption({value:u.id, text:u.username})
+ })
idSearch = $("#UserList").attr("data-group_id");
- selectize.clearOptions();
- usersSearch.forEach(function(u){
- isInGroup = false;
- $('.UsernameBlock').each(function(){
- if ($(this).data("id")==u.id)
- isInGroup = true;
- })
- if (!isInGroup) {
- selectize.addOption({value:u.id, text:u.username})
- }
+ $('.UsernameBlock').each(function(){
+ selectize.removeOption($(this).data("id"));
})
}
});
@@ -569,18 +560,35 @@ var openUserManager = function(grp_id) {
loadState.reverse();
data = jQuery.parseJSON(raw_data);
if (data.stat === "ok") {
- //Fill with user blocks
- let users = data.result.users;
- $(".UsersInGroupList").html('');
- $(".UserNumberBadge").html(''+users.length);
- users.forEach(u => {
- addUserDisplay(u.username, u.id, grp_id);
- });
+ $(".group-name-block p").html(
+ $("#group-" + grp_id + " #group_name").html() + " / " + str_user_list
+ )
+ $(".UsersInGroupList").html("");
+
+ //Display the popin
$('#UserList').fadeIn();
+
+ //Fill with user blocks
+ usersInGroup = data.result.users;
+ // Sort in alphabetic order
+ usersInGroup.sort(function( a, b ) {
+ if ( a.username.toLowerCase() < b.username.toLowerCase() ){
+ return 1;
+ } else return -1
+ });
+ let i = 0;
+ while ($(".UsersInGroupList").outerHeight() <= maxOffsetUserCont && usersInGroup[i] != undefined){
+ getUserDisplay(usersInGroup[i].username, usersInGroup[i].id, grp_id).prependTo(".UsersInGroupList");
+ i++;
+ };
+ while ($(".UsersInGroupList").height() > maxOffsetUserCont) {
+ $(".UsernameBlock").last().remove();
+ }
+ updateMembernumber(usersInGroup.length, grp_id);
//Attribute the group id to the div
$("#UserList").attr("data-group_id", grp_id);
- //Clear the selection
- selectize.clear();
+
+ $(".LinkUserManager a").attr("href","admin.php?page=user_list&group="+grp_id)
}
},
error: function (err) {
@@ -590,7 +598,7 @@ var openUserManager = function(grp_id) {
}
//Add a user block
-var addUserDisplay = function(username, user_id, grp_id) {
+var getUserDisplay = function(username, user_id, grp_id) {
let userBlock = $(''+
'
'+
'
'+username+'
'+
@@ -598,12 +606,18 @@ var addUserDisplay = function(username, user_id, grp_id) {
'
'+
'
Dissociate user from this group
'+
'
'+
- ''+
'');
- userBlock.appendTo(".UsersInGroupList");
- //Setup the delete action
- userBlock.find(".icon-cancel").on("click", function () {
+ while ($(".UsersInGroupList")[0].offsetHeight > maxOffsetUserCont) {
+ $(".UsernameBlock").last().remove();
+ }
+
+ //Setup the delete action
+ userBlock.find(".icon-cancel").on("click", function () {
+ userBlock.find(".icon-cancel").addClass("icon-spin6")
+ userBlock.find(".icon-cancel").addClass("animate-spin")
+ userBlock.find(".icon-cancel").css("pointer-events", "none")
+ userBlock.find(".icon-cancel").removeClass("icon-cancel")
jQuery.ajax({
url: "ws.php?format=json&method=pwg.groups.deleteUser",
type: "POST",
@@ -611,21 +625,23 @@ var addUserDisplay = function(username, user_id, grp_id) {
success: function (raw_data) {
data = jQuery.parseJSON(raw_data);
if (data.stat === "ok") {
- //Setup User Info
- userBlock.find(".UserInfo")
- .css("display", "flex")
- .addClass("UserInfo-dissociated").removeClass("UserInfo-associated")
- .hide()
- .find("p").html(str_user_dissociated);
- userBlock.find(".UserInfo").fadeIn();
- userBlock.delay(1000).fadeOut(function(){
- userBlock.remove();
- updateUserSearch();
- //Update member number
- $(".GroupContainer[data-id="+grp_id+"] .group_number_users")
- .html(($(".UsernameBlock").length) + " " + str_member_default);
- $(".UserNumberBadge").html(''+$(".UsernameBlock").length);
- })
+ infoUsers.remove();
+ infoUsers.insertAfter(userBlock).hide();
+ infoUsers.find("p").html(str_user_dissociated);
+ infoUsers.fadeIn()
+
+ userBlock.remove()
+
+ updateUserSearch();
+
+ while ($(".UsersInGroupList").height() > maxOffsetUserCont) {
+ $(".UsernameBlock").last().remove();
+ }
+
+ usersInGroup = usersInGroup.filter(u => u.id != user_id)
+
+ //Update member number
+ updateMembernumber(parseInt($(".UserNumberBadge").html()) -1, grp_id);
}
}
});
@@ -633,53 +649,101 @@ var addUserDisplay = function(username, user_id, grp_id) {
return userBlock;
}
+//Update member number function
+function updateMembernumber(number, grp_id) {
+ $(".GroupContainer[data-id="+grp_id+"] .group_number_users")
+ .html(number + " " + str_member_default);
+ $(".UserNumberBadge").html(number);
+ $(".AmountOfUsersShown strong:nth-child(2)").html(number)
+ $(".AmountOfUsersShown strong:nth-child(1)").html($(".UsernameBlock").length)
+}
+
// Close pop-up on cross click
$(".CloseUserList").on("click", function() {$('#UserList').fadeOut();})
// Adding Group Action
$(".AddUserBlock button").on("click", function () {
- let grp_id = $("#UserList").attr("data-group_id")
+ let grp_id = $("#UserList").attr("data-group_id");
let usersString = ""
// Get selected ids
- let ids = selectize.getValue();
- ids.split(',').forEach(function(id){
- usersString += "&user_id[]="+id
- });
- jQuery.ajax({
- url: "ws.php?format=json&method=pwg.groups.addUser",
- type: "POST",
- data: "group_id=" + grp_id+ usersString + "&pwg_token=" + pwg_token,
- success: function (raw_data) {
- data = jQuery.parseJSON(raw_data);
- ids.split(',').forEach(function(id){
- // Get the username
- let username = "undefined";
- usersSearch.forEach(function(u) {
- if (u.id == id) {
- username = u.username;
+ let id = selectize.getValue();
+
+ if (id != "") {
+ let loadState = new TemporaryState();
+ loadState.changeHTML($("#UserSubmit")," ");
+ loadState.removeClass($("#UserSubmit"),"icon-user-add");
+ loadState.changeAttribute($("#UserSubmit"),"css","pointer-events:none")
+ jQuery.ajax({
+ url: "ws.php?format=json&method=pwg.groups.addUser",
+ type: "POST",
+ data: "group_id=" + grp_id+ "&user_id=" + id + "&pwg_token=" + pwg_token,
+ success: function (raw_data) {
+ loadState.reverse()
+ data = jQuery.parseJSON(raw_data);
+
+ if (data.stat === "ok") {
+ // Get the username
+ let username = "undefined";
+ JSON.parse(usersCache.storage[usersCache.key]).data.forEach(function(u) {
+ if (u.id == id) {
+ username = u.username;
+ }
+ })
+ let userBlock = getUserDisplay(username, id, grp_id).prependTo(".UsersInGroupList");
+
+ infoUsers.remove();
+ infoUsers.insertAfter(userBlock).hide();
+ infoUsers.find("p").html(str_user_associated);
+ infoUsers.fadeIn()
+
+ updateUserSearch();
+
+ usersInGroup.push({username: username, id:id});
+
+ while ($(".UsersInGroupList").height() > maxOffsetUserCont) {
+ $(".UsernameBlock").last().remove();
}
- })
- let userBlock = addUserDisplay(username, id, grp_id)
- //Setup User Info
- userBlock.find(".UserInfo")
- .css("display", "flex")
- .addClass("UserInfo-associated").removeClass("UserInfo-dissociated")
- .show()
- .find("p").html(str_user_associated);
- userBlock.delay(1000).fadeIn();
- userBlock.find(".UserInfo").delay(1000).fadeOut();
-
- updateUserSearch();
- //Update member number
- $(".GroupContainer[data-id="+grp_id+"] .group_number_users")
- .html(($(".UsernameBlock").length) + " " + str_member_default);
- $(".UserNumberBadge").html(''+$(".UsernameBlock").length);
- })
- }
- });
+ //Update member number
+ updateMembernumber(parseInt($(".UserNumberBadge").html()) + 1, grp_id);
+ }
+ }
+ });
+ }
});
+$(".input-user-name").on("input", function() {
+ searchString = $(this).val().toLowerCase();
+ grp_id = $(".UserListPopIn").data("group_id");
+ if (searchString != "") {
+ infoUsers.remove();
+ $(".UsersInGroupListContainer").css("min-height", $(".UsersInGroupListContainer").height())
+ usersInGroup.forEach(function(u) {
+ let isSearched = u.username.toLowerCase().includes(searchString)
+ if ($(".UsernameBlock[data-id="+u.id+"]").length != 0) {
+ if (!isSearched) {
+ $(".UsernameBlock[data-id="+u.id+"]").remove();
+ }
+ } else if (isSearched) {
+ getUserDisplay(u.username, u.id, grp_id)
+ .prependTo(".UsersInGroupList");
+ }
+ })
+ } else {
+ $(".UsersInGroupListContainer").css("min-height", "")
+ $(".UsersInGroupList").html("");
+ let i = 0;
+ while ($(".UsersInGroupList").outerHeight() <= maxOffsetUserCont && usersInGroup[i] != undefined){
+ getUserDisplay(usersInGroup[i].username, usersInGroup[i].id, grp_id)
+ .prependTo(".UsersInGroupList");
+ i++;
+ }
+ }
+ while ($(".UsersInGroupList").height() > maxOffsetUserCont) {
+ $(".UsernameBlock").last().remove();
+ }
+})
+
// Class to implement a temporary state and reverse it
class TemporaryState {
//Arrays to reverse changes
@@ -688,8 +752,8 @@ class TemporaryState {
htmlChanges = []; //Html changes : {object(s), (old) html}
/**
- * Change an attribute of an object
- * @param {HTML Node} obj HTML Object(s)
+ * Change temporaly an attribute of an object
+ * @param {Jquery Object(s)} obj HTML Object(s)
* @param {String} attr Attribute
* @param {String} tempVal Temporary value of the attribute
*/
@@ -706,7 +770,7 @@ class TemporaryState {
/**
* Add/remove a class temporarily
- * @param {HTML Node} obj HTML Object
+ * @param {Jquery Object(s)} obj HTML Object
* @param {Boolean} st Add (true) or Remove (false) the class
* @param {String} loadclass Class Name
*/
@@ -726,14 +790,29 @@ class TemporaryState {
}
}
+ /**
+ * Add temporarily a class to the object
+ * @param {Jquery Object(s)} obj
+ * @param {string} tempclass
+ */
addClass(obj, tempclass) {
this.changeClass(obj, true, tempclass);
}
+ /**
+ * Remove temporarily a class to the object
+ * @param {Jquery Object(s)} obj
+ * @param {string} tempclass
+ */
removeClass(obj, tempclass) {
this.changeClass(obj, false, tempclass);
}
+ /**
+ * Change temporaly the html of objects (remove event handlers on the actual content)
+ * @param {Jquery Object(s)} obj
+ * @param {string} temphtml
+ */
changeHTML(obj, temphtml) {
for (let i = 0; i < obj.length; i++) {
this.htmlChanges.push({
diff --git a/admin/themes/default/template/group_list.tpl b/admin/themes/default/template/group_list.tpl
index d60b2b147..a2edff3f8 100644
--- a/admin/themes/default/template/group_list.tpl
+++ b/admin/themes/default/template/group_list.tpl
@@ -15,11 +15,18 @@ var str_yes_delete_confirmation = "{'Yes, delete it'|@translate}"
var str_no_delete_confirmation = "{"No, I've changed my mind"|@translate}"
var str_user_associated = "{"User Associated"|@translate}"
var str_user_dissociated = "{"User Dissociated"|@translate}"
+var str_user_list = "{"User List"|@translate}"
+
+var serverKey = '{$CACHE_KEYS.users}'
+var serverId = '{$CACHE_KEYS._hash}'
+var rootUrl = '{$ROOT_URL}'
{/footer_script}
{combine_script id='jquery.selectize' load='footer' path='themes/default/js/plugins/selectize.min.js'}
{combine_css path="themes/default/js/plugins/selectize.{$themeconf.colorscheme}.css"}
+{combine_script id='LocalStorageCache' load='footer' path='admin/themes/default/js/LocalStorageCache.js'}
+
{combine_script id='jquery.confirm' load='footer' require='jquery' path='themes/default/js/plugins/jquery-confirm.min.js'}
{combine_css path="themes/default/js/plugins/jquery-confirm.min.css"}
{combine_css path="admin/themes/default/fontello/css/animation.css"}
@@ -42,7 +49,7 @@ var str_user_dissociated = "{"User Dissociated"|@translate}"
-
+
{/function}
{/function}
@@ -191,15 +198,15 @@ var str_user_dissociated = "{"User Dissociated"|@translate}"
-
{$group.NAME} / User List
+
25
Associate User
-
-
+
+
diff --git a/admin/themes/default/theme.css b/admin/themes/default/theme.css
index f933f088f..59141ab82 100644
--- a/admin/themes/default/theme.css
+++ b/admin/themes/default/theme.css
@@ -2244,7 +2244,6 @@ input:checked + .slider:before {
.UserListPopIn{
position: fixed;
z-index: 100;
- padding-top: 100px;
left: 0;
top: 0;
width: 100%;
@@ -2258,7 +2257,8 @@ input:checked + .slider:before {
width:1100px;
position:absolute;
left:50%;
- transform:translateX(-50%);
+ top: 50%;
+ transform:translate(-50%, -48%);
text-align:left;
padding:30px;
}
@@ -2316,13 +2316,13 @@ input:checked + .slider:before {
}
#UserList .AddUserBlock p,
-#UserList .AddUserBlock input,
+#UserList .AddUserBlock select,
#UserList .AddUserBlock button{
display:inline-block;
margin:0 5px;
}
-#UserList .AddUserBlock input,
+#UserList .AddUserBlock select,
#UserList .FilterUserBlock input{
padding:11px 10px;
}
@@ -2367,30 +2367,6 @@ input:checked + .slider:before {
border-radius:25px;
}
-.UsernameBlock .UserInfo {
- display: none;
- position: absolute;
- top: 0;
-
- width: 100%;
- left: 0px;
- height: 100%;
- border-radius: 25px;
-}
-
-.UsernameBlock .UserInfo-dissociated {
- color: #f22;
- background-color: #ffd5dc;
-}
-
-.UsernameBlock .UserInfo-associated {
- color: #0a0;
- background-color:#c2f5c2;
-}
-
-.UsernameBlock .UserInfo p {
- margin: auto
-}
.UsersInGroupListContainer{
max-height:315px;
@@ -2424,7 +2400,7 @@ input:checked + .slider:before {
background-color:#f3f3f3;
color: #3c3c3c;
text-align: left;
- padding: 2px 10px;
+ padding: 5px 10px;
border-radius: 10px;
border:1px solid #3c3c3c;
font-weight:700;
@@ -2432,7 +2408,7 @@ input:checked + .slider:before {
position: absolute;
z-index: 4;
top:10px;
- left:10px;
+ left:20px;
transition: opacity 0.3s;
z-index:101;
}
@@ -2444,7 +2420,6 @@ input:checked + .slider:before {
.ValidationUserAssociated{
display:inline-block;
font-size:12px;
- width:110px;
text-align:left;
padding:2px;
border-radius:10px;
@@ -2469,7 +2444,7 @@ input:checked + .slider:before {
.LinkUserManager{
text-align:center;
font-weight:700;
- padding:30px 0;
+ padding-top:20px;
}
/********/