diff options
author | Georg Ehrke <developer@georgehrke.com> | 2014-06-05 22:54:27 +0200 |
---|---|---|
committer | Georg Ehrke <developer@georgehrke.com> | 2014-06-05 22:54:27 +0200 |
commit | 0fe8f77c1748d167e115680346ae98bba78da38d (patch) | |
tree | a456ff35bb2da1a2778f18ccab1ade63e9aaddda /settings/js | |
parent | fad3bd7fc0c094bd16e07708557cd1a7676889cd (diff) | |
parent | e1beb8c6c38d48eb923ed323dea25110e4bbacfd (diff) | |
download | nextcloud-server-0fe8f77c1748d167e115680346ae98bba78da38d.tar.gz nextcloud-server-0fe8f77c1748d167e115680346ae98bba78da38d.zip |
Merge branch 'master' into update_shipped_apps_from_appstore
Conflicts:
lib/private/app.php
settings/templates/apps.php
Diffstat (limited to 'settings/js')
-rw-r--r-- | settings/js/admin.js | 3 | ||||
-rw-r--r-- | settings/js/apps.js | 108 | ||||
-rw-r--r-- | settings/js/users.js | 546 | ||||
-rw-r--r-- | settings/js/users/deleteHandler.js | 171 | ||||
-rw-r--r-- | settings/js/users/filter.js | 82 | ||||
-rw-r--r-- | settings/js/users/groups.js | 292 | ||||
-rw-r--r-- | settings/js/users/users.js | 616 |
7 files changed, 1259 insertions, 559 deletions
diff --git a/settings/js/admin.js b/settings/js/admin.js index bc95c6a3dc5..8c7572fa394 100644 --- a/settings/js/admin.js +++ b/settings/js/admin.js @@ -83,6 +83,9 @@ $(document).ready(function(){ $('#allowLinks').change(function() { $("#publicLinkSettings").toggleClass('hidden', !this.checked); }); + $('#allowResharing').change(function() { + $("#resharingSettings").toggleClass('hidden', !this.checked); + }); $('#security').change(function(){ $.post(OC.filePath('settings','ajax','setsecurity.php'), { enforceHTTPS: $('#forcessl').val() },function(){} ); diff --git a/settings/js/apps.js b/settings/js/apps.js index a12131b0224..95e56485a6a 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -96,12 +96,41 @@ OC.Settings.Apps = OC.Settings.Apps || { } else { page.find(".warning").hide(); } + + page.find("div.multiselect").parent().remove(); + if(OC.Settings.Apps.isType(app, 'filesystem') || OC.Settings.Apps.isType(app, 'prelogin') || + OC.Settings.Apps.isType(app, 'authentication') || OC.Settings.Apps.isType(app, 'logging')) { + page.find("#groups_enable").hide(); + page.find("label[for='groups_enable']").hide(); + page.find("#groups_enable").attr('checked', null); + } else { + $('#group_select > option').each(function (i, el) { + if (app.groups.length === 0 || app.groups.indexOf(el.value) >= 0) { + $(el).attr('selected', 'selected'); + } else { + $(el).attr('selected', null); + } + }); + if (app.active) { + if (app.groups.length) { + $('#group_select').multiSelect(); + page.find("#groups_enable").attr('checked','checked'); + } else { + page.find("#groups_enable").attr('checked', null); + } + page.find("#groups_enable").show(); + page.find("label[for='groups_enable']").show(); + } else { + page.find("#groups_enable").hide(); + page.find("label[for='groups_enable']").hide(); + } + } }, - enableApp:function(appid, active, element) { - console.log('enableApp:', appid, active, element); + enableApp:function(appid, active, element, groups) { + groups = groups || []; var appitem=$('#app-navigation ul li[data-id="'+appid+'"]'); element.val(t('settings','Please wait....')); - if(active) { + if(active && !groups.length) { $.post(OC.filePath('settings','ajax','disableapp.php'),{appid:appid},function(result) { if(!result || result.status !== 'success') { if (result.data && result.data.message) { @@ -116,14 +145,19 @@ OC.Settings.Apps = OC.Settings.Apps || { } else { appitem.data('active',false); + appitem.data('groups', ''); element.data('active',false); OC.Settings.Apps.removeNavigation(appid); appitem.removeClass('active'); element.val(t('settings','Enable')); + element.parent().find("#groups_enable").hide(); + element.parent().find("label[for='groups_enable']").hide(); + var app = OC.get('appData_' + appid); + app.active = false; } },'json'); } else { - $.post(OC.filePath('settings','ajax','enableapp.php'),{appid:appid},function(result) { + $.post(OC.filePath('settings','ajax','enableapp.php'),{appid: appid, groups: groups},function(result) { if(!result || result.status !== 'success') { if (result.data && result.data.message) { OC.Settings.Apps.showErrorMessage(result.data.message); @@ -140,6 +174,21 @@ OC.Settings.Apps = OC.Settings.Apps || { element.data('active',true); appitem.addClass('active'); element.val(t('settings','Disable')); + var app = OC.get('appData_' + appid); + app.active = true; + if (OC.Settings.Apps.isType(app, 'filesystem') || OC.Settings.Apps.isType(app, 'prelogin') || + OC.Settings.Apps.isType(app, 'authentication') || OC.Settings.Apps.isType(app, 'logging')) { + element.parent().find("#groups_enable").hide(); + element.parent().find("label[for='groups_enable']").hide(); + } else { + element.parent().find("#groups_enable").show(); + element.parent().find("label[for='groups_enable']").show(); + if (groups) { + appitem.data('groups', JSON.stringify(groups)); + } else { + appitem.data('groups', ''); + } + } } },'json') .fail(function() { @@ -153,7 +202,6 @@ OC.Settings.Apps = OC.Settings.Apps || { } }, updateApp:function(appid, element) { - console.log('updateApp:', appid, element); element.val(t('settings','Updating....')); $.post(OC.filePath('settings','ajax','updateapp.php'),{appid:appid},function(result) { if(!result || result.status !== 'success') { @@ -204,7 +252,7 @@ OC.Settings.Apps = OC.Settings.Apps || { if(response.status === 'success'){ var navIds=response.nav_ids; for(var i=0; i< navIds.length; i++){ - $('#apps .wrapper').children('li[data-id="'+navIds[i]+'"]').remove(); + $('#apps ul').children('li[data-id="'+navIds[i]+'"]').remove(); } } }); @@ -215,7 +263,7 @@ OC.Settings.Apps = OC.Settings.Apps || { var navEntries=response.nav_entries; for(var i=0; i< navEntries.length; i++){ var entry = navEntries[i]; - var container = $('#apps .wrapper'); + var container = $('#apps ul'); if(container.children('li[data-id="'+entry.id+'"]').length === 0){ var li=$('<li></li>'); @@ -229,8 +277,9 @@ OC.Settings.Apps = OC.Settings.Apps || { li.append(a); // append the new app as last item in the list - // (.push is from sticky footer) - $('#apps .wrapper .push').before(li); + // which is the "add apps" entry with the id + // #apps-management + $('#apps-management').before(li); // scroll the app navigation down // so the newly added app is seen @@ -240,11 +289,12 @@ OC.Settings.Apps = OC.Settings.Apps || { // draw attention to the newly added app entry // by flashing it twice - container.children('li[data-id="' + entry.id + '"]') - .animate({opacity: 0.3}) + $('#header .menutoggle') + .animate({opacity: 0.5}) + .animate({opacity: 1}) + .animate({opacity: 0.5}) .animate({opacity: 1}) - .animate({opacity: 0.3}) - .animate({opacity: 1}); + .animate({opacity: 0.75}); if (!SVGSupport() && entry.icon.match(/\.svg$/i)) { $(img).addClass('svg'); @@ -258,12 +308,18 @@ OC.Settings.Apps = OC.Settings.Apps || { showErrorMessage: function(message) { $('.appinfo .warning').show(); $('.appinfo .warning').text(message); + }, + isType: function(app, type){ + return app.types && app.types.indexOf(type) !== -1; } }; $(document).ready(function(){ $('#app-navigation ul li').each(function(index,li){ var app = OC.get('appData_'+$(li).data('id')); + if (app) { + app.groups= $(li).data('groups') || []; + } $(li).data('app',app); $(this).find('span.hidden').remove(); }); @@ -308,6 +364,20 @@ $(document).ready(function(){ } }); + $('#group_select').change(function() { + var element = $('#app-content input.enable'); + var groups = $(this).val(); + var appid = element.data('appid'); + if (appid) { + OC.Settings.Apps.enableApp(appid, false, element, groups); + var li = $('[data-id="'+appid+'"]'); + var app = OC.get('appData_' + $(li).data('id')); + app.groups = groups; + li.data('groups', groups); + li.attr('data-groups', JSON.stringify(groups)); + } + }); + if(appid) { var item = $('#app-navigation ul li[data-id="'+appid+'"]'); if(item) { @@ -316,4 +386,16 @@ $(document).ready(function(){ $('#app-navigation').animate({scrollTop: $(item).offset().top-70}, 'slow','swing'); } } + + $("#groups_enable").change(function() { + if (this.checked) { + $("div.multiselect").parent().remove(); + $('#group_select').multiSelect(); + } else { + $('#group_select').hide().val(null); + $("div.multiselect").parent().remove(); + } + + $('#group_select').change(); + }); }); diff --git a/settings/js/users.js b/settings/js/users.js deleted file mode 100644 index eef3c237277..00000000000 --- a/settings/js/users.js +++ /dev/null @@ -1,546 +0,0 @@ -/** - * Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com> - * This file is licensed under the Affero General Public License version 3 or later. - * See the COPYING-README file. - */ - -function setQuota (uid, quota, ready) { - $.post( - OC.filePath('settings', 'ajax', 'setquota.php'), - {username: uid, quota: quota}, - function (result) { - if (ready) { - ready(result.data.quota); - } - } - ); -} - -var UserList = { - useUndo: true, - availableGroups: [], - offset: 30, //The first 30 users are there. No prob, if less in total. - //hardcoded in settings/users.php - - usersToLoad: 10, //So many users will be loaded when user scrolls down - - /** - * @brief Initiate user deletion process in UI - * @param string uid the user ID to be deleted - * - * Does not actually delete the user; it sets them for - * deletion when the current page is unloaded, at which point - * finishDelete() completes the process. This allows for 'undo'. - */ - do_delete: function (uid) { - if (typeof UserList.deleteUid !== 'undefined') { - //Already a user in the undo queue - UserList.finishDelete(null); - } - UserList.deleteUid = uid; - - // Set undo flag - UserList.deleteCanceled = false; - - // Provide user with option to undo - $('#notification').data('deleteuser', true); - OC.Notification.showHtml(t('settings', 'deleted') + ' ' + escapeHTML(uid) + '<span class="undo">' + t('settings', 'undo') + '</span>'); - }, - - /** - * @brief Delete a user via ajax - * @param bool ready whether to use ready() upon completion - * - * Executes deletion via ajax of user identified by property deleteUid - * if 'undo' has not been used. Completes the user deletion procedure - * and reflects success in UI. - */ - finishDelete: function (ready) { - - // Check deletion has not been undone - if (!UserList.deleteCanceled && UserList.deleteUid) { - - // Delete user via ajax - $.ajax({ - type: 'POST', - url: OC.filePath('settings', 'ajax', 'removeuser.php'), - async: false, - data: { username: UserList.deleteUid }, - success: function (result) { - if (result.status === 'success') { - // Remove undo option, & remove user from table - OC.Notification.hide(); - $('tr').filterAttr('data-uid', UserList.deleteUid).remove(); - UserList.deleteCanceled = true; - if (ready) { - ready(); - } - } else { - OC.dialogs.alert(result.data.message, t('settings', 'Unable to remove user')); - } - } - }); - } - }, - - add: function (username, displayname, groups, subadmin, quota, sort) { - var tr = $('tbody tr').first().clone(); - var subadminsEl; - var subadminSelect; - var groupsSelect; - if (tr.find('div.avatardiv').length){ - $('div.avatardiv', tr).avatar(username, 32); - } - tr.attr('data-uid', username); - tr.attr('data-displayName', displayname); - tr.find('td.name').text(username); - tr.find('td.displayName > span').text(displayname); - - // make them look like the multiselect buttons - // until they get time to really get initialized - groupsSelect = $('<select multiple="multiple" class="groupsselect multiselect button" data-placehoder="Groups" title="' + t('settings', 'Groups') + '"></select>') - .attr('data-username', username) - .data('user-groups', groups); - if (tr.find('td.subadmins').length > 0) { - subadminSelect = $('<select multiple="multiple" class="subadminsselect multiselect button" data-placehoder="subadmins" title="' + t('settings', 'Group Admin') + '">') - .attr('data-username', username) - .data('user-groups', groups) - .data('subadmin', subadmin); - tr.find('td.subadmins').empty(); - } - $.each(this.availableGroups, function (i, group) { - groupsSelect.append($('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>')); - if (typeof subadminSelect !== 'undefined' && group !== 'admin') { - subadminSelect.append($('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>')); - } - }); - tr.find('td.groups').empty().append(groupsSelect); - subadminsEl = tr.find('td.subadmins'); - if (subadminsEl.length > 0) { - subadminsEl.append(subadminSelect); - } - if (tr.find('td.remove img').length === 0 && OC.currentUser !== username) { - var rm_img = $('<img class="svg action">').attr({ - src: OC.imagePath('core', 'actions/delete') - }); - var rm_link = $('<a class="action delete">') - .attr({ href: '#', 'original-title': t('settings', 'Delete')}) - .append(rm_img); - tr.find('td.remove').append(rm_link); - } else if (OC.currentUser === username) { - tr.find('td.remove a').remove(); - } - var quotaSelect = tr.find('select.quota-user'); - if (quota === 'default') { - quotaSelect.find('option').attr('selected', null); - quotaSelect.find('option').first().attr('selected', 'selected'); - quotaSelect.data('previous', 'default'); - } else { - if (quotaSelect.find('option[value="' + quota + '"]').length > 0) { - quotaSelect.find('option[value="' + quota + '"]').attr('selected', 'selected'); - } else { - quotaSelect.append('<option value="' + escapeHTML(quota) + '" selected="selected">' + escapeHTML(quota) + '</option>'); - } - } - $(tr).appendTo('tbody'); - - if (sort) { - UserList.doSort(); - } - - quotaSelect.on('change', function () { - var uid = $(this).parent().parent().attr('data-uid'); - var quota = $(this).val(); - setQuota(uid, quota, function(returnedQuota){ - if (quota !== returnedQuota) { - $(quotaSelect).find(':selected').text(returnedQuota); - } - }); - }); - - // defer init so the user first sees the list appear more quickly - window.setTimeout(function(){ - quotaSelect.singleSelect(); - UserList.applyMultiplySelect(groupsSelect); - if (subadminSelect) { - UserList.applyMultiplySelect(subadminSelect); - } - }, 0); - return tr; - }, - // From http://my.opera.com/GreyWyvern/blog/show.dml/1671288 - alphanum: function(a, b) { - function chunkify(t) { - var tz = [], x = 0, y = -1, n = 0, i, j; - - while (i = (j = t.charAt(x++)).charCodeAt(0)) { - var m = (i === 46 || (i >=48 && i <= 57)); - if (m !== n) { - tz[++y] = ""; - n = m; - } - tz[y] += j; - } - return tz; - } - - var aa = chunkify(a.toLowerCase()); - var bb = chunkify(b.toLowerCase()); - - for (x = 0; aa[x] && bb[x]; x++) { - if (aa[x] !== bb[x]) { - var c = Number(aa[x]), d = Number(bb[x]); - if (c === aa[x] && d === bb[x]) { - return c - d; - } else { - return (aa[x] > bb[x]) ? 1 : -1; - } - } - } - return aa.length - bb.length; - }, - doSort: function() { - var self = this; - var rows = $('tbody tr').get(); - - rows.sort(function(a, b) { - return UserList.alphanum($(a).find('td.name').text(), $(b).find('td.name').text()); - }); - - var items = []; - $.each(rows, function(index, row) { - items.push(row); - if(items.length === 100) { - $('tbody').append(items); - items = []; - } - }); - if(items.length > 0) { - $('tbody').append(items); - } - }, - update: function () { - if (UserList.updating) { - return; - } - $('table+.loading').css('visibility', 'visible'); - UserList.updating = true; - var query = $.param({ offset: UserList.offset, limit: UserList.usersToLoad }); - $.get(OC.generateUrl('/settings/ajax/userlist') + '?' + query, function (result) { - var loadedUsers = 0; - var trs = []; - if (result.status === 'success') { - //The offset does not mirror the amount of users available, - //because it is backend-dependent. For correct retrieval, - //always the limit(requested amount of users) needs to be added. - $.each(result.data, function (index, user) { - if($('tr[data-uid="' + user.name + '"]').length > 0) { - return true; - } - var tr = UserList.add(user.name, user.displayname, user.groups, user.subadmin, user.quota, false); - tr.addClass('appear transparent'); - trs.push(tr); - loadedUsers++; - }); - if (result.data.length > 0) { - UserList.doSort(); - $('table+.loading').css('visibility', 'hidden'); - } - else { - UserList.noMoreEntries = true; - $('table+.loading').remove(); - } - UserList.offset += loadedUsers; - // animate - setTimeout(function() { - for (var i = 0; i < trs.length; i++) { - trs[i].removeClass('transparent'); - } - }, 0); - } - UserList.updating = false; - }); - }, - - applyMultiplySelect: function (element) { - var checked = []; - var user = element.attr('data-username'); - if ($(element).hasClass('groupsselect')) { - if (element.data('userGroups')) { - checked = element.data('userGroups'); - } - if (user) { - var checkHandeler = function (group) { - if (user === OC.currentUser && group === 'admin') { - return false; - } - if (!oc_isadmin && checked.length === 1 && checked[0] === group) { - return false; - } - $.post( - OC.filePath('settings', 'ajax', 'togglegroups.php'), - { - username: user, - group: group - }, - function (response) { - if(response.status === 'success' - && UserList.availableGroups.indexOf(response.data.groupname) === -1 - && response.data.action === 'add') { - UserList.availableGroups.push(response.data.groupname); - } - if(response.data.message) { - OC.Notification.show(response.data.message); - } - } - ); - }; - } else { - checkHandeler = false; - } - var addGroup = function (select, group) { - $('select[multiple]').each(function (index, element) { - if ($(element).find('option[value="' + group + '"]').length === 0 && select.data('msid') !== $(element).data('msid')) { - $(element).append('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>'); - } - }); - }; - var label; - if (oc_isadmin) { - label = t('settings', 'add group'); - } else { - label = null; - } - element.multiSelect({ - createCallback: addGroup, - createText: label, - selectedFirst: true, - checked: checked, - oncheck: checkHandeler, - onuncheck: checkHandeler, - minWidth: 100 - }); - } - if ($(element).hasClass('subadminsselect')) { - if (element.data('subadmin')) { - checked = element.data('subadmin'); - } - var checkHandeler = function (group) { - if (group === 'admin') { - return false; - } - $.post( - OC.filePath('settings', 'ajax', 'togglesubadmins.php'), - { - username: user, - group: group - }, - function () { - } - ); - }; - - var addSubAdmin = function (group) { - $('select[multiple]').each(function (index, element) { - if ($(element).find('option[value="' + group + '"]').length === 0) { - $(element).append('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>'); - } - }); - }; - element.multiSelect({ - createCallback: addSubAdmin, - createText: null, - checked: checked, - oncheck: checkHandeler, - onuncheck: checkHandeler, - minWidth: 100 - }); - } - }, - - _onScroll: function(e) { - if (!!UserList.noMoreEntries) { - return; - } - if ($(window).scrollTop() + $(window).height() > $(document).height() - 500) { - UserList.update(true); - } - }, -}; - -$(document).ready(function () { - - UserList.doSort(); - UserList.availableGroups = $('#content table').data('groups'); - $(window).scroll(function(e) {UserList._onScroll(e);}); - $('table').after($('<div class="loading" style="height: 200px; visibility: hidden;"></div>')); - - $('select[multiple]').each(function (index, element) { - UserList.applyMultiplySelect($(element)); - }); - - $('table').on('click', 'td.remove>a', function (event) { - var row = $(this).parent().parent(); - var uid = $(row).attr('data-uid'); - $(row).hide(); - // Call function for handling delete/undo - UserList.do_delete(uid); - }); - - $('table').on('click', 'td.password>img', function (event) { - event.stopPropagation(); - var img = $(this); - var uid = img.parent().parent().attr('data-uid'); - var input = $('<input type="password">'); - img.css('display', 'none'); - img.parent().children('span').replaceWith(input); - input.focus(); - input.keypress(function (event) { - if (event.keyCode === 13) { - if ($(this).val().length > 0) { - var recoveryPasswordVal = $('input:password[id="recoveryPassword"]').val(); - $.post( - OC.generateUrl('/settings/users/changepassword'), - {username: uid, password: $(this).val(), recoveryPassword: recoveryPasswordVal}, - function (result) { - if (result.status != 'success') { - OC.Notification.show(t('admin', result.data.message)); - } - } - ); - input.blur(); - } else { - input.blur(); - } - } - }); - input.blur(function () { - $(this).replaceWith($('<span>●●●●●●●</span>')); - img.css('display', ''); - }); - }); - $('input:password[id="recoveryPassword"]').keyup(function(event) { - OC.Notification.hide(); - }); - - $('table').on('click', 'td.password', function (event) { - $(this).children('img').click(); - }); - - $('table').on('click', 'td.displayName>img', function (event) { - event.stopPropagation(); - var img = $(this); - var uid = img.parent().parent().attr('data-uid'); - var displayName = escapeHTML(img.parent().parent().attr('data-displayName')); - var input = $('<input type="text" value="' + displayName + '">'); - img.css('display', 'none'); - img.parent().children('span').replaceWith(input); - input.focus(); - input.keypress(function (event) { - if (event.keyCode === 13) { - if ($(this).val().length > 0) { - $.post( - OC.filePath('settings', 'ajax', 'changedisplayname.php'), - {username: uid, displayName: $(this).val()}, - function (result) { - if (result && result.status==='success'){ - img.parent().parent().find('div.avatardiv').avatar(result.data.username, 32); - } - } - ); - input.blur(); - } else { - input.blur(); - } - } - }); - input.blur(function () { - var input = $(this), - displayName = input.val(); - input.closest('tr').attr('data-displayName', displayName); - input.replaceWith('<span>' + escapeHTML(displayName) + '</span>'); - img.css('display', ''); - }); - }); - $('table').on('click', 'td.displayName', function (event) { - $(this).children('img').click(); - }); - - $('select.quota, select.quota-user').singleSelect().on('change', function () { - var select = $(this); - var uid = $(this).parent().parent().attr('data-uid'); - var quota = $(this).val(); - setQuota(uid, quota, function(returnedQuota){ - if (quota !== returnedQuota) { - select.find(':selected').text(returnedQuota); - } - }); - }); - - $('#newuser').submit(function (event) { - event.preventDefault(); - var username = $('#newusername').val(); - var password = $('#newuserpassword').val(); - if ($.trim(username) === '') { - OC.dialogs.alert( - t('settings', 'A valid username must be provided'), - t('settings', 'Error creating user')); - return false; - } - if ($.trim(password) === '') { - OC.dialogs.alert( - t('settings', 'A valid password must be provided'), - t('settings', 'Error creating user')); - return false; - } - var groups = $('#newusergroups').prev().children('div').data('settings').checked; - $('#newuser').get(0).reset(); - $.post( - OC.filePath('settings', 'ajax', 'createuser.php'), - { - username: username, - password: password, - groups: groups - }, - function (result) { - if (result.status !== 'success') { - OC.dialogs.alert(result.data.message, - t('settings', 'Error creating user')); - } else { - if (result.data.groups) { - var addedGroups = result.data.groups; - UserList.availableGroups = $.unique($.merge(UserList.availableGroups, addedGroups)); - } - if (result.data.homeExists){ - OC.Notification.hide(); - OC.Notification.show(t('settings', 'Warning: Home directory for user "{user}" already exists', {user: result.data.username})); - if (UserList.notificationTimeout){ - window.clearTimeout(UserList.notificationTimeout); - } - UserList.notificationTimeout = window.setTimeout( - function(){ - OC.Notification.hide(); - UserList.notificationTimeout = null; - }, 10000); - } - if($('tr[data-uid="' + username + '"]').length === 0) { - UserList.add(username, username, result.data.groups, null, 'default', true); - } - } - } - ); - }); - // Handle undo notifications - OC.Notification.hide(); - $('#notification').on('click', '.undo', function () { - if ($('#notification').data('deleteuser')) { - $('tbody tr').filterAttr('data-uid', UserList.deleteUid).show(); - UserList.deleteCanceled = true; - } - OC.Notification.hide(); - }); - UserList.useUndo = ('onbeforeunload' in window); - $(window).bind('beforeunload', function () { - UserList.finishDelete(null); - }); -}); diff --git a/settings/js/users/deleteHandler.js b/settings/js/users/deleteHandler.js new file mode 100644 index 00000000000..894744ba3e9 --- /dev/null +++ b/settings/js/users/deleteHandler.js @@ -0,0 +1,171 @@ +/** + * Copyright (c) 2014, Arthur Schiwon <blizzz@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + +/** + * takes care of deleting things represented by an ID + * + * @class + * @param {string} endpoint the corresponding ajax PHP script. Currently limited + * to settings - ajax path. + * @param {string} paramID the by the script expected parameter name holding the + * ID of the object to delete + * @param {markCallback} markCallback function to be called after successfully + * marking the object for deletion. + * @param {removeCallback} removeCallback the function to be called after + * successful delete. + */ +function DeleteHandler(endpoint, paramID, markCallback, removeCallback) { + this.oidToDelete = false; + this.canceled = false; + + this.ajaxEndpoint = endpoint; + this.ajaxParamID = paramID; + + this.markCallback = markCallback; + this.removeCallback = removeCallback; + this.undoCallback = false; + + this.notifier = false; + this.notificationDataID = false; + this.notificationMessage = false; + this.notificationPlaceholder = '%oid'; +} + +/** + * The function to be called after successfully marking the object for deletion + * @callback markCallback + * @param {string} oid the ID of the specific user or group + */ + +/** + * The function to be called after successful delete. The id of the object will + * be passed as argument. Unsuccessful operations will display an error using + * OC.dialogs, no callback is fired. + * @callback removeCallback + * @param {string} oid the ID of the specific user or group + */ + +/** + * This callback is fired after "undo" was clicked so the consumer can update + * the web interface + * @callback undoCallback + * @param {string} oid the ID of the specific user or group + */ + +/** + * enabled the notification system. Required for undo UI. + * + * @param {object} notifier Usually OC.Notification + * @param {string} dataID an identifier for the notifier, e.g. 'deleteuser' + * @param {string} message the message that should be shown upon delete. %oid + * will be replaced with the affected id of the item to be deleted + * @param {undoCallback} undoCallback called after "undo" was clicked + */ +DeleteHandler.prototype.setNotification = function(notifier, dataID, message, undoCallback) { + this.notifier = notifier; + this.notificationDataID = dataID; + this.notificationMessage = message; + this.undoCallback = undoCallback; + + var dh = this; + + $('#notification').on('click', '.undo', function () { + if ($('#notification').data(dh.notificationDataID)) { + var oid = dh.oidToDelete; + dh.cancel(); + if(typeof dh.undoCallback !== 'undefined') { + dh.undoCallback(oid); + } + } + dh.notifier.hide(); + }); +}; + +/** + * shows the Undo Notification (if configured) + */ +DeleteHandler.prototype.showNotification = function() { + if(this.notifier !== false) { + if(!this.notifier.isHidden()) { + this.hideNotification(); + } + $('#notification').data(this.notificationDataID, true); + var msg = this.notificationMessage.replace(this.notificationPlaceholder, + this.oidToDelete); + this.notifier.showHtml(msg); + } +}; + +/** + * hides the Undo Notification + */ +DeleteHandler.prototype.hideNotification = function() { + if(this.notifier !== false) { + $('#notification').removeData(this.notificationDataID); + this.notifier.hide(); + } +}; + +/** + * initializes the delete operation for a given object id + * + * @param {string} oid the object id + */ +DeleteHandler.prototype.mark = function(oid) { + if(this.oidToDelete !== false) { + this.delete(); + } + this.oidToDelete = oid; + this.canceled = false; + this.markCallback(oid); + this.showNotification(); +}; + +/** + * cancels a delete operation + */ +DeleteHandler.prototype.cancel = function() { + this.canceled = true; + this.oidToDelete = false; +}; + +/** + * executes a delete operation. Requires that the operation has been + * initialized by mark(). On error, it will show a message via + * OC.dialogs.alert. On success, a callback is fired so that the client can + * update the web interface accordingly. + */ +DeleteHandler.prototype.delete = function() { + if(this.canceled || this.oidToDelete === false) { + return false; + } + + var dh = this; + if($('#notification').data(this.notificationDataID) === true) { + dh.hideNotification(); + } + + var payload = {}; + payload[dh.ajaxParamID] = dh.oidToDelete; + $.ajax({ + type: 'POST', + url: OC.filePath('settings', 'ajax', dh.ajaxEndpoint), + async: false, + data: payload, + success: function (result) { + if (result.status === 'success') { + // Remove undo option, & remove user from table + + //TODO: following line + dh.removeCallback(dh.oidToDelete); + dh.canceled = true; + } else { + OC.dialogs.alert(result.data.message, t('settings', 'Unable to delete ' + escapeHTML(dh.oidToDelete))); + dh.undoCallback(dh.oidToDelete); + } + } + }); +}; diff --git a/settings/js/users/filter.js b/settings/js/users/filter.js new file mode 100644 index 00000000000..1f7a29de0c9 --- /dev/null +++ b/settings/js/users/filter.js @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2014, Arthur Schiwon <blizzz@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + +/** + * @brief this object takes care of the filter functionality on the user + * management page + * @param jQuery input element that works as the user text input field + * @param object the UserList object + */ +function UserManagementFilter(filterInput, userList, groupList) { + this.filterInput = filterInput; + this.userList = userList; + this.groupList = groupList; + this.thread = undefined; + this.oldval = this.filterInput.val(); + + this.init(); +} + +/** + * @brief sets up when the filter action shall be triggered + */ +UserManagementFilter.prototype.init = function() { + var umf = this; + this.filterInput.keyup(function(e) { + //we want to react on any printable letter, plus on modifying stuff like + //Backspace and Delete. extended https://stackoverflow.com/a/12467610 + var valid = + e.keyCode === 0 || e.keyCode === 8 || // like ö or ж; backspace + e.keyCode === 9 || e.keyCode === 46 || // tab; delete + e.keyCode === 32 || // space + (e.keyCode > 47 && e.keyCode < 58) || // number keys + (e.keyCode > 64 && e.keyCode < 91) || // letter keys + (e.keyCode > 95 && e.keyCode < 112) || // numpad keys + (e.keyCode > 185 && e.keyCode < 193) || // ;=,-./` (in order) + (e.keyCode > 218 && e.keyCode < 223); // [\]' (in order) + + //besides the keys, the value must have been changed compared to last + //time + if(valid && umf.oldVal !== umf.getPattern()) { + umf.run(); + } + + umf.oldVal = umf.getPattern(); + }); +}; + +/** + * @brief the filter action needs to be done, here the accurate steps are being + * taken care of + */ +UserManagementFilter.prototype.run = _.debounce(function() { + this.userList.empty(); + this.userList.update(GroupList.getCurrentGID()); + this.groupList.empty(); + this.groupList.update(); + }, + 300 +); + +/** + * @brief returns the filter String + * @returns string + */ +UserManagementFilter.prototype.getPattern = function() { + return this.filterInput.val(); +}; + +/** + * @brief adds reset functionality to an HTML element + * @param jQuery the jQuery representation of that element + */ +UserManagementFilter.prototype.addResetButton = function(button) { + var umf = this; + button.click(function(){ + umf.filterInput.val(''); + umf.run(); + }); +}; diff --git a/settings/js/users/groups.js b/settings/js/users/groups.js new file mode 100644 index 00000000000..0ff8bdd6384 --- /dev/null +++ b/settings/js/users/groups.js @@ -0,0 +1,292 @@ +/** + * Copyright (c) 2014, Raghu Nayyar <beingminimal@gmail.com> + * Copyright (c) 2014, Arthur Schiwon <blizzz@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + +var $userGroupList; + +var GroupList; +GroupList = { + activeGID: '', + + addGroup: function (gid, usercount) { + var $li = $userGroupList.find('.isgroup:last-child').clone(); + $li + .data('gid', gid) + .find('.groupname').text(gid); + GroupList.setUserCount($li, usercount); + + $li.appendTo($userGroupList); + + GroupList.sortGroups(); + + return $li; + }, + + setUserCount: function (groupLiElement, usercount) { + var $groupLiElement = $(groupLiElement); + if (usercount === undefined || usercount === 0) { + usercount = ''; + } + $groupLiElement.data('usercount', usercount); + $groupLiElement.find('.usercount').text(usercount); + }, + + getCurrentGID: function () { + return GroupList.activeGID; + }, + + sortGroups: function () { + var lis = $('.isgroup').get(); + + lis.sort(function (a, b) { + return UserList.alphanum( + $(a).find('a span').text(), + $(b).find('a span').text() + ); + }); + + var items = []; + $.each(lis, function (index, li) { + items.push(li); + if (items.length === 100) { + $userGroupList.append(items); + items = []; + } + }); + if (items.length > 0) { + $userGroupList.append(items); + } + }, + + createGroup: function (groupname) { + $.post( + OC.filePath('settings', 'ajax', 'creategroup.php'), + { + groupname: groupname + }, + function (result) { + if (result.status !== 'success') { + OC.dialogs.alert(result.data.message, + t('settings', 'Error creating group')); + } + else { + if (result.data.groupname) { + var addedGroup = result.data.groupname; + UserList.availableGroups = $.unique($.merge(UserList.availableGroups, [addedGroup])); + GroupList.addGroup(result.data.groupname); + + $('.groupsselect, .subadminsselect') + .append($('<option>', { value: result.data.groupname }) + .text(result.data.groupname)); + } + GroupList.toggleAddGroup(); + } + } + ); + }, + + update: function () { + if (GroupList.updating) { + return; + } + GroupList.updating = true; + $.get( + OC.generateUrl('/settings/ajax/grouplist'), + {pattern: filter.getPattern()}, + function (result) { + + var lis = []; + if (result.status === 'success') { + $.each(result.data, function (i, subset) { + $.each(subset, function (index, group) { + if (GroupList.getGroupLI(group.name).length > 0) { + GroupList.setUserCount(GroupList.getGroupLI(group.name).first(), group.usercount); + } + else { + var $li = GroupList.addGroup(group.name, group.usercount); + + $li.addClass('appear transparent'); + lis.push($li); + } + }); + }); + if (result.data.length > 0) { + GroupList.doSort(); + } + else { + GroupList.noMoreEntries = true; + } + _.defer(function () { + $(lis).each(function () { + this.removeClass('transparent') + }); + }); + } + GroupList.updating = false; + + } + ); + }, + + elementBelongsToAddGroup: function (el) { + return !(el !== $('#newgroup-form').get(0) && + $('#newgroup-form').find($(el)).length === 0); + }, + + hasAddGroupNameText: function () { + var name = $('#newgroupname').val(); + return $.trim(name) !== ''; + + }, + + showGroup: function (gid) { + GroupList.activeGID = gid; + UserList.empty(); + UserList.update(gid); + $userGroupList.find('li').removeClass('active'); + if (gid !== undefined) { + //TODO: treat Everyone properly + GroupList.getGroupLI(gid).addClass('active'); + } + }, + + isAddGroupButtonVisible: function () { + return $('#newgroup-init').is(":visible"); + }, + + toggleAddGroup: function (event) { + if (GroupList.isAddGroupButtonVisible()) { + event.stopPropagation(); + $('#newgroup-form').show(); + $('#newgroup-init').hide(); + $('#newgroupname').focus(); + } + else { + $('#newgroup-form').hide(); + $('#newgroup-init').show(); + $('#newgroupname').val(''); + } + }, + + isGroupNameValid: function (groupname) { + if ($.trim(groupname) === '') { + OC.dialogs.alert( + t('settings', 'A valid group name must be provided'), + t('settings', 'Error creating group')); + return false; + } + return true; + }, + + hide: function (gid) { + GroupList.getGroupLI(gid).hide(); + }, + show: function (gid) { + GroupList.getGroupLI(gid).show(); + }, + remove: function (gid) { + GroupList.getGroupLI(gid).remove(); + }, + empty: function () { + $userGroupList.find('.isgroup').filter(function(index, item){ + return $(item).data('gid') !== ''; + }).remove(); + }, + initDeleteHandling: function () { + //set up handler + GroupDeleteHandler = new DeleteHandler('removegroup.php', 'groupname', + GroupList.hide, GroupList.remove); + + //configure undo + OC.Notification.hide(); + var msg = t('settings', 'deleted') + ' %oid <span class="undo">' + + t('settings', 'undo') + '</span>'; + GroupDeleteHandler.setNotification(OC.Notification, 'deletegroup', msg, + GroupList.show); + + //when to mark user for delete + $userGroupList.on('click', '.delete', function () { + // Call function for handling delete/undo + GroupDeleteHandler.mark(GroupList.getElementGID(this)); + }); + + //delete a marked user when leaving the page + $(window).on('beforeunload', function () { + GroupDeleteHandler.delete(); + }); + }, + + getGroupLI: function (gid) { + return $userGroupList.find('li.isgroup').filter(function () { + return GroupList.getElementGID(this) === gid; + }); + }, + + getElementGID: function (element) { + return ($(element).closest('li').data('gid') || '').toString(); + } +}; + +$(document).ready( function () { + $userGroupList = $('#usergrouplist'); + GroupList.initDeleteHandling(); + + // Display or hide of Create Group List Element + $('#newgroup-form').hide(); + $('#newgroup-init').on('click', function (e) { + GroupList.toggleAddGroup(e); + }); + + $(document).on('click keydown keyup', function(event) { + if(!GroupList.isAddGroupButtonVisible() && + !GroupList.elementBelongsToAddGroup(event.target) && + !GroupList.hasAddGroupNameText()) { + GroupList.toggleAddGroup(); + } + // Escape + if(!GroupList.isAddGroupButtonVisible() && event.keyCode && event.keyCode === 27) { + GroupList.toggleAddGroup(); + } + }); + + + // Responsible for Creating Groups. + $('#newgroup-form form').submit(function (event) { + event.preventDefault(); + if(GroupList.isGroupNameValid($('#newgroupname').val())) { + GroupList.createGroup($('#newgroupname').val()); + } + }); + + // click on group name + $userGroupList.on('click', '.isgroup', function () { + GroupList.showGroup(GroupList.getElementGID(this)); + }); + + // Implements Quota Settings Toggle. + var $appSettings = $('#app-settings'); + $('#app-settings-header').on('click keydown',function(event) { + if(wrongKey(event)) { + return; + } + if($appSettings.hasClass('open')) { + $appSettings.switchClass('open', ''); + } else { + $appSettings.switchClass('', 'open'); + } + }); + $('body').on('click', function(event){ + if($appSettings.find(event.target).length === 0) { + $appSettings.switchClass('open', ''); + } + }); + +}); + +var wrongKey = function(event) { + return ((event.type === 'keydown' || event.type === 'keypress') && + (event.keyCode !== 32 && event.keyCode !== 13)); +}; diff --git a/settings/js/users/users.js b/settings/js/users/users.js new file mode 100644 index 00000000000..68098e03a50 --- /dev/null +++ b/settings/js/users/users.js @@ -0,0 +1,616 @@ +/** + * Copyright (c) 2014, Arthur Schiwon <blizzz@owncloud.com> + * Copyright (c) 2014, Raghu Nayyar <beingminimal@gmail.com> + * Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com> + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + +var $userList; +var $userListBody; +var filter; + +var UserList = { + availableGroups: [], + offset: 30, //The first 30 users are there. No prob, if less in total. + //hardcoded in settings/users.php + + usersToLoad: 10, //So many users will be loaded when user scrolls down + currentGid: '', + + add: function (username, displayname, groups, subadmin, quota, storageLocation, lastLogin, sort) { + var $tr = $userListBody.find('tr:first-child').clone(); + var subadminsEl; + var subadminSelect; + var groupsSelect; + if ($tr.find('div.avatardiv').length){ + $tr.find('.avatardiv').imageplaceholder(username, displayname); + $('div.avatardiv', $tr).avatar(username, 32); + } + $tr.data('uid', username); + $tr.data('displayname', displayname); + $tr.find('td.name').text(username); + $tr.find('td.displayName > span').text(displayname); + + // make them look like the multiselect buttons + // until they get time to really get initialized + groupsSelect = $('<select multiple="multiple" class="groupsselect multiselect button" data-placehoder="Groups" title="' + t('settings', 'Groups') + '"></select>') + .data('username', username) + .data('user-groups', groups); + if ($tr.find('td.subadmins').length > 0) { + subadminSelect = $('<select multiple="multiple" class="subadminsselect multiselect button" data-placehoder="subadmins" title="' + t('settings', 'Group Admin') + '">') + .data('username', username) + .data('user-groups', groups) + .data('subadmin', subadmin); + $tr.find('td.subadmins').empty(); + } + $.each(this.availableGroups, function (i, group) { + groupsSelect.append($('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>')); + if (typeof subadminSelect !== 'undefined' && group !== 'admin') { + subadminSelect.append($('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>')); + } + }); + $tr.find('td.groups').empty().append(groupsSelect); + subadminsEl = $tr.find('td.subadmins'); + if (subadminsEl.length > 0) { + subadminsEl.append(subadminSelect); + } + if ($tr.find('td.remove img').length === 0 && OC.currentUser !== username) { + var deleteImage = $('<img class="svg action">').attr({ + src: OC.imagePath('core', 'actions/delete') + }); + var deleteLink = $('<a class="action delete">') + .attr({ href: '#', 'original-title': t('settings', 'Delete')}) + .append(deleteImage); + $tr.find('td.remove').append(deleteLink); + } else if (OC.currentUser === username) { + $tr.find('td.remove a').remove(); + } + var $quotaSelect = $tr.find('.quota-user'); + if (quota === 'default') { + $quotaSelect + .data('previous', 'default') + .find('option').attr('selected', null) + .first().attr('selected', 'selected'); + } else { + if ($quotaSelect.find('option[value="' + quota + '"]').length > 0) { + $quotaSelect.find('option[value="' + quota + '"]').attr('selected', 'selected'); + } else { + $quotaSelect.append('<option value="' + escapeHTML(quota) + '" selected="selected">' + escapeHTML(quota) + '</option>'); + } + } + $tr.find('td.storageLocation').text(storageLocation); + if(lastLogin === 0) { + lastLogin = t('settings', 'never'); + } else { + lastLogin = new Date(lastLogin * 1000); + lastLogin = relative_modified_date(lastLogin.getTime() / 1000); + } + $tr.find('td.lastLogin').text(lastLogin); + $tr.appendTo($userList); + if(UserList.isEmpty === true) { + //when the list was emptied, one row was left, necessary to keep + //add working and the layout unbroken. We need to remove this item + $tr.show(); + $userListBody.find('tr:first').remove(); + UserList.isEmpty = false; + UserList.checkUsersToLoad(); + } + if (sort) { + UserList.doSort(); + } + + $quotaSelect.on('change', function () { + var uid = UserList.getUID(this); + var quota = $(this).val(); + setQuota(uid, quota, function(returnedQuota){ + if (quota !== returnedQuota) { + $($quotaSelect).find(':selected').text(returnedQuota); + } + }); + }); + + // defer init so the user first sees the list appear more quickly + window.setTimeout(function(){ + $quotaSelect.singleSelect(); + UserList.applyGroupSelect(groupsSelect); + if (subadminSelect) { + UserList.applySubadminSelect(subadminSelect); + } + }, 0); + return $tr; + }, + // From http://my.opera.com/GreyWyvern/blog/show.dml/1671288 + alphanum: function(a, b) { + function chunkify(t) { + var tz = [], x = 0, y = -1, n = 0, i, j; + + while (i = (j = t.charAt(x++)).charCodeAt(0)) { + var m = (i === 46 || (i >=48 && i <= 57)); + if (m !== n) { + tz[++y] = ""; + n = m; + } + tz[y] += j; + } + return tz; + } + + var aa = chunkify(a.toLowerCase()); + var bb = chunkify(b.toLowerCase()); + + for (var x = 0; aa[x] && bb[x]; x++) { + if (aa[x] !== bb[x]) { + var c = Number(aa[x]), d = Number(bb[x]); + if (c === aa[x] && d === bb[x]) { + return c - d; + } else { + return (aa[x] > bb[x]) ? 1 : -1; + } + } + } + return aa.length - bb.length; + }, + preSortSearchString: function(a, b) { + var pattern = filter.getPattern(); + if(typeof pattern === 'undefined') { + return undefined; + } + pattern = pattern.toLowerCase(); + var aMatches = false; + var bMatches = false; + if(typeof a === 'string' && a.toLowerCase().indexOf(pattern) === 0) { + aMatches = true; + } + if(typeof b === 'string' && b.toLowerCase().indexOf(pattern) === 0) { + bMatches = true; + } + + if((aMatches && bMatches) || (!aMatches && !bMatches)) { + return undefined; + } + + if(aMatches) { + return -1; + } else { + return 1; + } + }, + doSort: function() { + var rows = $userListBody.find('tr').get(); + + rows.sort(function(a, b) { + a = $(a).find('td.name').text(); + b = $(b).find('td.name').text(); + var firstSort = UserList.preSortSearchString(a, b); + if(typeof firstSort !== 'undefined') { + return firstSort; + } + return UserList.alphanum(a, b); + }); + + var items = []; + $.each(rows, function(index, row) { + items.push(row); + if(items.length === 100) { + $userListBody.append(items); + items = []; + } + }); + if(items.length > 0) { + $userListBody.append(items); + } + }, + checkUsersToLoad: function() { + //30 shall be loaded initially, from then on always 10 upon scrolling + if(UserList.isEmpty === false) { + UserList.usersToLoad = 10; + } else { + UserList.usersToLoad = 30; + } + }, + empty: function() { + //one row needs to be kept, because it is cloned to add new rows + $userListBody.find('tr:not(:first)').remove(); + var $tr = $userListBody.find('tr:first'); + $tr.hide(); + //on an update a user may be missing when the username matches with that + //of the hidden row. So change this to a random string. + $tr.data('uid', Math.random().toString(36).substring(2)); + UserList.isEmpty = true; + UserList.offset = 0; + UserList.checkUsersToLoad(); + }, + hide: function(uid) { + UserList.getRow(uid).hide(); + }, + show: function(uid) { + UserList.getRow(uid).show(); + }, + remove: function(uid) { + UserList.getRow(uid).remove(); + }, + has: function(uid) { + return UserList.getRow(uid).length > 0; + }, + getRow: function(uid) { + return $userListBody.find('tr').filter(function(){ + return UserList.getUID(this) === uid; + }); + }, + getUID: function(element) { + return ($(element).closest('tr').data('uid') || '').toString(); + }, + getDisplayName: function(element) { + return ($(element).closest('tr').data('displayname') || '').toString(); + }, + initDeleteHandling: function() { + //set up handler + UserDeleteHandler = new DeleteHandler('removeuser.php', 'username', + UserList.hide, UserList.remove); + + //configure undo + OC.Notification.hide(); + var msg = t('settings', 'deleted') + ' %oid <span class="undo">' + + t('settings', 'undo') + '</span>'; + UserDeleteHandler.setNotification(OC.Notification, 'deleteuser', msg, + UserList.show); + + //when to mark user for delete + $userListBody.on('click', '.delete', function () { + // Call function for handling delete/undo + var uid = UserList.getUID(this); + UserDeleteHandler.mark(uid); + }); + + //delete a marked user when leaving the page + $(window).on('beforeunload', function () { + UserDeleteHandler.delete(); + }); + }, + update: function (gid) { + if (UserList.updating) { + return; + } + $userList.siblings('.loading').css('visibility', 'visible'); + UserList.updating = true; + if(gid === undefined) { + gid = ''; + } + UserList.currentGid = gid; + var pattern = filter.getPattern(); + $.get( + OC.generateUrl('/settings/ajax/userlist'), + { offset: UserList.offset, limit: UserList.usersToLoad, gid: gid, pattern: pattern }, + function (result) { + var loadedUsers = 0; + var trs = []; + if (result.status === 'success') { + //The offset does not mirror the amount of users available, + //because it is backend-dependent. For correct retrieval, + //always the limit(requested amount of users) needs to be added. + $.each(result.data, function (index, user) { + if(UserList.has(user.name)) { + return true; + } + var $tr = UserList.add(user.name, user.displayname, user.groups, user.subadmin, user.quota, user.storageLocation, user.lastLogin, false); + $tr.addClass('appear transparent'); + trs.push($tr); + loadedUsers++; + }); + if (result.data.length > 0) { + UserList.doSort(); + $userList.siblings('.loading').css('visibility', 'hidden'); + } + else { + UserList.noMoreEntries = true; + $userList.siblings('.loading').remove(); + } + UserList.offset += loadedUsers; + // animate + setTimeout(function() { + for (var i = 0; i < trs.length; i++) { + trs[i].removeClass('transparent'); + } + }, 0); + } + UserList.updating = false; + }); + }, + + applyGroupSelect: function (element) { + var checked = []; + var $element = $(element); + var user = UserList.getUID($element); + + if ($element.data('user-groups')) { + checked = $element.data('user-groups'); + } + var checkHandler = null; + if(user) { // Only if in a user row, and not the #newusergroups select + checkHandler = function (group) { + if (user === OC.currentUser && group === 'admin') { + return false; + } + if (!oc_isadmin && checked.length === 1 && checked[0] === group) { + return false; + } + $.post( + OC.filePath('settings', 'ajax', 'togglegroups.php'), + { + username: user, + group: group + }, + function (response) { + if (response.status === 'success') { + GroupList.update(); + if (UserList.availableGroups.indexOf(response.data.groupname) === -1 && + response.data.action === 'add' + ) { + UserList.availableGroups.push(response.data.groupname); + } + } + if (response.data.message) { + OC.Notification.show(response.data.message); + } + } + ); + } + }; + var addGroup = function (select, group) { + $('select[multiple]').each(function (index, element) { + $element = $(element); + if ($element.find('option[value="' + group + '"]').length === 0 && select.data('msid') !== $element.data('msid')) { + $element.append('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>'); + } + }); + GroupList.addGroup(escapeHTML(group)); + }; + var label; + if (oc_isadmin) { + label = t('settings', 'add group'); + } + else { + label = null; + } + $element.multiSelect({ + createCallback: addGroup, + createText: label, + selectedFirst: true, + checked: checked, + oncheck: checkHandler, + onuncheck: checkHandler, + minWidth: 100 + }); + }, + + applySubadminSelect: function (element) { + var checked = []; + var $element = $(element); + var user = UserList.getUID($element); + + if ($element.data('subadmin')) { + checked = $element.data('subadmin'); + } + var checkHandler = function (group) { + if (group === 'admin') { + return false; + } + $.post( + OC.filePath('settings', 'ajax', 'togglesubadmins.php'), + { + username: user, + group: group + }, + function () { + } + ); + }; + + var addSubAdmin = function (group) { + $('select[multiple]').each(function (index, element) { + if ($(element).find('option[value="' + group + '"]').length === 0) { + $(element).append('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>'); + } + }); + }; + $element.multiSelect({ + createCallback: addSubAdmin, + createText: null, + checked: checked, + oncheck: checkHandler, + onuncheck: checkHandler, + minWidth: 100 + }); + }, + + _onScroll: function() { + if (!!UserList.noMoreEntries) { + return; + } + if (UserList.scrollArea.scrollTop() + UserList.scrollArea.height() > UserList.scrollArea.get(0).scrollHeight - 500) { + UserList.update(UserList.currentGid, true); + } + } +}; + +function setQuota (uid, quota, ready) { + $.post( + OC.filePath('settings', 'ajax', 'setquota.php'), + {username: uid, quota: quota}, + function (result) { + if (ready) { + ready(result.data.quota); + } + } + ); +} + +$(document).ready(function () { + $userList = $('#userlist'); + $userListBody = $userList.find('tbody'); + + UserList.initDeleteHandling(); + + // Implements User Search + filter = new UserManagementFilter($('#usersearchform input'), UserList, GroupList); + + UserList.doSort(); + UserList.availableGroups = $userList.data('groups'); + + + UserList.scrollArea = $('#app-content'); + UserList.scrollArea.scroll(function(e) {UserList._onScroll(e);}); + + + $userList.after($('<div class="loading" style="height: 200px; visibility: hidden;"></div>')); + + $('.groupsselect').each(function (index, element) { + UserList.applyGroupSelect(element); + }); + $('.subadminsselect').each(function (index, element) { + UserList.applySubadminSelect(element); + }); + + $userListBody.on('click', '.password', function (event) { + event.stopPropagation(); + + var $td = $(this).closest('td'); + var uid = UserList.getUID($td); + var $input = $('<input type="password">'); + $td.find('img').hide(); + $td.children('span').replaceWith($input); + $input + .focus() + .keypress(function (event) { + if (event.keyCode === 13) { + if ($(this).val().length > 0) { + var recoveryPasswordVal = $('input:password[id="recoveryPassword"]').val(); + $.post( + OC.generateUrl('/settings/users/changepassword'), + {username: uid, password: $(this).val(), recoveryPassword: recoveryPasswordVal}, + function (result) { + if (result.status != 'success') { + OC.Notification.show(t('admin', result.data.message)); + } + } + ); + $input.blur(); + } else { + $input.blur(); + } + } + }) + .blur(function () { + $(this).replaceWith($('<span>●●●●●●●</span>')); + $td.find('img').show(); + }); + }); + $('input:password[id="recoveryPassword"]').keyup(function() { + OC.Notification.hide(); + }); + + $userListBody.on('click', '.displayName', function (event) { + event.stopPropagation(); + var $td = $(this).closest('td'); + var $tr = $td.closest('tr'); + var uid = UserList.getUID($td); + var displayName = escapeHTML(UserList.getDisplayName($td)); + var $input = $('<input type="text" value="' + displayName + '">'); + $td.find('img').hide(); + $td.children('span').replaceWith($input); + $input + .focus() + .keypress(function (event) { + if (event.keyCode === 13) { + if ($(this).val().length > 0) { + $tr.find('.avatardiv').imageplaceholder(uid, displayName); + $.post( + OC.filePath('settings', 'ajax', 'changedisplayname.php'), + {username: uid, displayName: $(this).val()}, + function (result) { + if (result && result.status==='success'){ + $tr.find('.avatardiv').avatar(result.data.username, 32); + } + } + ); + $input.blur(); + } else { + $input.blur(); + } + } + }) + .blur(function () { + var displayName = $input.val(); + $tr.data('displayname', displayName); + $input.replaceWith('<span>' + escapeHTML(displayName) + '</span>'); + $td.find('img').show(); + }); + }); + + $('#default_quota, .quota-user').singleSelect().on('change', function () { + var $select = $(this); + var uid = UserList.getUID($select); + var quota = $select.val(); + setQuota(uid, quota, function(returnedQuota){ + if (quota !== returnedQuota) { + $select.find(':selected').text(returnedQuota); + } + }); + }); + + $('#newuser').submit(function (event) { + event.preventDefault(); + var username = $('#newusername').val(); + var password = $('#newuserpassword').val(); + if ($.trim(username) === '') { + OC.dialogs.alert( + t('settings', 'A valid username must be provided'), + t('settings', 'Error creating user')); + return false; + } + if ($.trim(password) === '') { + OC.dialogs.alert( + t('settings', 'A valid password must be provided'), + t('settings', 'Error creating user')); + return false; + } + var groups = $('#newusergroups').val(); + $('#newuser').get(0).reset(); + $.post( + OC.filePath('settings', 'ajax', 'createuser.php'), + { + username: username, + password: password, + groups: groups + }, + function (result) { + if (result.status !== 'success') { + OC.dialogs.alert(result.data.message, + t('settings', 'Error creating user')); + } else { + if (result.data.groups) { + var addedGroups = result.data.groups; + UserList.availableGroups = $.unique($.merge(UserList.availableGroups, addedGroups)); + } + if (result.data.homeExists){ + OC.Notification.hide(); + OC.Notification.show(t('settings', 'Warning: Home directory for user "{user}" already exists', {user: result.data.username})); + if (UserList.notificationTimeout){ + window.clearTimeout(UserList.notificationTimeout); + } + UserList.notificationTimeout = window.setTimeout( + function(){ + OC.Notification.hide(); + UserList.notificationTimeout = null; + }, 10000); + } + if(!UserList.has(username)) { + UserList.add(username, username, result.data.groups, null, 'default', result.data.storageLocation, 0, true); + } + } + } + ); + }); + +}); |