FEATURE: copy invite link for topic invites

This commit is contained in:
Arpit Jalan 2015-08-31 19:36:13 +05:30
parent ce0a50eae1
commit eb96016043
6 changed files with 49 additions and 40 deletions

View File

@ -20,12 +20,25 @@ export default Ember.Controller.extend(ModalFunctionality, {
if (!this.get('invitingToTopic') && !Discourse.Utilities.emailValid(emailOrUsername)) return true; if (!this.get('invitingToTopic') && !Discourse.Utilities.emailValid(emailOrUsername)) return true;
// normal users (not admin) can't invite users to private topic via email // normal users (not admin) can't invite users to private topic via email
if (!this.get('isAdmin') && this.get('isPrivateTopic') && Discourse.Utilities.emailValid(emailOrUsername)) return true; if (!this.get('isAdmin') && this.get('isPrivateTopic') && Discourse.Utilities.emailValid(emailOrUsername)) return true;
// when invting to private topic via email, group name must be specified // when inviting to private topic via email, group name must be specified
if (this.get('isPrivateTopic') && Ember.isEmpty(this.get('model.groupNames')) && Discourse.Utilities.emailValid(emailOrUsername)) return true; if (this.get('isPrivateTopic') && Ember.isEmpty(this.get('model.groupNames')) && Discourse.Utilities.emailValid(emailOrUsername)) return true;
if (this.get('model.details.can_invite_to')) return false; if (this.get('model.details.can_invite_to')) return false;
return false; return false;
}.property('isAdmin', 'emailOrUsername', 'invitingToTopic', 'isPrivateTopic', 'model.groupNames', 'model.saving'), }.property('isAdmin', 'emailOrUsername', 'invitingToTopic', 'isPrivateTopic', 'model.groupNames', 'model.saving'),
disabledCopyLink: function() {
if (this.get('model.saving')) return true;
if (Ember.isEmpty(this.get('emailOrUsername'))) return true;
const emailOrUsername = this.get('emailOrUsername').trim();
// email must be valid
if (!Discourse.Utilities.emailValid(emailOrUsername)) return true;
// normal users (not admin) can't invite users to private topic via email
if (!this.get('isAdmin') && this.get('isPrivateTopic') && Discourse.Utilities.emailValid(emailOrUsername)) return true;
// when inviting to private topic via email, group name must be specified
if (this.get('isPrivateTopic') && Ember.isEmpty(this.get('model.groupNames')) && Discourse.Utilities.emailValid(emailOrUsername)) return true;
return false;
}.property('emailOrUsername', 'model.saving', 'isPrivateTopic', 'model.groupNames'),
buttonTitle: function() { buttonTitle: function() {
return this.get('model.saving') ? 'topic.inviting' : 'topic.invite_reply.action'; return this.get('model.saving') ? 'topic.inviting' : 'topic.invite_reply.action';
}.property('model.saving'), }.property('model.saving'),
@ -36,9 +49,9 @@ export default Ember.Controller.extend(ModalFunctionality, {
return this.get('model') !== this.currentUser; return this.get('model') !== this.currentUser;
}.property('model'), }.property('model'),
invitingToForum: function() { showCopyInviteButton: function() {
return (!Discourse.SiteSettings.enable_sso && !this.get('invitingToTopic') && !this.get('isMessage')); return (!Discourse.SiteSettings.enable_sso && !this.get('isMessage'));
}.property('invitingToTopic', 'isMessage'), }.property('isMessage'),
topicId: Ember.computed.alias('model.id'), topicId: Ember.computed.alias('model.id'),
@ -163,9 +176,15 @@ export default Ember.Controller.extend(ModalFunctionality, {
userInvitedController = this.get('controllers.user-invited-show'), userInvitedController = this.get('controllers.user-invited-show'),
model = this.get('model'); model = this.get('model');
if (this.get('invitingToTopic')) {
var topicId = this.get('model.id');
} else {
var topicId = null;
}
model.setProperties({ saving: true, error: false }); model.setProperties({ saving: true, error: false });
return this.get('model').generateInviteLink(this.get('emailOrUsername').trim(), groupNames).then(result => { return this.get('model').generateInviteLink(this.get('emailOrUsername').trim(), groupNames, topicId).then(result => {
model.setProperties({ saving: false, finished: true, inviteLink: result }); model.setProperties({ saving: false, finished: true, inviteLink: result });
Invite.findInvitedBy(this.currentUser, userInvitedController.get('filter')).then(invite_model => { Invite.findInvitedBy(this.currentUser, userInvitedController.get('filter')).then(invite_model => {
userInvitedController.set('model', invite_model); userInvitedController.set('model', invite_model);

View File

@ -263,6 +263,13 @@ const Topic = RestModel.extend({
}); });
}, },
generateInviteLink: function(email, groupNames, topicId) {
return Discourse.ajax('/invites/link', {
type: 'POST',
data: {email: email, group_names: groupNames, topic_id: topicId}
});
},
// Delete this topic // Delete this topic
destroy(deleted_by) { destroy(deleted_by) {
this.setProperties({ this.setProperties({

View File

@ -372,10 +372,10 @@ const User = RestModel.extend({
}); });
}, },
generateInviteLink: function(email, groupNames) { generateInviteLink: function(email, groupNames, topicId) {
return Discourse.ajax('/invites/link', { return Discourse.ajax('/invites/link', {
type: 'POST', type: 'POST',
data: {email: email, group_names: groupNames} data: {email: email, group_names: groupNames, topic_id: topicId}
}); });
}, },

View File

@ -29,8 +29,8 @@
{{d-button class="btn-primary" action="closeModal" label="close"}} {{d-button class="btn-primary" action="closeModal" label="close"}}
{{else}} {{else}}
{{d-button icon="envelope" action="createInvite" class="btn-primary" disabled=disabled label=buttonTitle}} {{d-button icon="envelope" action="createInvite" class="btn-primary" disabled=disabled label=buttonTitle}}
{{#if invitingToForum}} {{#if showCopyInviteButton}}
{{d-button icon="link" action="generateInvitelink" class="btn-primary" disabled=disabled label='user.invited.generate_link'}} {{d-button icon="link" action="generateInvitelink" class="btn-primary" disabled=disabledCopyLink label='user.invited.generate_link'}}
{{/if}} {{/if}}
{{/if}} {{/if}}
</div> </div>

View File

@ -51,6 +51,7 @@ class InvitesController < ApplicationController
def create_invite_link def create_invite_link
params.require(:email) params.require(:email)
group_ids = Group.lookup_group_ids(params) group_ids = Group.lookup_group_ids(params)
topic = Topic.find_by(id: params[:topic_id])
guardian.ensure_can_invite_to_forum!(group_ids) guardian.ensure_can_invite_to_forum!(group_ids)
invite_exists = Invite.where(email: params[:email], invited_by_id: current_user.id).first invite_exists = Invite.where(email: params[:email], invited_by_id: current_user.id).first
@ -59,7 +60,7 @@ class InvitesController < ApplicationController
end end
# generate invite link # generate invite link
invite_link = Invite.generate_invite_link(params[:email], current_user, group_ids) invite_link = Invite.generate_invite_link(params[:email], current_user, topic, group_ids)
render_json_dump(invite_link) render_json_dump(invite_link)
end end

View File

@ -72,10 +72,20 @@ class Invite < ActiveRecord::Base
end end
end end
def self.invite_by_email(email, invited_by, topic=nil, group_ids=nil)
create_invite_by_email(email, invited_by, topic, group_ids, true)
end
# generate invite link
def self.generate_invite_link(email, invited_by, topic=nil, group_ids=nil)
invite = create_invite_by_email(email, invited_by, topic, group_ids, false)
return "#{Discourse.base_url}/invites/#{invite.invite_key}"
end
# Create an invite for a user, supplying an optional topic # Create an invite for a user, supplying an optional topic
# #
# Return the previously existing invite if already exists. Returns nil if the invite can't be created. # Return the previously existing invite if already exists. Returns nil if the invite can't be created.
def self.invite_by_email(email, invited_by, topic=nil, group_ids=nil) def self.create_invite_by_email(email, invited_by, topic=nil, group_ids=nil, send_email=true)
lower_email = Email.downcase(email) lower_email = Email.downcase(email)
user = User.find_by(email: lower_email) user = User.find_by(email: lower_email)
@ -116,40 +126,12 @@ class Invite < ActiveRecord::Base
end end
end end
Jobs.enqueue(:invite_email, invite_id: invite.id) Jobs.enqueue(:invite_email, invite_id: invite.id) if send_email
invite.reload invite.reload
invite invite
end end
# generate invite link
def self.generate_invite_link(email, invited_by, group_ids=nil)
lower_email = Email.downcase(email)
invite = Invite.with_deleted
.where(email: lower_email, invited_by_id: invited_by.id)
.order('created_at DESC')
.first
if invite && (invite.expired? || invite.deleted_at)
invite.destroy
invite = nil
end
if !invite
invite = Invite.create!(invited_by: invited_by, email: lower_email)
end
if group_ids.present?
group_ids = group_ids - invite.invited_groups.pluck(:group_id)
group_ids.each do |group_id|
invite.invited_groups.create!(group_id: group_id)
end
end
return "#{Discourse.base_url}/invites/#{invite.invite_key}"
end
# generate invite tokens without email # generate invite tokens without email
def self.generate_disposable_tokens(invited_by, quantity=nil, group_names=nil) def self.generate_disposable_tokens(invited_by, quantity=nil, group_names=nil)
invite_tokens = [] invite_tokens = []