mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 11:05:54 +01:00 
			
		
		
		
	closes #2605
This commit is contained in:
		| @@ -1,11 +1,13 @@ | ||||
| "use strict"; | ||||
| /* globals define, socket, ajaxify, app, bootbox, RELATIVE_PATH, utils */ | ||||
|  | ||||
| define('forum/groups/details', ['iconSelect', 'components', 'vendor/colorpicker/colorpicker', 'vendor/jquery/draggable-background/backgroundDraggable'], function(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; | ||||
|  | ||||
| 	Details.init = function() { | ||||
| 		var detailsPage = components.get('groups/container'), | ||||
| 			settingsFormEl = detailsPage.find('form'); | ||||
| @@ -15,6 +17,9 @@ define('forum/groups/details', ['iconSelect', 'components', 'vendor/colorpicker/ | ||||
| 			Details.initialiseCover(); | ||||
| 		} | ||||
|  | ||||
| 		handleMemberSearch(); | ||||
| 		handleMemberInfiniteScroll(); | ||||
|  | ||||
| 		components.get('groups/activity').find('.content img').addClass('img-responsive'); | ||||
|  | ||||
| 		detailsPage.on('click', '[data-action]', function() { | ||||
| @@ -280,5 +285,83 @@ define('forum/groups/details', ['iconSelect', 'components', 'vendor/colorpicker/ | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	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: ajaxify.variables.get('group_name'), query: query}, function(err, results) { | ||||
| 					if (err) { | ||||
| 						return app.alertError(err.message); | ||||
| 					} | ||||
|  | ||||
| 					infinitescroll.parseAndTranslate('groups/details', 'members', { | ||||
| 						group: { | ||||
| 							members: results.users, | ||||
| 							isOwner: ajaxify.variables.get('is_owner') === 'true' | ||||
| 						} | ||||
| 					}, function(html) { | ||||
| 						$('[component="groups/members"] tbody').html(html); | ||||
| 					}); | ||||
| 				}); | ||||
| 			}, 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 loadMoreMembers() { | ||||
| 		var members = $('[component="groups/members"]'); | ||||
| 		if (members.attr('loading')) { | ||||
| 			return; | ||||
| 		} | ||||
| 		members.attr('loading', 1); | ||||
| 		socket.emit('groups.loadMoreMembers', { | ||||
| 			groupName: ajaxify.variables.get('group_name'), | ||||
| 			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.variables.get('is_owner') === 'true' | ||||
| 			} | ||||
| 		}, function(html) { | ||||
| 			$('[component="groups/members"] tbody').append(html); | ||||
| 			callback(); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	return Details; | ||||
| }); | ||||
| @@ -79,7 +79,9 @@ groupsController.details = function(req, res, next) { | ||||
| 		async.parallel({ | ||||
| 			group: function(next) { | ||||
| 				groups.get(res.locals.groupName, { | ||||
| 					uid: req.uid | ||||
| 					uid: req.uid, | ||||
| 					truncateUserList: true, | ||||
| 					userListCount: 20 | ||||
| 				}, next); | ||||
| 			}, | ||||
| 			posts: function(next) { | ||||
|   | ||||
| @@ -115,27 +115,18 @@ var async = require('async'), | ||||
| 		} | ||||
|  | ||||
| 		options.escape = options.hasOwnProperty('escape') ? options.escape : true; | ||||
| 		var stop = -1; | ||||
|  | ||||
| 		async.parallel({ | ||||
| 			base: function (next) { | ||||
| 				db.getObject('group:' + groupName, next); | ||||
| 			}, | ||||
| 			owners: function (next) { | ||||
| 				async.waterfall([ | ||||
| 					function(next) { | ||||
| 						db.getSetMembers('group:' + groupName + ':owners', next); | ||||
| 					}, | ||||
| 					function(uids, next) { | ||||
| 						user.getUsers(uids, options.uid, next); | ||||
| 					} | ||||
| 				], next); | ||||
| 			}, | ||||
| 			members: function (next) { | ||||
| 				var stop = -1; | ||||
| 				if (options.truncateUserList) { | ||||
| 					stop = (parseInt(options.userListCount, 10) || 4) - 1; | ||||
| 				} | ||||
| 				user.getUsersFromSet('group:' + groupName + ':members', options.uid, 0, stop, next); | ||||
|  | ||||
| 				Groups.getOwnersAndMembers(groupName, options.uid, 0, stop, next); | ||||
| 			}, | ||||
| 			pending: function (next) { | ||||
| 				async.waterfall([ | ||||
| @@ -164,19 +155,6 @@ var async = require('async'), | ||||
| 				results.base['cover:position'] = '50% 50%'; | ||||
| 			} | ||||
|  | ||||
| 			var ownerUids = []; | ||||
| 			results.owners.forEach(function(user) { | ||||
| 				if (user) { | ||||
| 					user.isOwner = true; | ||||
| 					ownerUids.push(user.uid.toString()); | ||||
| 				} | ||||
| 			}); | ||||
|  | ||||
| 			results.members = results.members.filter(function(user, index, array) { | ||||
| 				return user && user.uid && ownerUids.indexOf(user.uid.toString()) === -1; | ||||
| 			}); | ||||
| 			results.members = results.owners.concat(results.members); | ||||
|  | ||||
| 			plugins.fireHook('filter:parse.raw', results.base.description, function(err, descriptionParsed) { | ||||
| 				if (err) { | ||||
| 					return callback(err); | ||||
| @@ -190,6 +168,7 @@ var async = require('async'), | ||||
| 				results.base.userTitleEnabled = results.base.userTitleEnabled ? !!parseInt(results.base.userTitleEnabled, 10) : true; | ||||
| 				results.base.createtimeISO = utils.toISOString(results.base.createtime); | ||||
| 				results.base.members = results.members; | ||||
| 				results.base.membersNextStart = stop + 1; | ||||
| 				results.base.pending = results.pending.filter(Boolean); | ||||
| 				results.base.deleted = !!parseInt(results.base.deleted, 10); | ||||
| 				results.base.hidden = !!parseInt(results.base.hidden, 10); | ||||
| @@ -207,6 +186,43 @@ var async = require('async'), | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	Groups.getOwnersAndMembers = function(groupName, uid, start, stop, callback) { | ||||
| 		async.parallel({ | ||||
| 			owners: function (next) { | ||||
| 				async.waterfall([ | ||||
| 					function(next) { | ||||
| 						db.getSetMembers('group:' + groupName + ':owners', next); | ||||
| 					}, | ||||
| 					function(uids, next) { | ||||
| 						user.getUsers(uids, uid, next); | ||||
| 					} | ||||
| 				], next); | ||||
| 			}, | ||||
| 			members: function (next) { | ||||
| 				user.getUsersFromSet('group:' + groupName + ':members', uid, start, stop, next); | ||||
| 			} | ||||
| 		}, function(err, results) { | ||||
| 			if (err) { | ||||
| 				return callback(err); | ||||
| 			} | ||||
|  | ||||
| 			var ownerUids = []; | ||||
| 			results.owners.forEach(function(user) { | ||||
| 				if (user) { | ||||
| 					user.isOwner = true; | ||||
| 					ownerUids.push(user.uid.toString()); | ||||
| 				} | ||||
| 			}); | ||||
|  | ||||
| 			results.members = results.members.filter(function(user, index, array) { | ||||
| 				return user && user.uid && ownerUids.indexOf(user.uid.toString()) === -1; | ||||
| 			}); | ||||
| 			results.members = results.owners.concat(results.members); | ||||
|  | ||||
| 			callback(null, results.members); | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	Groups.escapeGroupData = function(group) { | ||||
| 		if (group) { | ||||
| 			group.nameEncoded = encodeURIComponent(group.name); | ||||
|   | ||||
| @@ -13,6 +13,14 @@ module.exports = function(Groups) { | ||||
| 		db.isSetMember('group:' + groupName + ':owners', uid, callback); | ||||
| 	}; | ||||
|  | ||||
| 	Groups.ownership.isOwners = function(uids, groupName, callback) { | ||||
| 		if (!Array.isArray(uids)) { | ||||
| 			return callback(null, []); | ||||
| 		} | ||||
|  | ||||
| 		db.isSetMembers('group:' + groupName + ':owners', uids, callback); | ||||
| 	}; | ||||
|  | ||||
| 	Groups.ownership.grant = function(toUid, groupName, callback) { | ||||
| 		// Note: No ownership checking is done here on purpose! | ||||
| 		db.setAdd('group:' + groupName + ':owners', toUid, callback); | ||||
|   | ||||
| @@ -87,7 +87,48 @@ module.exports = function(Groups) { | ||||
| 			], callback); | ||||
| 		} | ||||
|  | ||||
| 		if (!data.query) { | ||||
| 			Groups.getOwnersAndMembers(data.groupName, data.uid, 0, 19, function(err, users) { | ||||
| 				if (err) { | ||||
| 					return callback(err); | ||||
| 				} | ||||
| 				callback(null, {users: users}); | ||||
| 			}); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		data.findUids = findUids; | ||||
| 		user.search(data, callback); | ||||
| 		var results; | ||||
| 		async.waterfall([ | ||||
| 			function(next) { | ||||
| 				user.search(data, next); | ||||
| 			}, | ||||
| 			function(_results, next) { | ||||
| 				results = _results; | ||||
| 				var uids = results.users.map(function(user) { | ||||
| 					return user && user.uid; | ||||
| 				}); | ||||
| 				Groups.ownership.isOwners(uids, data.groupName, next); | ||||
| 			}, | ||||
| 			function(isOwners, next) { | ||||
|  | ||||
| 				results.users.forEach(function(user, index) { | ||||
| 					if (user) { | ||||
| 						user.isOwner = isOwners[index]; | ||||
| 					} | ||||
| 				}); | ||||
|  | ||||
| 				results.users.sort(function(a,b) { | ||||
| 					if (a.isOwner && !b.isOwner) { | ||||
| 						return -1; | ||||
| 					} else if (!a.isOwner && b.isOwner) { | ||||
| 						return 1; | ||||
| 					} else { | ||||
| 						return 0; | ||||
| 					} | ||||
| 				}) | ||||
| 				next(null, results); | ||||
| 			} | ||||
| 		], callback); | ||||
| 	}; | ||||
| }; | ||||
|   | ||||
| @@ -244,6 +244,20 @@ SocketGroups.searchMembers = function(socket, data, callback) { | ||||
| 	groups.searchMembers(data, callback); | ||||
| }; | ||||
|  | ||||
| SocketGroups.loadMoreMembers = function(socket, data, callback) { | ||||
| 	if (!data || !data.groupName || !parseInt(data.after, 10)) { | ||||
| 		return callback(new Error('[[error:invalid-data]]')); | ||||
| 	} | ||||
| 	data.after = parseInt(data.after, 10); | ||||
| 	user.getUsersFromSet('group:' + data.groupName + ':members', socket.uid, data.after, data.after + 9, function(err, users) { | ||||
| 		if (err) { | ||||
| 			return callback(err); | ||||
| 		} | ||||
|  | ||||
| 		callback(null, {users: users, nextStart: data.after + 10}); | ||||
| 	}); | ||||
| }; | ||||
|  | ||||
| SocketGroups.kick = function(socket, data, callback) { | ||||
| 	if (!data) { | ||||
| 		return callback(new Error('[[error:invalid-data]]')); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user