From 434d68129dc79160344d039b64d76e1f6974bb5c Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 23 Aug 2016 17:22:10 +0200 Subject: Backport of Users page lazy multiselect group dropdowns #1128 to stable9 Users page lazy multiselect group dropdowns Instead of pre-rendering all multiselects with lots of group entries, the current groups are now displayed as simple labels. Behind the labels there is a pencil icon like for other fields. When clicking the pencil icon, the dropdown will be spawned and will open itself. Upon closing of the dropdown, the label comes back with the updated selection and the dropdown is destroyed. Extra non-available groups also in list Fix group sorting in user list group selection --- core/js/multiselect.js | 52 ++++---- settings/css/settings.css | 9 ++ settings/js/users/groups.js | 4 - settings/js/users/users.js | 174 +++++++++++++++------------ settings/templates/users/main.php | 4 +- settings/templates/users/part.createuser.php | 11 +- settings/templates/users/part.userlist.php | 8 +- 7 files changed, 143 insertions(+), 119 deletions(-) diff --git a/core/js/multiselect.js b/core/js/multiselect.js index 6d5c54ac0f5..49a7934a468 100644 --- a/core/js/multiselect.js +++ b/core/js/multiselect.js @@ -32,7 +32,7 @@ 'onuncheck':false, 'minWidth': 'default;' }; - var slideDuration = 200; + var slideDuration = 0; $(this).attr('data-msid', multiSelectId); $.extend(settings,options); $.each(this.children(),function(i,option) { @@ -75,6 +75,26 @@ var self = this; self.menuDirection = 'down'; + + function closeDropDown() { + if(!button.parent().data('preventHide')) { + // How can I save the effect in a var? + if(self.menuDirection === 'down') { + button.parent().children('ul').slideUp(slideDuration,function() { + button.parent().children('ul').remove(); + button.removeClass('active down'); + $(self).trigger($.Event('dropdownclosed', settings)); + }); + } else { + button.parent().children('ul').fadeOut(slideDuration,function() { + button.parent().children('ul').remove(); + button.removeClass('active up'); + $(self).trigger($.Event('dropdownclosed', settings)); + }); + } + } + } + button.click(function(event){ var button=$(this); @@ -83,21 +103,20 @@ button.parent().children('ul').slideUp(slideDuration,function() { button.parent().children('ul').remove(); button.removeClass('active down'); + $(self).trigger($.Event('dropdownclosed', settings)); }); } else { button.parent().children('ul').fadeOut(slideDuration,function() { button.parent().children('ul').remove(); button.removeClass('active up'); + $(self).trigger($.Event('dropdownclosed', settings)); }); } return; } + // tell other lists to shut themselves var lists=$('ul.multiselectoptions'); - lists.slideUp(slideDuration,function(){ - lists.remove(); - $('div.multiselect').removeClass('active'); - button.addClass('active'); - }); + lists.trigger($.Event('shut')); button.addClass('active'); event.stopPropagation(); var options=$(this).parent().next().children(); @@ -309,29 +328,16 @@ list.detach().insertBefore($(this)); list.addClass('up'); button.addClass('up'); - list.fadeIn(); + list.show(); self.menuDirection = 'up'; } list.click(function(event) { event.stopPropagation(); }); + list.one('shut', closeDropDown); }); - $(window).click(function() { - if(!button.parent().data('preventHide')) { - // How can I save the effect in a var? - if(self.menuDirection === 'down') { - button.parent().children('ul').slideUp(slideDuration,function() { - button.parent().children('ul').remove(); - button.removeClass('active down'); - }); - } else { - button.parent().children('ul').fadeOut(slideDuration,function() { - button.parent().children('ul').remove(); - button.removeClass('active up'); - }); - } - } - }); + + $(window).click(closeDropDown); return span; }; diff --git a/settings/css/settings.css b/settings/css/settings.css index db6cced6185..b29b65d28f1 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -194,6 +194,15 @@ span.usersLastLoginTooltip { white-space: nowrap; } color: #000000; } +#newuser .groups { + display: inline; +} + +#newuser .groupsListContainer.hidden, +#userlist .groupsListContainer.hidden { + display: none; +} + tr:hover>td.password>span, tr:hover>td.displayName>span { margin:0; cursor:pointer; } tr:hover>td.remove>a, tr:hover>td.password>img,tr:hover>td.displayName>img, tr:hover>td.quota>img { visibility:visible; cursor:pointer; } td.remove { diff --git a/settings/js/users/groups.js b/settings/js/users/groups.js index 27c41884504..78c0f42b77d 100644 --- a/settings/js/users/groups.js +++ b/settings/js/users/groups.js @@ -136,10 +136,6 @@ GroupList = { var addedGroup = result.groupname; UserList.availableGroups = $.unique($.merge(UserList.availableGroups, [addedGroup])); GroupList.addGroup(result.groupname); - - $('.groupsselect, .subadminsselect') - .append($('')); + } + + $.each(this.availableGroups, function (i, group) { + // some new groups might be selected but not in the available groups list yet + var extraIndex = extraGroups.indexOf(group); + if (extraIndex >= 0) { + // remove extra group as it was found + extraGroups.splice(extraIndex, 1); + } + createItem(group); + }); + $.each(extraGroups, function (i, group) { + createItem(group); + }); + + $td.append($groupsSelect); + + if (isSubadminSelect) { + UserList.applySubadminSelect($groupsSelect, user, checked); + } else { + UserList.applyGroupSelect($groupsSelect, user, checked); + } + + $groupsListContainer.addClass('hidden'); + $td.find('.multiselect:not(.groupsListContainer):first').click(); + $groupsSelect.on('dropdownclosed', function(e) { + $groupsSelect.remove(); + $td.find('.multiselect:not(.groupsListContainer)').parent().remove(); + $td.find('.multiselectoptions').remove(); + $groupsListContainer.removeClass('hidden'); + UserList._updateGroupListLabel($td, e.checked); + }); + }, + + /** + * Updates the groups list td with the given groups selection + */ + _updateGroupListLabel: function($td, groups) { + var placeholder = $td.find('.groupsListContainer').attr('data-placeholder'); + var $groupsEl = $td.find('.groupsList'); + $groupsEl.text(groups.join(', ') || placeholder || t('settings', 'no group')); + $td.data('groups', groups); } }; @@ -623,13 +635,6 @@ $(document).ready(function () { // TODO: move other init calls inside of initialize UserList.initialize($('#userlist')); - $('.groupsselect').each(function (index, element) { - UserList.applyGroupSelect(element); - }); - $('.subadminsselect').each(function (index, element) { - UserList.applySubadminSelect(element); - }); - $userListBody.on('click', '.password', function (event) { event.stopPropagation(); @@ -758,11 +763,24 @@ $(document).ready(function () { }); }); + $('#newuser .groupsListContainer').on('click', function (event) { + event.stopPropagation(); + var $div = $(this).closest('.groups'); + UserList._triggerGroupEdit($div); + }); + $userListBody.on('click', '.groups .groupsListContainer, .subadmins .groupsListContainer', function (event) { + event.stopPropagation(); + var $td = $(this).closest('td'); + var isSubadminSelect = $td.hasClass('subadmins'); + UserList._triggerGroupEdit($td, isSubadminSelect); + }); + // init the quota field select box after it is shown the first time $('#app-settings').one('show', function() { $(this).find('#default_quota').singleSelect().on('change', UserList.onQuotaSelect); }); + UserList._updateGroupListLabel($('#newuser .groups'), []); $('#newuser').submit(function (event) { event.preventDefault(); var username = $('#newusername').val(); @@ -798,7 +816,7 @@ $(document).ready(function () { } promise.then(function() { - var groups = $('#newusergroups').val() || []; + var groups = $('#newuser .groups').data('groups') || []; $.post( OC.generateUrl('/settings/users/users'), { diff --git a/settings/templates/users/main.php b/settings/templates/users/main.php index f50f83b38b3..b363a4c4da8 100644 --- a/settings/templates/users/main.php +++ b/settings/templates/users/main.php @@ -19,10 +19,10 @@ style('settings', 'settings'); $userlistParams = array(); $allGroups=array(); -foreach($_["groups"] as $group) { +foreach($_["adminGroup"] as $group) { $allGroups[] = $group['name']; } -foreach($_["adminGroup"] as $group) { +foreach($_["groups"] as $group) { $allGroups[] = $group['name']; } $userlistParams['subadmingroups'] = $allGroups; diff --git a/settings/templates/users/part.createuser.php b/settings/templates/users/part.createuser.php index 0fc5a2bdeaa..6f23d06cfa3 100644 --- a/settings/templates/users/part.createuser.php +++ b/settings/templates/users/part.createuser.php @@ -10,16 +10,7 @@ - +
diff --git a/settings/templates/users/part.userlist.php b/settings/templates/users/part.userlist.php index 15b7cb4abd7..788fe3a4a8e 100644 --- a/settings/templates/users/part.userlist.php +++ b/settings/templates/users/part.userlist.php @@ -38,9 +38,13 @@ src="" alt="t('change email address'))?>" title="t('change email address'))?>"/> - +
+ - +
+