diff --git a/app/assets/javascripts/discourse/components/group-member-dropdown.js.es6 b/app/assets/javascripts/discourse/components/group-member-dropdown.js.es6
new file mode 100644
index 00000000000..1b5d97d00be
--- /dev/null
+++ b/app/assets/javascripts/discourse/components/group-member-dropdown.js.es6
@@ -0,0 +1,32 @@
+import { iconHTML } from 'discourse-common/lib/icon-library';
+import DropdownButton from 'discourse/components/dropdown-button';
+import computed from "ember-addons/ember-computed-decorators";
+
+export default DropdownButton.extend({
+ buttonExtraClasses: 'no-text',
+ title: '',
+ text: iconHTML('ellipsis-h'),
+ classNames: ['group-member-dropdown'],
+
+ @computed()
+ dropDownContent() {
+ const items = [
+ {
+ id: 'removeMember',
+ title: I18n.t('groups.members.remove_member'),
+ description: I18n.t('groups.members.remove_member_description'),
+ icon: 'user-times'
+ }
+ ];
+
+ return items;
+ },
+
+ clicked(id) {
+ switch (id) {
+ case 'removeMember':
+ this.sendAction('removeMember', this.get('member'));
+ break;
+ }
+ }
+});
diff --git a/app/assets/javascripts/discourse/controllers/group-index.js.es6 b/app/assets/javascripts/discourse/controllers/group-index.js.es6
index 269ecab7cdb..1223e764211 100644
--- a/app/assets/javascripts/discourse/controllers/group-index.js.es6
+++ b/app/assets/javascripts/discourse/controllers/group-index.js.es6
@@ -27,6 +27,11 @@ export default Ember.Controller.extend({
return members && members.length > 0;
},
+ @computed
+ canManageGroup() {
+ return this.currentUser && this.currentUser.canManageGroup(this.get('model'));
+ },
+
actions: {
toggleActions() {
this.toggleProperty("showActions");
diff --git a/app/assets/javascripts/discourse/controllers/group.js.es6 b/app/assets/javascripts/discourse/controllers/group.js.es6
index 755e6fecde3..c0df0d65132 100644
--- a/app/assets/javascripts/discourse/controllers/group.js.es6
+++ b/app/assets/javascripts/discourse/controllers/group.js.es6
@@ -19,7 +19,8 @@ export default Ember.Controller.extend({
const membersTab = Tab.create({
name: 'members',
route: 'group.index',
- icon: 'users'
+ icon: 'users',
+ i18nKey: "members.title"
});
membersTab.set('count', userCount);
diff --git a/app/assets/javascripts/discourse/routes/group-index.js.es6 b/app/assets/javascripts/discourse/routes/group-index.js.es6
index 003a4a8d9e1..faac0525b0e 100644
--- a/app/assets/javascripts/discourse/routes/group-index.js.es6
+++ b/app/assets/javascripts/discourse/routes/group-index.js.es6
@@ -1,6 +1,6 @@
export default Discourse.Route.extend({
titleToken() {
- return I18n.t('groups.members');
+ return I18n.t('groups.members.title');
},
model() {
diff --git a/app/assets/javascripts/discourse/templates/components/group-members-input.hbs b/app/assets/javascripts/discourse/templates/components/group-members-input.hbs
index 4f0ab683ccb..fc0e9667b85 100644
--- a/app/assets/javascripts/discourse/templates/components/group-members-input.hbs
+++ b/app/assets/javascripts/discourse/templates/components/group-members-input.hbs
@@ -1,4 +1,4 @@
-
+
{{#if model.members}}
diff --git a/app/assets/javascripts/discourse/templates/group-index.hbs b/app/assets/javascripts/discourse/templates/group-index.hbs
index a58ed87a3c4..57f3b503a8c 100644
--- a/app/assets/javascripts/discourse/templates/group-index.hbs
+++ b/app/assets/javascripts/discourse/templates/group-index.hbs
@@ -5,6 +5,7 @@
{{group-index-toggle order=order desc=desc field='username_lower' i18nKey='username'}}
{{group-index-toggle order=order desc=desc field='last_posted_at' i18nKey='last_post'}}
{{group-index-toggle order=order desc=desc field='last_seen_at' i18nKey='last_seen'}}
+
|
@@ -21,6 +22,14 @@
{{bound-date m.last_seen_at}}
|
+
+
+ {{#if canManageGroup}}
+ {{group-member-dropdown
+ removeMember="removeMember"
+ member=m}}
+ {{/if}}
+ |
{{/each}}
diff --git a/app/assets/stylesheets/common/base/group.scss b/app/assets/stylesheets/common/base/group.scss
index 6b4586ad7de..059680df3ea 100644
--- a/app/assets/stylesheets/common/base/group.scss
+++ b/app/assets/stylesheets/common/base/group.scss
@@ -124,6 +124,10 @@ table.group-members {
text-align: left;
}
+ th:last-child {
+ width: 5%;
+ }
+
th.group-members-actions {
width: 5%;
}
diff --git a/app/assets/stylesheets/common/components/group-member-dropdown.scss b/app/assets/stylesheets/common/components/group-member-dropdown.scss
new file mode 100644
index 00000000000..49b3209fd23
--- /dev/null
+++ b/app/assets/stylesheets/common/components/group-member-dropdown.scss
@@ -0,0 +1,9 @@
+.group-member-dropdown {
+ ul {
+ width: 250px;
+ top: 27px;
+ bottom: auto;
+ left: -217px;
+ text-align: left;
+ }
+}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index aebfd9ea785..cc5b80ad8cc 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -464,7 +464,10 @@ en:
one: "Group"
other: "Groups"
activity: "Activity"
- members: "Members"
+ members:
+ title: "Members"
+ remove_member: "Remove member"
+ remove_member_description: "Remove a member from this group"
topics: "Topics"
posts: "Posts"
mentions: "Mentions"
@@ -1368,7 +1371,7 @@ en:
desc: Whispers are only visible to staff members
create_topic:
label: "New Topic"
- shared_draft:
+ shared_draft:
label: "Shared Draft"
desc: "Draft a topic that will only be visible to staff"
diff --git a/test/javascripts/acceptance/group-index-test.js.es6 b/test/javascripts/acceptance/group-index-test.js.es6
new file mode 100644
index 00000000000..fd22b18d0da
--- /dev/null
+++ b/test/javascripts/acceptance/group-index-test.js.es6
@@ -0,0 +1,31 @@
+import { acceptance, logIn } from "helpers/qunit-helpers";
+
+acceptance("Group Members");
+
+QUnit.test("Viewing Members as anon user", assert => {
+ visit("/groups/discourse");
+
+ andThen(() => {
+ assert.ok(count('.avatar-flair .fa-adjust') === 1, "it displays the group's avatar flair");
+ assert.ok(count('.group-members tr') > 0, "it lists group members");
+
+ assert.ok(
+ count('.group-member-dropdown') === 0,
+ 'it does not allow anon user to manage group members'
+ );
+ });
+});
+
+QUnit.test("Viewing Members as an admin user", assert => {
+ logIn();
+ Discourse.reset();
+
+ visit("/groups/discourse");
+
+ andThen(() => {
+ assert.ok(
+ count('.group-member-dropdown') > 0,
+ 'it allows admin user to manage group members'
+ );
+ });
+});
diff --git a/test/javascripts/acceptance/groups-test.js.es6 b/test/javascripts/acceptance/groups-test.js.es6
index 19106a1ace6..0c3e94ddeda 100644
--- a/test/javascripts/acceptance/groups-test.js.es6
+++ b/test/javascripts/acceptance/groups-test.js.es6
@@ -69,10 +69,6 @@ QUnit.test("Anonymous Viewing Group", assert => {
visit("/groups/discourse");
andThen(() => {
- assert.ok(count('.avatar-flair .fa-adjust') === 1, "it displays the group's avatar flair");
- assert.ok(count('.group-members tr') > 0, "it lists group members");
- assert.ok(count('.group-message-button') === 0, 'it does not show group message button');
-
assert.equal(
count(".nav-pills li a[title='Messages']"),
0,