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

'+ '
'+ - '

User Dissociated

'+ ''); - 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}"
-
+
@@ -77,7 +84,7 @@ var str_user_dissociated = "{"User Dissociated"|@translate}"
Manage users - Manage permissions + Manage permissions
{/function} {/function} @@ -191,15 +198,15 @@ var str_user_dissociated = "{"User Dissociated"|@translate}"
-

{$group.NAME} / User List

+

25

Associate User

- - + +
@@ -215,9 +222,6 @@ var str_user_dissociated = "{"User Dissociated"|@translate}"
-
-

User Associated

-
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; } /********/