v1.18.x
barisusakli 10 years ago
parent 47e2dd9478
commit e2a5440ae8

@ -77,7 +77,8 @@
"group-name-too-short": "Group name too short",
"group-already-exists": "Group already exists",
"group-name-change-not-allowed": "Group name change not allowed",
"group-already-member": "You are already part of this group",
"group-already-member": "Already part of this group",
"group-not-member": "Not a member of this group",
"group-needs-owner": "This group requires at least one owner",
"group-already-invited": "This user has already been invited",
"group-already-requested": "Your membership request has already been submitted",

@ -1,5 +1,20 @@
.group {
.current_members {
[component="groups/members"] {
padding: 0;
tbody {
max-height: 500px;
display: block;
overflow-y: auto;
padding-bottom: 100px;
.member-name {
width: 100%;
}
}
img {
width: 32px;
height: 32px;
}
}
}

@ -1,16 +1,16 @@
"use strict";
/*global define, templates, socket, ajaxify, app, admin, bootbox, utils, config */
/*global define, templates, socket, ajaxify, app, bootbox, translator */
define('admin/manage/group', [
'forum/groups/memberlist',
'iconSelect',
'admin/modules/colorpicker'
], function(iconSelect, colorpicker) {
], function(memberList, iconSelect, colorpicker) {
var Groups = {};
Groups.init = function() {
var groupDetailsSearch = $('#group-details-search'),
groupDetailsSearchResults = $('#group-details-search-results'),
groupMembersEl = $('ul.current_members'),
groupIcon = $('#group-icon'),
changeGroupUserTitle = $('#change-group-user-title'),
changeGroupLabelColor = $('#change-group-label-color'),
@ -20,6 +20,8 @@ define('admin/manage/group', [
var groupName = ajaxify.data.group.name;
memberList.init(true);
changeGroupUserTitle.keyup(function() {
groupLabelPreview.text(changeGroupUserTitle.val());
});
@ -46,10 +48,17 @@ define('admin/manage/group', [
}
groupDetailsSearchResults.empty();
for (x = 0; x < numResults; x++) {
foundUser = $('<li />');
foundUser
.attr({title: results.users[x].username, 'data-uid': results.users[x].uid})
.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
})
.append($('<img />').attr('src', results.users[x].picture))
.append($('<span />').html(results.users[x].username));
@ -64,45 +73,74 @@ define('admin/manage/group', [
groupDetailsSearchResults.on('click', 'li[data-uid]', function() {
var userLabel = $(this),
uid = parseInt(userLabel.attr('data-uid'), 10),
members = [];
groupMembersEl.find('li[data-uid]').each(function() {
members.push(parseInt($(this).attr('data-uid'), 10));
});
if (members.indexOf(uid) === -1) {
socket.emit('admin.groups.join', {
groupName: groupName,
uid: uid
}, function(err, data) {
if (!err) {
groupMembersEl.append(userLabel.clone(true));
}
});
}
});
groupMembersEl.on('click', 'li[data-uid]', function() {
var uid = $(this).attr('data-uid');
uid = parseInt(userLabel.attr('data-uid'), 10);
bootbox.confirm('Are you sure you want to remove this user?', function(confirm) {
if (!confirm) {
return;
socket.emit('admin.groups.join', {
groupName: groupName,
uid: uid
}, function(err) {
if (err) {
return app.alertError(err.message);
}
socket.emit('admin.groups.leave', {
groupName: groupName,
uid: uid
}, function(err, data) {
if (err) {
return app.alertError(err.message);
}
groupMembersEl.find('li[data-uid="' + uid + '"]').remove();
var member = {
uid: userLabel.attr('data-uid'),
username: userLabel.attr('data-username'),
userslug: userLabel.attr('data-userslug'),
picture: userLabel.attr('data-picture')
};
templates.parse('partials/groups/memberlist', 'members', {group: {isOwner: ajaxify.data.group.isOwner, members: [member]}}, function(html) {
translator.translate(html, function(html) {
$('[component="groups/members"] tr').first().before(html);
});
});
});
});
$('[component="groups/members"]').on('click', '[data-action]', function() {
var btnEl = $(this),
userRow = btnEl.parents('[data-uid]'),
ownerFlagEl = userRow.find('.member-name i'),
isOwner = !ownerFlagEl.hasClass('invisible') ? true : false,
uid = userRow.attr('data-uid'),
action = btnEl.attr('data-action');
switch(action) {
case 'toggleOwnership':
socket.emit('groups.' + (isOwner ? 'rescind' : 'grant'), {
toUid: uid,
groupName: groupName
}, function(err) {
if (err) {
return app.alertError(err.message);
}
ownerFlagEl.toggleClass('invisible');
});
break;
case 'kick':
bootbox.confirm('Are you sure you want to remove this user?', function(confirm) {
if (!confirm) {
return;
}
socket.emit('admin.groups.leave', {
uid: uid,
groupName: groupName
}, function(err) {
if (err) {
return app.alertError(err.message);
}
userRow.slideUp().remove();
});
});
break;
default:
break;
}
});
$('#group-icon').on('click', function() {
iconSelect.init(groupIcon);
});

@ -1,17 +1,22 @@
"use strict";
/* globals define, socket, ajaxify, app, bootbox, RELATIVE_PATH, utils */
/* globals define, socket, ajaxify, app, bootbox, utils */
define('forum/groups/details', [
'forum/groups/memberlist',
'iconSelect',
'components',
'vendor/colorpicker/colorpicker',
'vendor/jquery/draggable-background/backgroundDraggable'
], function(memberList, iconSelect, components) {
define('forum/groups/details', ['iconSelect', 'components', 'forum/infinitescroll', 'vendor/colorpicker/colorpicker', 'vendor/jquery/draggable-background/backgroundDraggable'], function(iconSelect, components, infinitescroll) {
var Details = {
cover: {}
};
var searchInterval;
var groupName;
Details.init = function() {
var detailsPage = components.get('groups/container'),
settingsFormEl = detailsPage.find('form');
var detailsPage = components.get('groups/container');
groupName = ajaxify.data.group.name;
@ -20,8 +25,8 @@ define('forum/groups/details', ['iconSelect', 'components', 'forum/infinitescrol
Details.initialiseCover();
}
handleMemberSearch();
handleMemberInfiniteScroll();
memberList.init();
handleMemberInvitations();
components.get('groups/activity').find('.content img:not(.not-responsive)').addClass('img-responsive');
@ -291,44 +296,6 @@ define('forum/groups/details', ['iconSelect', 'components', 'forum/infinitescrol
});
};
function handleMemberSearch() {
$('[component="groups/members/search"]').on('keyup', function() {
var query = $(this).val();
if (searchInterval) {
clearInterval(searchInterval);
searchInterval = 0;
}
searchInterval = setTimeout(function() {
socket.emit('groups.searchMembers', {groupName: groupName, query: query}, function(err, results) {
if (err) {
return app.alertError(err.message);
}
infinitescroll.parseAndTranslate('groups/details', 'members', {
group: {
members: results.users,
isOwner: ajaxify.data.group.isOwner
}
}, function(html) {
$('[component="groups/members"] tbody').html(html);
$('[component="groups/members"]').attr('data-nextstart', 20);
});
});
}, 250);
});
}
function handleMemberInfiniteScroll() {
$('[component="groups/members"] tbody').on('scroll', function() {
var $this = $(this);
var bottom = ($this[0].scrollHeight - $this.height()) * 0.9;
if ($this.scrollTop() > bottom) {
loadMoreMembers();
}
});
}
function handleMemberInvitations() {
if (ajaxify.data.group.isOwner) {
var searchInput = $('[component="groups/members/invite"]');
@ -349,48 +316,5 @@ define('forum/groups/details', ['iconSelect', 'components', 'forum/infinitescrol
}
}
function loadMoreMembers() {
var members = $('[component="groups/members"]');
if (members.attr('loading')) {
return;
}
members.attr('loading', 1);
socket.emit('groups.loadMoreMembers', {
groupName: groupName,
after: members.attr('data-nextstart')
}, function(err, data) {
if (err) {
return app.alertError(err.message);
}
if (data && data.users.length) {
onMembersLoaded(data.users, function() {
members.removeAttr('loading');
members.attr('data-nextstart', data.nextStart);
});
} else {
members.removeAttr('loading');
}
});
}
function onMembersLoaded(users, callback) {
users = users.filter(function(user) {
return !$('[component="groups/members"] [data-uid="' + user.uid + '"]').length;
});
infinitescroll.parseAndTranslate('groups/details', 'members', {
group: {
members: users,
isOwner: ajaxify.data.group.isOwner
}
}, function(html) {
$('[component="groups/members"] tbody').append(html);
callback();
});
}
return Details;
});

@ -0,0 +1,97 @@
"use strict";
/* globals define, socket, ajaxify, app */
define('forum/groups/memberlist', ['components', 'forum/infinitescroll'], function(components, infinitescroll) {
var MemberList = {};
var searchInterval;
var groupName;
MemberList.init = function() {
groupName = ajaxify.data.group.name;
handleMemberSearch();
handleMemberInfiniteScroll();
};
function handleMemberSearch() {
$('[component="groups/members/search"]').on('keyup', function() {
var query = $(this).val();
if (searchInterval) {
clearInterval(searchInterval);
searchInterval = 0;
}
searchInterval = setTimeout(function() {
socket.emit('groups.searchMembers', {groupName: groupName, query: query}, function(err, results) {
if (err) {
return app.alertError(err.message);
}
parseAndTranslate(results.users, function(html) {
$('[component="groups/members"] tbody').html(html);
$('[component="groups/members"]').attr('data-nextstart', 20);
});
});
}, 250);
});
}
function handleMemberInfiniteScroll() {
$('[component="groups/members"] tbody').on('scroll', function() {
var $this = $(this);
var bottom = ($this[0].scrollHeight - $this.innerHeight()) * 0.9;
if ($this.scrollTop() > bottom) {
loadMoreMembers();
}
});
}
function loadMoreMembers() {
var members = $('[component="groups/members"]');
if (members.attr('loading')) {
return;
}
members.attr('loading', 1);
socket.emit('groups.loadMoreMembers', {
groupName: groupName,
after: members.attr('data-nextstart')
}, function(err, data) {
if (err) {
return app.alertError(err.message);
}
if (data && data.users.length) {
onMembersLoaded(data.users, function() {
members.removeAttr('loading');
members.attr('data-nextstart', data.nextStart);
});
} else {
members.removeAttr('loading');
}
});
}
function onMembersLoaded(users, callback) {
users = users.filter(function(user) {
return !$('[component="groups/members"] [data-uid="' + user.uid + '"]').length;
});
parseAndTranslate(users, function(html) {
$('[component="groups/members"] tbody').append(html);
callback();
});
}
function parseAndTranslate(users, callback) {
infinitescroll.parseAndTranslate('groups/details', 'members', {
group: {
members: users,
isOwner: ajaxify.data.group.isOwner
}
}, callback);
}
return MemberList;
});

@ -59,12 +59,13 @@ groupsController.get = function(req, res, callback) {
if (!exists) {
return callback();
}
groups.get(groupName, {uid: req.uid}, next);
groups.get(groupName, {uid: req.uid, truncateUserList: true, userListCount: 20}, next);
}
], function(err, group) {
if (err) {
return callback(err);
}
group.isOwner = true;
res.render('admin/manage/group', {group: group});
});
};

@ -1,5 +1,6 @@
"use strict";
var async = require('async');
var groups = require('../../groups'),
Groups = {};
@ -20,7 +21,17 @@ Groups.join = function(socket, data, callback) {
return callback(new Error('[[error:invalid-data]]'));
}
groups.join(data.groupName, data.uid, callback);
async.waterfall([
function (next) {
groups.isMember(data.uid, data.groupName, next);
},
function (isMember, next) {
if (isMember) {
return next(new Error('[[error:group-already-member]]'));
}
groups.join(data.groupName, data.uid, next);
}
], callback);
};
Groups.leave = function(socket, data, callback) {
@ -32,7 +43,17 @@ Groups.leave = function(socket, data, callback) {
return callback(new Error('[[error:cant-remove-self-as-admin]]'));
}
groups.leave(data.groupName, data.uid, callback);
async.waterfall([
function (next) {
groups.isMember(data.uid, data.groupName, next);
},
function (isMember, next) {
if (!isMember) {
return next(new Error('[[error:group-not-member]]'));
}
groups.leave(data.groupName, data.uid, next);
}
], callback);
};
Groups.update = function(socket, data, callback) {

@ -62,8 +62,11 @@ SocketGroups.leave = function(socket, data, callback) {
function isOwner(next) {
return function (socket, data, callback) {
groups.ownership.isOwner(socket.uid, data.groupName, function(err, isOwner) {
if (err || !isOwner) {
async.parallel({
isAdmin: async.apply(user.isAdmin, socket.uid),
isOwner: async.apply(groups.ownership.isOwner, socket.uid, data.groupName)
}, function(err, results) {
if (err || (!isOwner && !results.isAdmin)) {
return callback(err || new Error('[[error:no-privileges]]'));
}
next(socket, data, callback);

@ -37,6 +37,7 @@
waitSeconds: 3,
urlArgs: "{cache-buster}",
paths: {
'forum': '../client',
'admin': '../admin',
'vendor': '../../vendor',
'buzz': '../../vendor/buzz/buzz.min'

@ -54,24 +54,20 @@
<label for="add-member">Add User to Group</label>
<input type="text" class="form-control" id="group-details-search" placeholder="Search Users" />
<ul class="members user-list" id="group-details-search-results"></ul>
</fieldset>
<fieldset>
<label>Members</label>
<p>Click on a user to remove them from the group</p>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-users"></i> [[groups:details.members]]</h3>
</div>
<div class="panel-body">
<ul class="members current_members user-list">
<!-- BEGIN group.members -->
<li data-uid="{group.members.uid}">
<img src="{group.members.picture}" />
<span>{group.members.username}</span>
</li>
<!-- END group.members -->
</ul>
<!-- IMPORT partials/groups/memberlist.tpl -->
</div>
</div>
</fieldset>
</div>
</div>

Loading…
Cancel
Save