Merge pull request #5033 from tgxworld/reason_when_requesting_to_join_a_group
FEATURE: Force user to enter reason when requesting for group members…
This commit is contained in:
commit
898c6ba037
|
@ -91,6 +91,17 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
{{#if model.allow_membership_requests}}
|
||||
<div>
|
||||
<label for="membership-request-template">
|
||||
{{i18n 'groups.membership_request_template'}}
|
||||
</label>
|
||||
|
||||
{{expanding-text-area name="membership-request-template"
|
||||
value=model.membership_request_template}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div>
|
||||
<label for="primary_group">
|
||||
{{input type="checkbox" checked=model.primary_group}}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import { default as computed } from 'ember-addons/ember-computed-decorators';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import DiscourseURL from 'discourse/lib/url';
|
||||
import showModal from 'discourse/lib/show-modal';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
loading: false,
|
||||
|
||||
@computed("model.public_admission", "userIsGroupUser")
|
||||
canJoinGroup(publicAdmission, userIsGroupUser) {
|
||||
return publicAdmission && !userIsGroupUser;
|
||||
|
@ -56,15 +54,9 @@ export default Ember.Component.extend({
|
|||
});
|
||||
},
|
||||
|
||||
requestMembership() {
|
||||
showRequestMembershipForm() {
|
||||
if (this.currentUser) {
|
||||
this.set('loading', true);
|
||||
|
||||
this.get('model').requestMembership().then(result => {
|
||||
DiscourseURL.routeTo(result.relative_url);
|
||||
}).catch(popupAjaxError).finally(() => {
|
||||
this.set('loading', false);
|
||||
});
|
||||
showModal("request-group-membership-form", { model: this.get('model') });
|
||||
} else {
|
||||
this._showLoginModal();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import DiscourseURL from 'discourse/lib/url';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
loading: false,
|
||||
reason: Ember.computed.alias('model.membership_request_template'),
|
||||
|
||||
@computed('model.name')
|
||||
title(groupName) {
|
||||
return I18n.t('groups.membership_request.title', { group_name: groupName });
|
||||
},
|
||||
|
||||
@computed('loading', 'reason')
|
||||
disableSubmit(loading, reason) {
|
||||
return (loading || Ember.isEmpty(reason));
|
||||
},
|
||||
|
||||
actions: {
|
||||
requestMember() {
|
||||
if (this.currentUser) {
|
||||
this.set('loading', true);
|
||||
|
||||
this.get('model').requestMembership(this.get('reason')).then(result => {
|
||||
DiscourseURL.routeTo(result.relative_url);
|
||||
}).catch(popupAjaxError).finally(() => {
|
||||
this.set('loading', false);
|
||||
});
|
||||
} else {
|
||||
this._showLoginModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
|
@ -147,7 +147,8 @@ const Group = RestModel.extend({
|
|||
public_exit: this.get('public_exit'),
|
||||
allow_membership_requests: this.get('allow_membership_requests'),
|
||||
full_name: this.get('full_name'),
|
||||
default_notification_level: this.get('default_notification_level')
|
||||
default_notification_level: this.get('default_notification_level'),
|
||||
membership_request_template: this.get('membership_request_template')
|
||||
};
|
||||
|
||||
if (!this.get('id')) {
|
||||
|
@ -220,9 +221,10 @@ const Group = RestModel.extend({
|
|||
});
|
||||
},
|
||||
|
||||
requestMembership() {
|
||||
requestMembership(reason) {
|
||||
return ajax(`/groups/${this.get('name')}/request_membership`, {
|
||||
type: "POST"
|
||||
type: "POST",
|
||||
data: { reason: reason }
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -20,15 +20,11 @@
|
|||
disabled=true}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{d-button action="requestMembership"
|
||||
{{d-button action="showRequestMembershipForm"
|
||||
class="group-index-request"
|
||||
disabled=loading
|
||||
icon="user-plus"
|
||||
label="groups.request"}}
|
||||
|
||||
{{#if loading}}
|
||||
{{loading-spinner size="small"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{yield}}
|
||||
|
|
|
@ -51,6 +51,18 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
{{#if model.allow_membership_requests}}
|
||||
<div>
|
||||
<label for="membership-request-template">
|
||||
{{i18n 'groups.membership_request_template'}}
|
||||
</label>
|
||||
|
||||
{{expanding-text-area name="membership-request-template"
|
||||
value=model.membership_request_template
|
||||
class="group-edit-membership-request-template"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet name="group-edit" args=(hash group=model)}}
|
||||
|
||||
{{d-button action="save" class="btn-primary" disabled=saving label="save"}}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<form class='request-group-membership-form'>
|
||||
{{#d-modal-body rawTitle=title}}
|
||||
<div class="control-group">
|
||||
<label>
|
||||
{{i18n "groups.membership_request.reason"}}
|
||||
</label>
|
||||
|
||||
{{expanding-text-area value=reason}}
|
||||
</div>
|
||||
{{/d-modal-body}}
|
||||
|
||||
<div class="modal-footer">
|
||||
{{d-button class="btn-primary"
|
||||
disabled=disableSubmit
|
||||
label="groups.membership_request.submit"
|
||||
action="requestMember"}}
|
||||
|
||||
<a {{action "closeModal"}}>{{i18n 'cancel'}}</a>
|
||||
{{conditional-loading-spinner size="small" condition=loading}}
|
||||
</div>
|
||||
</form>
|
|
@ -0,0 +1,5 @@
|
|||
.request-group-membership-form {
|
||||
label {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
|
@ -97,6 +97,7 @@ class Admin::GroupsController < Admin::AdminController
|
|||
|
||||
if group_params[:allow_membership_requests]
|
||||
group.allow_membership_requests = group_params[:allow_membership_requests]
|
||||
group.membership_request_template = group_params[:membership_request_template]
|
||||
end
|
||||
|
||||
if group_params[:owner_usernames].present?
|
||||
|
@ -208,7 +209,8 @@ class Admin::GroupsController < Admin::AdminController
|
|||
:full_name,
|
||||
:default_notification_level,
|
||||
:usernames,
|
||||
:owner_usernames
|
||||
:owner_usernames,
|
||||
:membership_request_template
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -243,6 +243,8 @@ class GroupsController < ApplicationController
|
|||
end
|
||||
|
||||
def request_membership
|
||||
params.require(:reason)
|
||||
|
||||
unless current_user.staff?
|
||||
RateLimiter.new(current_user, "request_group_membership", 1, 1.day).performed!
|
||||
end
|
||||
|
@ -259,7 +261,7 @@ class GroupsController < ApplicationController
|
|||
|
||||
post = PostCreator.new(current_user,
|
||||
title: I18n.t('groups.request_membership_pm.title', group_name: group_name),
|
||||
raw: I18n.t('groups.request_membership_pm.body', group_name: group_name),
|
||||
raw: params[:reason],
|
||||
archetype: Archetype.private_message,
|
||||
target_usernames: usernames.join(','),
|
||||
skip_validations: true
|
||||
|
|
|
@ -22,7 +22,8 @@ class BasicGroupSerializer < ApplicationSerializer
|
|||
:public_exit,
|
||||
:allow_membership_requests,
|
||||
:full_name,
|
||||
:default_notification_level
|
||||
:default_notification_level,
|
||||
:membership_request_template
|
||||
|
||||
def include_display_name?
|
||||
object.automatic
|
||||
|
|
|
@ -427,6 +427,12 @@ en:
|
|||
closed_group: Closed Group
|
||||
is_group_user: "You are a member of this group"
|
||||
allow_membership_requests: "Allow users to send membership requests to group owners"
|
||||
membership_request_template: "Custom template to display to users when sending a membership request"
|
||||
membership_request:
|
||||
submit: "Submit Request"
|
||||
title: "Request to join @%{group_name}"
|
||||
reason: "Let the group owners know why you belong in this group"
|
||||
|
||||
membership: "Membership"
|
||||
name: "Name"
|
||||
user_count: "Number of Members"
|
||||
|
|
|
@ -280,7 +280,6 @@ en:
|
|||
trust_level_4: "trust_level_4"
|
||||
request_membership_pm:
|
||||
title: "Membership Request for @%{group_name}"
|
||||
body: "I would like to apply for membership in @%{group_name}."
|
||||
|
||||
education:
|
||||
until_posts:
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class AddMembershipRequestTemplateToGroups < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :groups, :membership_request_template, :text
|
||||
end
|
||||
end
|
|
@ -15,7 +15,8 @@ RSpec.describe "Managing groups as an admin" do
|
|||
name: 'testing',
|
||||
usernames: [admin.username, user.username].join(","),
|
||||
owner_usernames: [user.username].join(","),
|
||||
allow_membership_requests: true
|
||||
allow_membership_requests: true,
|
||||
membership_request_template: 'Testing',
|
||||
}
|
||||
|
||||
expect(response).to be_success
|
||||
|
@ -25,6 +26,7 @@ RSpec.describe "Managing groups as an admin" do
|
|||
expect(group.name).to eq('testing')
|
||||
expect(group.users).to contain_exactly(admin, user)
|
||||
expect(group.allow_membership_requests).to eq(true)
|
||||
expect(group.membership_request_template).to eq('Testing')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -564,6 +564,14 @@ describe "Groups" do
|
|||
end.to raise_error(Discourse::NotLoggedIn)
|
||||
end
|
||||
|
||||
it 'requires a reason' do
|
||||
sign_in(user)
|
||||
|
||||
expect do
|
||||
xhr :post, "/groups/#{group.name}/request_membership"
|
||||
end.to raise_error(ActionController::ParameterMissing)
|
||||
end
|
||||
|
||||
it 'should create the right PM' do
|
||||
owner1 = Fabricate(:user, last_seen_at: Time.zone.now)
|
||||
owner2 = Fabricate(:user, last_seen_at: Time.zone.now - 1 .day)
|
||||
|
@ -571,7 +579,8 @@ describe "Groups" do
|
|||
|
||||
sign_in(user)
|
||||
|
||||
xhr :post, "/groups/#{group.name}/request_membership"
|
||||
xhr :post, "/groups/#{group.name}/request_membership",
|
||||
reason: 'Please add me in'
|
||||
|
||||
expect(response).to be_success
|
||||
|
||||
|
@ -586,10 +595,7 @@ describe "Groups" do
|
|||
group_name: group.name
|
||||
))
|
||||
|
||||
expect(post.raw).to eq(I18n.t(
|
||||
'groups.request_membership_pm.body', group_name: group.name
|
||||
))
|
||||
|
||||
expect(post.raw).to eq('Please add me in')
|
||||
expect(topic.archetype).to eq(Archetype.private_message)
|
||||
expect(topic.allowed_users).to contain_exactly(user, owner1, owner2)
|
||||
expect(topic.allowed_groups).to eq([])
|
||||
|
|
|
@ -27,9 +27,7 @@ QUnit.test("Editing group", assert => {
|
|||
assert.ok(find('.group-members-input .item').length === 7, 'it should display group members');
|
||||
assert.ok(find('.group-members-input-selector').length === 1, 'it should display input to add group members');
|
||||
assert.ok(find('.group-members-input-selector .add[disabled]').length === 1, 'add members button should be disabled');
|
||||
});
|
||||
|
||||
andThen(() => {
|
||||
assert.ok(
|
||||
find('.group-edit-allow-membership-requests[disabled]').length === 1,
|
||||
'it should disable group allow_membership_request input'
|
||||
|
@ -44,6 +42,11 @@ QUnit.test("Editing group", assert => {
|
|||
find('.group-edit-public-admission[disabled]').length === 1,
|
||||
'it should disable group public admission input'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
find('.group-edit-membership-request-template').length, 1,
|
||||
'it should display the membership request template field'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -85,6 +85,34 @@ QUnit.test("User Viewing Group", assert => {
|
|||
logIn();
|
||||
Discourse.reset();
|
||||
|
||||
visit("/groups");
|
||||
click('.group-index-request');
|
||||
|
||||
server.post('/groups/Macdonald/request_membership', () => { // eslint-disable-line no-undef
|
||||
return [
|
||||
200,
|
||||
{ "Content-Type": "application/json" },
|
||||
{ relative_url: '/t/internationalization-localization/280' }
|
||||
];
|
||||
});
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(find('.modal-header').text().trim(), I18n.t(
|
||||
'groups.membership_request.title', { group_name: 'Macdonald' }
|
||||
));
|
||||
|
||||
assert.equal(find('.request-group-membership-form textarea').val(), 'Please add me');
|
||||
});
|
||||
|
||||
click('.modal-footer .btn-primary');
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(
|
||||
find('.fancy-title').text().trim(),
|
||||
"Internationalization / localization"
|
||||
);
|
||||
});
|
||||
|
||||
visit("/groups/discourse");
|
||||
|
||||
click('.group-message-button');
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export default {
|
||||
"/groups.json": {"groups":[{"id":41,"automatic":false,"name":"discourse","user_count":0,"alias_level":0,"visible":true,"automatic_membership_email_domains":"","automatic_membership_retroactive":false,"primary_group":false,"title":null,"grant_trust_level":null,"has_messages":false,"flair_url":null,"flair_bg_color":null,"flair_color":null,"bio_raw":"","bio_cooked":null,"public_admission":true,"allow_membership_requests":false,"full_name":"Awesome Team"},{"id":42,"automatic":false,"name":"Macdonald","user_count":0,"alias_level":99,"visible":true,"automatic_membership_email_domains":"","automatic_membership_retroactive":false,"primary_group":false,"title":null,"grant_trust_level":null,"has_messages":false,"flair_url":null,"flair_bg_color":null,"flair_color":null,"bio_raw":null,"bio_cooked":null,"public_admission":false,"allow_membership_requests":true,"full_name":null}],"extras":{"group_user_ids":[]},"total_rows_groups":2,"load_more_groups":"/groups?page=1"}
|
||||
"/groups.json": {"groups":[{"id":41,"automatic":false,"name":"discourse","user_count":0,"alias_level":0,"visible":true,"automatic_membership_email_domains":"","automatic_membership_retroactive":false,"primary_group":false,"title":null,"grant_trust_level":null,"has_messages":false,"flair_url":null,"flair_bg_color":null,"flair_color":null,"bio_raw":"","bio_cooked":null,"public_admission":true,"allow_membership_requests":false,"full_name":"Awesome Team"},{"id":42,"automatic":false,"name":"Macdonald","user_count":0,"alias_level":99,"visible":true,"automatic_membership_email_domains":"","automatic_membership_retroactive":false,"primary_group":false,"title":null,"grant_trust_level":null,"has_messages":false,"flair_url":null,"flair_bg_color":null,"flair_color":null,"bio_raw":null,"bio_cooked":null,"public_admission":false,"allow_membership_requests":true,"membership_request_template":"Please add me","full_name":null}],"extras":{"group_user_ids":[]},"total_rows_groups":2,"load_more_groups":"/groups?page=1"}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue