mirror of
https://github.com/discourse/discourse.git
synced 2026-09-05 04:40:41 -05:00
UX: Allow users to filter members on group page.
* Only admins are allowed to filter users by email.
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import Group from 'discourse/models/group';
|
||||
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
|
||||
import debounce from 'discourse/lib/debounce';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
queryParams: ['order', 'desc'],
|
||||
queryParams: ['order', 'desc', 'filter'],
|
||||
order: '',
|
||||
desc: null,
|
||||
loading: false,
|
||||
@@ -11,15 +12,26 @@ export default Ember.Controller.extend({
|
||||
offset: null,
|
||||
isOwner: Ember.computed.alias('model.is_group_owner'),
|
||||
showActions: false,
|
||||
filter: null,
|
||||
filterInput: null,
|
||||
|
||||
@observes('order', 'desc')
|
||||
@observes("filterInput")
|
||||
_setFilter: debounce(function() {
|
||||
this.set("filter", this.get("filterInput"));
|
||||
}, 500),
|
||||
|
||||
@observes('order', 'desc', 'filter')
|
||||
refreshMembers() {
|
||||
this.set('loading', true);
|
||||
const model = this.get('model');
|
||||
|
||||
this.get('model') &&
|
||||
this.get('model')
|
||||
.findMembers({ order: this.get('order'), desc: this.get('desc') })
|
||||
.finally(() => this.set('loading', false));
|
||||
if (model) {
|
||||
model.findMembers({
|
||||
order: this.get('order'),
|
||||
desc: this.get('desc'),
|
||||
filter: this.get('filter'),
|
||||
}).finally(() => this.set('loading', false));
|
||||
}
|
||||
},
|
||||
|
||||
@computed('model.members')
|
||||
@@ -32,6 +44,15 @@ export default Ember.Controller.extend({
|
||||
return this.currentUser && this.currentUser.canManageGroup(model);
|
||||
},
|
||||
|
||||
@computed
|
||||
filterPlaceholder() {
|
||||
if (this.currentUser && this.currentUser.admin) {
|
||||
return "groups.members.filter_placeholder_admin";
|
||||
} else {
|
||||
return "groups.members.filter_placeholder";
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
toggleActions() {
|
||||
this.toggleProperty("showActions");
|
||||
|
||||
@@ -33,13 +33,13 @@ const Group = RestModel.extend({
|
||||
findMembers(params) {
|
||||
if (Em.isEmpty(this.get('name'))) { return ; }
|
||||
|
||||
const self = this, offset = Math.min(this.get("user_count"), Math.max(this.get("offset"), 0));
|
||||
const offset = Math.min(this.get("user_count"), Math.max(this.get("offset"), 0));
|
||||
|
||||
return Group.loadMembers(this.get("name"), offset, this.get("limit"), params).then(function (result) {
|
||||
return Group.loadMembers(this.get("name"), offset, this.get("limit"), params).then(result => {
|
||||
var ownerIds = {};
|
||||
result.owners.forEach(owner => ownerIds[owner.id] = true);
|
||||
|
||||
self.setProperties({
|
||||
this.setProperties({
|
||||
user_count: result.meta.total,
|
||||
limit: result.meta.limit,
|
||||
offset: result.meta.offset,
|
||||
|
||||
@@ -3,13 +3,19 @@ export default Discourse.Route.extend({
|
||||
return I18n.t('groups.members.title');
|
||||
},
|
||||
|
||||
model() {
|
||||
model(params) {
|
||||
this._params = params;
|
||||
return this.modelFor("group");
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
this.controllerFor("group").set("showing", "members");
|
||||
controller.set("model", model);
|
||||
|
||||
controller.setProperties({
|
||||
model,
|
||||
filterInput: this._params.filter
|
||||
});
|
||||
|
||||
controller.refreshMembers();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
{{text-field value=filterInput
|
||||
placeholderKey=filterPlaceholder
|
||||
class="group-username-filter no-blur"}}
|
||||
|
||||
{{#if hasMembers}}
|
||||
{{#load-more selector=".group-members tr" action="loadMore"}}
|
||||
<table class='group-members'>
|
||||
|
||||
@@ -186,8 +186,8 @@ class GroupsController < ApplicationController
|
||||
end
|
||||
|
||||
users = group.users.human_users
|
||||
|
||||
total = users.count
|
||||
|
||||
members = users
|
||||
.order('NOT group_users.owner')
|
||||
.order(order)
|
||||
@@ -200,6 +200,16 @@ class GroupsController < ApplicationController
|
||||
.order(username_lower: dir)
|
||||
.where('group_users.owner')
|
||||
|
||||
if (filter = params[:filter]).present?
|
||||
if current_user&.admin
|
||||
owners = owners.filter_by_username_or_email(filter)
|
||||
members = members.filter_by_username_or_email(filter)
|
||||
else
|
||||
owners = owners.filter_by_username(filter)
|
||||
members = members.filter_by_username(filter)
|
||||
end
|
||||
end
|
||||
|
||||
render json: {
|
||||
members: serialize_data(members, GroupUserSerializer),
|
||||
owners: serialize_data(owners, GroupUserSerializer),
|
||||
|
||||
@@ -159,6 +159,25 @@ class User < ActiveRecord::Base
|
||||
scope :not_suspended, -> { where('suspended_till IS NULL OR suspended_till <= ?', Time.zone.now) }
|
||||
scope :activated, -> { where(active: true) }
|
||||
|
||||
scope :filter_by_username, ->(filter) do
|
||||
where('username_lower ILIKE ?', filter)
|
||||
end
|
||||
|
||||
scope :filter_by_username_or_email, ->(filter) do
|
||||
if filter =~ /.+@.+/
|
||||
# probably an email so try the bypass
|
||||
if user_id = UserEmail.where("lower(email) = ?", filter.downcase).pluck(:user_id).first
|
||||
return where('users.id = ?', user_id)
|
||||
end
|
||||
end
|
||||
|
||||
joins(:primary_email)
|
||||
.where(
|
||||
'username_lower ILIKE :filter OR lower(user_emails.email) ILIKE :filter',
|
||||
filter: "%#{filter}%"
|
||||
)
|
||||
end
|
||||
|
||||
module NewTopicDuration
|
||||
ALWAYS = -1
|
||||
LAST_VISIT = -2
|
||||
|
||||
Reference in New Issue
Block a user