diff --git a/app/assets/javascripts/admin/components/admin-group-selector.js.es6 b/app/assets/javascripts/admin/components/admin-group-selector.js.es6 new file mode 100644 index 000000000..c78f1ff89 --- /dev/null +++ b/app/assets/javascripts/admin/components/admin-group-selector.js.es6 @@ -0,0 +1,39 @@ +export default Ember.Component.extend({ + tagName: 'div', + + didInsertElement: function(){ + this.$("input").select2({ + multiple: true, + width: '100%', + query: function(opts){ + opts.callback({ + results: this.get("available").map(this._format) + }); + }.bind(this) + }).on("change", function(evt) { + if (evt.added){ + this.triggerAction({action: "groupAdded", + actionContext: this.get("available" + ).findBy("id", evt.added.id)}); + } else if (evt.removed) { + this.triggerAction({action:"groupRemoved", + actionContext: this.get("selected" + ).findBy("id", evt.removed.id)}); + } + }.bind(this)); + + Discourse.Group.findAll().then(function(groups){ + this.set("available", groups.filterBy("automatic", false)); + }.bind(this)); + + this.refreshOnReset(); + }, + + _format: function(item){ + return {"text": item.name, "id": item.id, "locked": item.automatic}; + }, + + refreshOnReset: function() { + this.$("input").select2("data", this.get("selected").map(this._format)); + }.observes("selected") +}); \ No newline at end of file diff --git a/app/assets/javascripts/admin/controllers/admin_user_controller.js b/app/assets/javascripts/admin/controllers/admin_user_controller.js index 50dff9a2f..5fc95f505 100644 --- a/app/assets/javascripts/admin/controllers/admin_user_controller.js +++ b/app/assets/javascripts/admin/controllers/admin_user_controller.js @@ -25,6 +25,12 @@ Discourse.AdminUserIndexController = Discourse.ObjectController.extend({ primaryGroupDirty: Discourse.computed.propertyNotEqual('originalPrimaryGroupId', 'primary_group_id'), + custom_groups: function(){ + return this.get("model.groups").filter(function(g){ + return (!g.automatic && g.visible); + }); + }.property("model.groups.[]"), + actions: { toggleTitleEdit: function() { this.toggleProperty('editingTitle'); @@ -45,6 +51,28 @@ Discourse.AdminUserIndexController = Discourse.ObjectController.extend({ this.get('model').generateApiKey(); }, + groupAdded: function(added){ + var self = this; + Discourse.ajax("/admin/users/" + this.get('id') + "/groups", { + type: 'POST', + data: {group_id: added.id} + }).then(function () { + self.get('model.groups').pushObject(added); + }).catch(function() { + bootbox.alert(I18n.t('generic_error')); + }); + }, + groupRemoved: function(removed){ + var self = this; + Discourse.ajax("/admin/users/" + this.get('id') + "/groups/" + removed.id, { + type: 'DELETE' + }).then(function () { + self.set('model.groups.[]', self.get('model.groups').rejectBy("id", removed.id)); + }).catch(function() { + bootbox.alert(I18n.t('generic_error')); + }); + }, + savePrimaryGroup: function() { var self = this; Discourse.ajax("/admin/users/" + this.get('id') + "/primary_group", { diff --git a/app/assets/javascripts/admin/templates/user_index.js.handlebars b/app/assets/javascripts/admin/templates/user_index.js.handlebars index dddcee603..fccb6d13a 100644 --- a/app/assets/javascripts/admin/templates/user_index.js.handlebars +++ b/app/assets/javascripts/admin/templates/user_index.js.handlebars @@ -53,20 +53,18 @@
-
{{i18n admin.groups.primary}}
+
{{i18n admin.groups.title}}
- {{#if custom_groups}} - {{combo-box content=custom_groups value=primary_group_id nameProperty="name" none="admin.groups.no_primary"}} - {{else}} - — - {{/if}} + {{admin-group-selector selected=model.groups }}
+ {{#if custom_groups}} + {{i18n admin.groups.primary}} + {{combo-box content=custom_groups value=primary_group_id nameProperty="name" none="admin.groups.no_primary"}} + {{/if}} {{#if primaryGroupDirty}} -
-
{{/if}}
diff --git a/app/assets/javascripts/discourse/templates/components/admin-group-selector.js.handlebars b/app/assets/javascripts/discourse/templates/components/admin-group-selector.js.handlebars new file mode 100644 index 000000000..f897810ab --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/admin-group-selector.js.handlebars @@ -0,0 +1,3 @@ + + + diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index e5fd6d1ae..b7a4123a3 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -17,6 +17,8 @@ class Admin::UsersController < Admin::AdminController :block, :unblock, :trust_level, + :add_group, + :remove_group, :primary_group, :generate_api_key, :revoke_api_key] @@ -101,6 +103,21 @@ class Admin::UsersController < Admin::AdminController render_serialized(@user, AdminUserSerializer) end + def add_group + group = Group.find(params[:group_id].to_i) + return render_json_error group unless group && !group.automatic + group.users << @user + render nothing: true + end + + def remove_group + group = Group.find(params[:group_id].to_i) + return render_json_error group unless group && !group.automatic + group.users.delete(@user) + render nothing: true + end + + def primary_group guardian.ensure_can_change_primary_group!(@user) @user.primary_group_id = params[:primary_group_id] diff --git a/app/serializers/admin_detailed_user_serializer.rb b/app/serializers/admin_detailed_user_serializer.rb index 32ba08cff..030e6aded 100644 --- a/app/serializers/admin_detailed_user_serializer.rb +++ b/app/serializers/admin_detailed_user_serializer.rb @@ -22,7 +22,7 @@ class AdminDetailedUserSerializer < AdminUserSerializer has_one :api_key, serializer: ApiKeySerializer, embed: :objects has_one :suspended_by, serializer: BasicUserSerializer, embed: :objects has_one :leader_requirements, serializer: LeaderRequirementsSerializer, embed: :objects - has_many :custom_groups, embed: :object, serializer: BasicGroupSerializer + has_many :groups, embed: :object, serializer: BasicGroupSerializer def can_revoke_admin scope.can_revoke_admin?(object) diff --git a/config/routes.rb b/config/routes.rb index c7a5acddf..779f5f984 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -70,6 +70,8 @@ Discourse::Application.routes.draw do put "unblock" put "trust_level" put "primary_group" + post "groups" => "users#add_group", constraints: AdminConstraint.new + delete "groups/:group_id" => "users#remove_group", constraints: AdminConstraint.new get "badges" get "leader_requirements" end