diff --git a/install/package.json b/install/package.json index 0b92fa2ea9..f3d3b431cc 100644 --- a/install/package.json +++ b/install/package.json @@ -75,9 +75,9 @@ "nodebb-plugin-spam-be-gone": "0.5.4", "nodebb-rewards-essentials": "0.0.11", "nodebb-theme-lavender": "5.0.5", - "nodebb-theme-persona": "9.0.17", - "nodebb-theme-slick": "1.2.5", - "nodebb-theme-vanilla": "10.0.15", + "nodebb-theme-persona": "9.0.18", + "nodebb-theme-slick": "1.2.6", + "nodebb-theme-vanilla": "10.0.16", "nodebb-widget-essentials": "4.0.7", "nodemailer": "^4.6.5", "passport": "^0.4.0", diff --git a/public/language/en-GB/groups.json b/public/language/en-GB/groups.json index 08c8d4d1f5..c18335bb5e 100644 --- a/public/language/en-GB/groups.json +++ b/public/language/en-GB/groups.json @@ -33,7 +33,7 @@ "details.grant": "Grant/Rescind Ownership", "details.kick": "Kick", "details.kick_confirm": "Are you sure you want to remove this member from the group?", - + "details.add-member": "Add Member", "details.owner_options": "Group Administration", "details.group_name": "Group Name", "details.member_count": "Member Count", diff --git a/public/src/admin/manage/group.js b/public/src/admin/manage/group.js index 95e1751ff6..92ef056630 100644 --- a/public/src/admin/manage/group.js +++ b/public/src/admin/manage/group.js @@ -5,20 +5,14 @@ define('admin/manage/group', [ 'forum/groups/memberlist', 'iconSelect', 'admin/modules/colorpicker', - 'translator', - 'benchpress', -], function (memberList, iconSelect, colorpicker, translator, Benchpress) { +], function (memberList, iconSelect, colorpicker) { var Groups = {}; Groups.init = function () { - var groupDetailsSearch = $('#group-details-search'); - var groupDetailsSearchResults = $('#group-details-search-results'); var groupIcon = $('#group-icon'); var changeGroupUserTitle = $('#change-group-user-title'); var changeGroupLabelColor = $('#change-group-label-color'); var groupLabelPreview = $('#group-label-preview'); - var searchDelay; - var groupName = ajaxify.data.group.name; @@ -36,87 +30,6 @@ define('admin/manage/group', [ groupLabelPreview.css('background', changeGroupLabelColor.val() || '#000000'); }); - groupDetailsSearch.on('keyup', function () { - if (searchDelay) { - clearTimeout(searchDelay); - } - - searchDelay = setTimeout(function () { - var searchText = groupDetailsSearch.val(); - var foundUser; - - socket.emit('admin.user.search', { - query: searchText, - }, function (err, results) { - if (!err && results && results.users.length > 0) { - var numResults = results.users.length; - var x; - if (numResults > 20) { - numResults = 20; - } - - groupDetailsSearchResults.empty(); - - for (x = 0; x < numResults; x += 1) { - foundUser = $('
  • '); - foundUser - .attr({ - title: results.users[x].username, - 'data-uid': results.users[x].uid, - 'data-username': results.users[x].username, - 'data-userslug': results.users[x].userslug, - 'data-picture': results.users[x].picture, - 'data-usericon-bgColor': results.users[x]['icon:bgColor'], - 'data-usericon-text': results.users[x]['icon:text'], - }) - .append(results.users[x].picture ? - $('').addClass('avatar avatar-sm').attr('src', results.users[x].picture) : - $('
    ').addClass('avatar avatar-sm').css('background-color', results.users[x]['icon:bgColor']).html(results.users[x]['icon:text'])) - .append($('').html(results.users[x].username)); - - groupDetailsSearchResults.append(foundUser); - } - } else { - groupDetailsSearchResults.translateHtml('
  • [[admin/manage/groups:edit.no-users-found]]
  • '); - } - }); - }, 200); - }); - - groupDetailsSearchResults.on('click', 'li[data-uid]', function () { - var userLabel = $(this); - var uid = parseInt(userLabel.attr('data-uid'), 10); - - socket.emit('admin.groups.join', { - groupName: groupName, - uid: uid, - }, function (err) { - if (err) { - return app.alertError(err.message); - } - - var member = { - uid: userLabel.attr('data-uid'), - username: userLabel.attr('data-username'), - userslug: userLabel.attr('data-userslug'), - picture: userLabel.attr('data-picture'), - 'icon:bgColor': userLabel.attr('data-usericon-bgColor'), - 'icon:text': userLabel.attr('data-usericon-text'), - }; - - Benchpress.parse('admin/partials/groups/memberlist', 'group.members', { - group: { - isOwner: ajaxify.data.group.isOwner, - members: [member], - }, - }, function (html) { - translator.translate(html, function (html) { - $('[component="groups/members"] tbody').prepend(html); - }); - }); - }); - }); - $('[component="groups/members"]').on('click', '[data-action]', function () { var btnEl = $(this); var userRow = btnEl.parents('[data-uid]'); diff --git a/public/src/client/groups/memberlist.js b/public/src/client/groups/memberlist.js index cc3b36ce3c..82e2cdc9a7 100644 --- a/public/src/client/groups/memberlist.js +++ b/public/src/client/groups/memberlist.js @@ -1,7 +1,7 @@ 'use strict'; -define('forum/groups/memberlist', ['components', 'forum/infinitescroll'], function () { +define('forum/groups/memberlist', ['autocomplete'], function (autocomplete) { var MemberList = {}; var searchInterval; var groupName; @@ -11,10 +11,40 @@ define('forum/groups/memberlist', ['components', 'forum/infinitescroll'], functi templateName = _templateName || 'groups/details'; groupName = ajaxify.data.group.name; + handleMemberAdd(); handleMemberSearch(); handleMemberInfiniteScroll(); }; + function handleMemberAdd() { + $('[component="groups/members/add"]').on('click', function () { + var modal = bootbox.dialog({ + title: '[[groups:details.add-member]]', + message: '', + }); + autocomplete.user(modal.find('input'), function (ev, ui) { + var user = ui.item.user; + if (user) { + addUserToGroup(user, function () { + modal.modal('hide'); + }); + } + }); + }); + } + + function addUserToGroup(user, callback) { + socket.emit('groups.addMember', { groupName: groupName, uid: user.uid }, function (err) { + if (err) { + return app.alertError(err); + } + parseAndTranslate([user], function (html) { + $('[component="groups/members"] tbody').prepend(html); + }); + callback(); + }); + } + function handleMemberSearch() { $('[component="groups/members/search"]').on('keyup', function () { var query = $(this).val(); diff --git a/src/socket.io/groups.js b/src/socket.io/groups.js index e98b8451c6..033a4e7a4b 100644 --- a/src/socket.io/groups.js +++ b/src/socket.io/groups.js @@ -71,14 +71,27 @@ SocketGroups.leave = function (socket, data, callback) { groups.leave(data.groupName, socket.uid, callback); }; +SocketGroups.addMember = isOwner(function (socket, data, callback) { + if (data.groupName === 'administrators' || groups.isPrivilegeGroup(data.groupName)) { + return callback(new Error('[[error:not-allowed]]')); + } + groups.join(data.groupName, data.uid, callback); +}); + function isOwner(next) { return function (socket, data, callback) { async.parallel({ isAdmin: async.apply(user.isAdministrator, socket.uid), + isGlobalModerator: async.apply(user.isGlobalModerator, socket.uid), isOwner: async.apply(groups.ownership.isOwner, socket.uid, data.groupName), + group: async.apply(groups.getGroupData, data.groupName), }, function (err, results) { - if (err || (!results.isOwner && !results.isAdmin)) { - return callback(err || new Error('[[error:no-privileges]]')); + if (err) { + return callback(err); + } + var isOwner = results.isOwner || results.isAdmin || (results.isGlobalModerator && !results.group.system); + if (!isOwner) { + return callback(new Error('[[error:no-privileges]]')); } next(socket, data, callback); }); diff --git a/src/views/admin/manage/group.tpl b/src/views/admin/manage/group.tpl index b9170df21a..51301f8e56 100644 --- a/src/views/admin/manage/group.tpl +++ b/src/views/admin/manage/group.tpl @@ -74,13 +74,6 @@ -
    - - - - -
    -
    diff --git a/src/views/admin/partials/groups/memberlist.tpl b/src/views/admin/partials/groups/memberlist.tpl index f7456de2b5..c6aae28af7 100644 --- a/src/views/admin/partials/groups/memberlist.tpl +++ b/src/views/admin/partials/groups/memberlist.tpl @@ -1,7 +1,16 @@ -
    - - -

    +
    + +
    + +
    + +
    +
    + + +
    +
    +
    @@ -10,9 +19,9 @@
    - + -
    {group.members.icon:text}
    +
    {group.members.icon:text}