From da7009a9683f324acc3bb75c2f1b892ab3b058c4 Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan Date: Mon, 12 Dec 2016 22:46:45 +0800 Subject: [PATCH] FEATURE: Add request membership button for allowed groups. --- .../admin/controllers/admin-group.js.es6 | 11 +++++++ .../javascripts/admin/templates/group.hbs | 23 ++++++++++--- .../discourse/controllers/group-index.js.es6 | 12 +++++++ .../javascripts/discourse/models/group.js.es6 | 22 +++++++++++-- .../discourse/templates/group-index.hbs | 5 +++ .../discourse/templates/modal/edit-group.hbs | 15 ++++++++- app/assets/stylesheets/common/base/group.scss | 4 +++ app/controllers/admin/groups_controller.rb | 2 +- app/controllers/groups_controller.rb | 3 +- app/serializers/basic_group_serializer.rb | 3 +- config/locales/client.en.yml | 7 +++- ...add_allow_membership_requests_to_groups.rb | 5 +++ .../admin/groups_controller_spec.rb | 3 +- spec/integration/groups_spec.rb | 8 +++-- .../javascripts/acceptance/groups-test.js.es6 | 14 ++++++++ .../controllers/admin-group-test.js.es6 | 33 +++++++++++++++++++ .../controllers/group-index-test.js.es6 | 18 ++++++++++ 17 files changed, 172 insertions(+), 16 deletions(-) create mode 100644 db/migrate/20161212123649_add_allow_membership_requests_to_groups.rb create mode 100644 test/javascripts/controllers/admin-group-test.js.es6 diff --git a/app/assets/javascripts/admin/controllers/admin-group.js.es6 b/app/assets/javascripts/admin/controllers/admin-group.js.es6 index 660fbafd3b6..71cb2c70328 100644 --- a/app/assets/javascripts/admin/controllers/admin-group.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-group.js.es6 @@ -1,5 +1,6 @@ import { popupAjaxError } from 'discourse/lib/ajax-error'; import { propertyEqual } from 'discourse/lib/computed'; +import computed from 'ember-addons/ember-computed-decorators'; export default Ember.Controller.extend({ adminGroupsType: Ember.inject.controller(), @@ -35,6 +36,16 @@ export default Ember.Controller.extend({ ]; }.property(), + @computed('model.visible', 'model.public', 'model.alias_level') + disableMembershipRequestSetting(visible, publicGroup) { + return !visible || publicGroup || !this.get('model.canEveryoneMention'); + }, + + @computed('model.visible', 'model.allow_membership_requests') + disablePublicSetting(visible, allowMembershipRequests) { + return !visible || allowMembershipRequests; + }, + actions: { next() { if (this.get("showingLast")) { return; } diff --git a/app/assets/javascripts/admin/templates/group.hbs b/app/assets/javascripts/admin/templates/group.hbs index 3b06790e439..f66e0ca8557 100644 --- a/app/assets/javascripts/admin/templates/group.hbs +++ b/app/assets/javascripts/admin/templates/group.hbs @@ -64,16 +64,29 @@ {{#unless model.automatic}}
-
+
+ +
+
{{/unless}} diff --git a/app/assets/javascripts/discourse/controllers/group-index.js.es6 b/app/assets/javascripts/discourse/controllers/group-index.js.es6 index 385ad7414e6..ff1b32741e5 100644 --- a/app/assets/javascripts/discourse/controllers/group-index.js.es6 +++ b/app/assets/javascripts/discourse/controllers/group-index.js.es6 @@ -22,6 +22,11 @@ export default Ember.Controller.extend({ return !!(this.currentUser) && publicGroup; }, + @computed('model.allow_membership_requests', 'model.alias_level') + canRequestMembership(allowMembershipRequests, aliasLevel) { + return !!(this.currentUser) && allowMembershipRequests && aliasLevel === 99; + }, + actions: { removeMember(user) { this.get('model').removeMember(user); @@ -34,6 +39,13 @@ export default Ember.Controller.extend({ } }, + requestMembership() { + const groupName = this.get('model.name'); + const title = I18n.t('groups.request_membership_pm.title'); + const body = I18n.t('groups.request_membership_pm.body', { groupName }); + this.transitionToRoute(`/new-message?groupname=${groupName}&title=${title}&body=${body}`); + }, + joinGroup() { this.set('updatingMembership', true); const model = this.get('model'); diff --git a/app/assets/javascripts/discourse/models/group.js.es6 b/app/assets/javascripts/discourse/models/group.js.es6 index 7d8a58cec66..c4cd97ddf00 100644 --- a/app/assets/javascripts/discourse/models/group.js.es6 +++ b/app/assets/javascripts/discourse/models/group.js.es6 @@ -1,5 +1,5 @@ import { ajax } from 'discourse/lib/ajax'; -import computed from "ember-addons/ember-computed-decorators"; +import { default as computed, observes } from "ember-addons/ember-computed-decorators"; import GroupHistory from 'discourse/models/group-history'; const Group = Discourse.Model.extend({ @@ -101,6 +101,23 @@ const Group = Discourse.Model.extend({ return this.get('flair_color') ? this.get('flair_color').replace(new RegExp("[^0-9a-fA-F]", "g"), "") : null; }, + @computed('alias_level') + canEveryoneMention(aliasLevel) { + return aliasLevel === '99'; + }, + + @observes("visible", "canEveryoneMention") + _updateAllowMembershipRequests() { + if (!this.get('visible') || !this.get('canEveryoneMention')) { + this.set('allow_membership_requests', false); + } + }, + + @observes("visible") + _updatePublic() { + if (!this.get('visible')) this.set('public', false); + }, + asJSON() { return { name: this.get('name'), @@ -116,7 +133,8 @@ const Group = Discourse.Model.extend({ flair_bg_color: this.get('flairBackgroundHexColor'), flair_color: this.get('flairHexColor'), bio_raw: this.get('bio_raw'), - public: this.get('public') + public: this.get('public'), + allow_membership_requests: this.get('allow_membership_requests') }; }, diff --git a/app/assets/javascripts/discourse/templates/group-index.hbs b/app/assets/javascripts/discourse/templates/group-index.hbs index 694750e6821..cd01f61fa4d 100644 --- a/app/assets/javascripts/discourse/templates/group-index.hbs +++ b/app/assets/javascripts/discourse/templates/group-index.hbs @@ -18,6 +18,11 @@ label="groups.join" disabled=updatingMembership}} {{/if}} + {{else if canRequestMembership}} + {{d-button action="requestMembership" + class="group-index-request" + icon="envelope" + label="groups.request"}} {{/if}} {{#load-more selector=".group-members tr" action="loadMore"}} diff --git a/app/assets/javascripts/discourse/templates/modal/edit-group.hbs b/app/assets/javascripts/discourse/templates/modal/edit-group.hbs index 3c65ade87ed..863f83dd3c3 100644 --- a/app/assets/javascripts/discourse/templates/modal/edit-group.hbs +++ b/app/assets/javascripts/discourse/templates/modal/edit-group.hbs @@ -9,9 +9,22 @@ {{group-flair-inputs model=model}} + + {{/d-modal-body}} diff --git a/app/assets/stylesheets/common/base/group.scss b/app/assets/stylesheets/common/base/group.scss index ef9ee506f60..146c5039ad2 100644 --- a/app/assets/stylesheets/common/base/group.scss +++ b/app/assets/stylesheets/common/base/group.scss @@ -23,6 +23,10 @@ } } +.group-index-request, .group-index-join, .group-index-leave { + float: right; +} + table.group-logs { width: 100%; diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index 7f4109277e6..ed96b325100 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -145,7 +145,7 @@ class Admin::GroupsController < Admin::AdminController :name, :alias_level, :visible, :automatic_membership_email_domains, :automatic_membership_retroactive, :title, :primary_group, :grant_trust_level, :incoming_email, :flair_url, :flair_bg_color, - :flair_color, :bio_raw, :public + :flair_color, :bio_raw, :public, :allow_membership_requests ) end end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index cfb8b686743..87137ed5937 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -237,7 +237,8 @@ class GroupsController < ApplicationController :flair_color, :bio_raw, :title, - :public + :public, + :allow_membership_requests ) end diff --git a/app/serializers/basic_group_serializer.rb b/app/serializers/basic_group_serializer.rb index a4f1e4a2d0c..264013cbdaf 100644 --- a/app/serializers/basic_group_serializer.rb +++ b/app/serializers/basic_group_serializer.rb @@ -17,7 +17,8 @@ class BasicGroupSerializer < ApplicationSerializer :flair_color, :bio_raw, :bio_cooked, - :public + :public, + :allow_membership_requests def include_incoming_email? staff? diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index cb0c4bc99f4..c5c9c3443b6 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -397,8 +397,11 @@ en: edit: title: 'Edit Group' group_title: 'Title' + request_membership_pm: + title: "Membership Request" + body: "I would like to request membership in @%{groupName}." name_placeholder: "Group name, no spaces, same as username rule" - public: "Allow users to join/leave the group freely" + public: "Allow users to join/leave the group freely (Requires group to be visible)" empty: posts: "There is no post by members of this group." members: "There is no member in this group." @@ -409,6 +412,8 @@ en: add: "Add" join: "Join Group" leave: "Leave Group" + request: "Request to Join Group" + allow_membership_requests: "Allow users to send membership requests to group owners (Requires everyone to be able to mention the group)" name: "Name" bio: "About Group" selector_placeholder: "Add members" diff --git a/db/migrate/20161212123649_add_allow_membership_requests_to_groups.rb b/db/migrate/20161212123649_add_allow_membership_requests_to_groups.rb new file mode 100644 index 00000000000..b219ed4ef8c --- /dev/null +++ b/db/migrate/20161212123649_add_allow_membership_requests_to_groups.rb @@ -0,0 +1,5 @@ +class AddAllowMembershipRequestsToGroups < ActiveRecord::Migration + def change + add_column :groups, :allow_membership_requests, :boolean, default: false, null: false + end +end diff --git a/spec/controllers/admin/groups_controller_spec.rb b/spec/controllers/admin/groups_controller_spec.rb index a5b696932fe..f9ee82f9ee6 100644 --- a/spec/controllers/admin/groups_controller_spec.rb +++ b/spec/controllers/admin/groups_controller_spec.rb @@ -40,7 +40,8 @@ describe Admin::GroupsController do "flair_color"=>nil, "bio_raw"=>nil, "bio_cooked"=>nil, - "public"=>false + "public"=>false, + "allow_membership_requests"=>false }]) end diff --git a/spec/integration/groups_spec.rb b/spec/integration/groups_spec.rb index e13677f9793..0a53cee2f89 100644 --- a/spec/integration/groups_spec.rb +++ b/spec/integration/groups_spec.rb @@ -55,9 +55,10 @@ describe "Groups" do flair_url: 'fa-adjust', bio_raw: 'testing', title: 'awesome team', - public: true + public: true, + allow_membership_requests: true } } - end.to change { GroupHistory.count }.by(6) + end.to change { GroupHistory.count }.by(7) expect(response).to be_success @@ -69,7 +70,8 @@ describe "Groups" do expect(group.bio_raw).to eq('testing') expect(group.title).to eq('awesome team') expect(group.public).to eq(true) - expect(GroupHistory.last.subject).to eq('public') + expect(group.allow_membership_requests).to eq(true) + expect(GroupHistory.last.subject).to eq('allow_membership_requests') end end diff --git a/test/javascripts/acceptance/groups-test.js.es6 b/test/javascripts/acceptance/groups-test.js.es6 index 8ba58086aad..c3578e43d74 100644 --- a/test/javascripts/acceptance/groups-test.js.es6 +++ b/test/javascripts/acceptance/groups-test.js.es6 @@ -53,5 +53,19 @@ test("Admin Browsing Groups", () => { ok(find('.edit-group-bio').length === 1, 'it should display group bio input'); ok(find('.edit-group-title').length === 1, 'it should display group title input'); ok(find('.edit-group-public').length === 1, 'it should display group public input'); + ok(find('.edit-group-allow-membership-requests').length === 1, 'it should display group allow_membership_requets input'); + }); + + click('.edit-group-public'); + + andThen(() => { + ok(find('.edit-group-allow-membership-requests[disabled]').length === 1, 'it should disable group allow_membership_requets input'); + }); + + click('.edit-group-public'); + click('.edit-group-allow-membership-requests'); + + andThen(() => { + ok(find('.edit-group-public[disabled]').length === 1, 'it should disable group public input'); }); }); diff --git a/test/javascripts/controllers/admin-group-test.js.es6 b/test/javascripts/controllers/admin-group-test.js.es6 new file mode 100644 index 00000000000..e80e50d6f3c --- /dev/null +++ b/test/javascripts/controllers/admin-group-test.js.es6 @@ -0,0 +1,33 @@ +moduleFor("controller:admin-group"); + +test("disablePublicSetting", function() { + this.subject().setProperties({ + model: { visible: false, allow_membership_requests: false } + }); + + equal(this.subject().get("disablePublicSetting"), true, "it should disable setting"); + + this.subject().set("model.visible", true); + + equal(this.subject().get("disablePublicSetting"), false, "it should enable setting"); + + this.subject().set("model.allow_membership_requests", true); + + equal(this.subject().get("disablePublicSetting"), true, "it should disable setting"); +}); + +test("disableMembershipRequestSetting", function() { + this.subject().setProperties({ + model: { visible: false, public: false, canEveryoneMention: true } + }); + + equal(this.subject().get("disableMembershipRequestSetting"), true, "it should disable setting"); + + this.subject().set("model.visible", true); + + equal(this.subject().get("disableMembershipRequestSetting"), false, "it should enable setting"); + + this.subject().set("model.public", true); + + equal(this.subject().get("disableMembershipRequestSetting"), true, "it should disalbe setting"); +}); diff --git a/test/javascripts/controllers/group-index-test.js.es6 b/test/javascripts/controllers/group-index-test.js.es6 index d3ac38a18a0..f308def5747 100644 --- a/test/javascripts/controllers/group-index-test.js.es6 +++ b/test/javascripts/controllers/group-index-test.js.es6 @@ -19,3 +19,21 @@ test("canJoinGroup", function() { equal(this.subject().get("canJoinGroup"), false, "can't join group when not logged in"); }); + +test('canRequestMembership', function() { + this.subject().setProperties({ + model: { allow_membership_requests: false, alias_level: 0 } + }) + + equal(this.subject().get('canRequestMembership'), false); + + this.subject().setProperties({ + currentUser: currentUser(), model: { allow_membership_requests: true, alias_level: 99 } + }); + + equal(this.subject().get('canRequestMembership'), true); + + this.subject().set("model.alias_level", 0); + + equal(this.subject().get('canRequestMembership'), false); +});