diff --git a/app/assets/javascripts/discourse/controllers/user-invited-show.js.es6 b/app/assets/javascripts/discourse/controllers/user-invited-show.js.es6 index f03d7d0d8f2..ed5e0d94788 100644 --- a/app/assets/javascripts/discourse/controllers/user-invited-show.js.es6 +++ b/app/assets/javascripts/discourse/controllers/user-invited-show.js.es6 @@ -10,6 +10,7 @@ export default Ember.Controller.extend({ invitesCount: null, canLoadMore: true, invitesLoading: false, + reinvitedAll: false, init: function() { this._super(); @@ -32,6 +33,10 @@ export default Ember.Controller.extend({ inviteRedeemed: Em.computed.equal('filter', 'redeemed'), + showReinviteAllButton: function() { + return (this.get('filter') === "pending" && this.get('model').invites.length > 4); + }.property('filter'), + /** Can the currently logged in user invite users to the site @@ -87,6 +92,13 @@ export default Ember.Controller.extend({ return false; }, + reinviteAll() { + const self = this; + Invite.reinviteAll().then(function() { + self.set('reinvitedAll', true); + }); + }, + loadMore() { var self = this; var model = self.get('model'); diff --git a/app/assets/javascripts/discourse/models/invite.js.es6 b/app/assets/javascripts/discourse/models/invite.js.es6 index 49a116bda60..9b4b6c8091f 100644 --- a/app/assets/javascripts/discourse/models/invite.js.es6 +++ b/app/assets/javascripts/discourse/models/invite.js.es6 @@ -48,6 +48,10 @@ Invite.reopenClass({ findInvitedCount(user) { if (!user) { return Em.RSVP.resolve(); } return Discourse.ajax("/users/" + user.get('username_lower') + "/invited_count.json").then(result => Em.Object.create(result.counts)); + }, + + reinviteAll() { + return Discourse.ajax('/invites/reinvite-all', { type: 'POST' }); } }); diff --git a/app/assets/javascripts/discourse/templates/user-invited-show.hbs b/app/assets/javascripts/discourse/templates/user-invited-show.hbs index eb88a4c3766..098193b7e81 100644 --- a/app/assets/javascripts/discourse/templates/user-invited-show.hbs +++ b/app/assets/javascripts/discourse/templates/user-invited-show.hbs @@ -17,6 +17,13 @@ {{#if canBulkInvite}} {{resumable-upload target="/invites/upload" success="uploadSuccess" error="uploadError" uploadText=uploadText}} {{/if}} + {{#if showReinviteAllButton}} + {{#if reinvitedAll}} + {{i18n 'user.invited.reinvited_all'}} + {{else}} + {{d-button icon="refresh" action="reinviteAll" class="btn" label="user.invited.reinvite_all"}} + {{/if}} + {{/if}} {{/if}} diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 923e822ce0d..f6696d3b9e0 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -4,7 +4,7 @@ class InvitesController < ApplicationController skip_before_filter :check_xhr, :preload_json skip_before_filter :redirect_to_login_if_required - before_filter :ensure_logged_in, only: [:destroy, :create, :create_invite_link, :resend_invite, :check_csv_chunk, :upload_csv_chunk] + before_filter :ensure_logged_in, only: [:destroy, :create, :create_invite_link, :resend_invite, :resend_all_invites, :check_csv_chunk, :upload_csv_chunk] before_filter :ensure_new_registrations_allowed, only: [:show, :redeem_disposable_invite] before_filter :ensure_not_logged_in, only: [:show, :redeem_disposable_invite] @@ -135,6 +135,13 @@ class InvitesController < ApplicationController render nothing: true end + def resend_all_invites + guardian.ensure_can_invite_to_forum! + + Invite.resend_all_invites_from(current_user.id) + render nothing: true + end + def check_csv_chunk guardian.ensure_can_bulk_invite_to_forum!(current_user) diff --git a/app/models/invite.rb b/app/models/invite.rb index d6e0f02fb27..cd8123c89f6 100644 --- a/app/models/invite.rb +++ b/app/models/invite.rb @@ -233,6 +233,12 @@ class Invite < ActiveRecord::Base Jobs.enqueue(:invite_email, invite_id: self.id) end + def self.resend_all_invites_from(user_id) + Invite.where('invites.user_id IS NULL AND invites.email IS NOT NULL AND invited_by_id = ?', user_id).find_each do |invite| + invite.resend_invite unless invite.blank? + end + end + def limit_invites_per_day RateLimiter.new(invited_by, "invites-per-day", SiteSetting.max_invites_per_day, 1.day.to_i) end diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 64833744344..0e620d4190a 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -723,7 +723,9 @@ en: rescind: "Remove" rescinded: "Invite removed" reinvite: "Resend Invite" + reinvite_all: "Resend all Invites" reinvited: "Invite re-sent" + reinvited_all: "All Invites re-sent!" time_read: "Read Time" days_visited: "Days Visited" account_age_days: "Account age in days" diff --git a/config/routes.rb b/config/routes.rb index beb6892357a..92c24177840 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -580,6 +580,7 @@ Discourse::Application.routes.draw do end end post "invites/reinvite" => "invites#resend_invite" + post "invites/reinvite-all" => "invites#resend_all_invites" post "invites/link" => "invites#create_invite_link" post "invites/disposable" => "invites#create_disposable_invite" get "invites/redeem/:token" => "invites#redeem_disposable_invite"