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 781d9be9ab8..f03d7d0d8f2 100644 --- a/app/assets/javascripts/discourse/controllers/user-invited-show.js.es6 +++ b/app/assets/javascripts/discourse/controllers/user-invited-show.js.es6 @@ -7,6 +7,7 @@ export default Ember.Controller.extend({ model: null, filter: null, totalInvites: null, + invitesCount: null, canLoadMore: true, invitesLoading: false, @@ -58,6 +59,22 @@ export default Ember.Controller.extend({ return this.get('totalInvites') > 9; }.property('totalInvites'), + pendingLabel: function() { + if (this.get('invitesCount.total') > 50) { + return I18n.t('user.invited.pending_tab_with_count', {count: this.get('invitesCount.pending')}); + } else { + return I18n.t('user.invited.pending_tab'); + } + }.property('invitesCount'), + + redeemedLabel: function() { + if (this.get('invitesCount.total') > 50) { + return I18n.t('user.invited.redeemed_tab_with_count', {count: this.get('invitesCount.redeemed')}); + } else { + return I18n.t('user.invited.redeemed_tab'); + } + }.property('invitesCount'), + actions: { rescind(invite) { diff --git a/app/assets/javascripts/discourse/models/invite.js.es6 b/app/assets/javascripts/discourse/models/invite.js.es6 index 8f9bcd0bdea..49a116bda60 100644 --- a/app/assets/javascripts/discourse/models/invite.js.es6 +++ b/app/assets/javascripts/discourse/models/invite.js.es6 @@ -43,6 +43,11 @@ Invite.reopenClass({ return Em.Object.create(result); }); + }, + + 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)); } }); diff --git a/app/assets/javascripts/discourse/routes/user-invited-show.js.es6 b/app/assets/javascripts/discourse/routes/user-invited-show.js.es6 index 48e6d415cb5..c9465fa7d14 100644 --- a/app/assets/javascripts/discourse/routes/user-invited-show.js.es6 +++ b/app/assets/javascripts/discourse/routes/user-invited-show.js.es6 @@ -4,8 +4,12 @@ import showModal from "discourse/lib/show-modal"; export default Discourse.Route.extend({ model(params) { - this.inviteFilter = params.filter; - return Invite.findInvitedBy(this.modelFor("user"), params.filter); + const self = this; + Invite.findInvitedCount(self.modelFor("user")).then(function (result) { + self.set('invitesCount', result); + }); + self.inviteFilter = params.filter; + return Invite.findInvitedBy(self.modelFor("user"), params.filter); }, afterModel(model) { @@ -20,7 +24,8 @@ export default Discourse.Route.extend({ user: this.controllerFor("user").get("model"), filter: this.inviteFilter, searchTerm: "", - totalInvites: model.invites.length + totalInvites: model.invites.length, + invitesCount: this.get('invitesCount') }); }, diff --git a/app/assets/javascripts/discourse/templates/components/nav-item.hbs b/app/assets/javascripts/discourse/templates/components/nav-item.hbs index ec8e0a1e758..96c49a6fc3d 100644 --- a/app/assets/javascripts/discourse/templates/components/nav-item.hbs +++ b/app/assets/javascripts/discourse/templates/components/nav-item.hbs @@ -1,5 +1,9 @@ {{#if routeParam}} - {{#link-to route routeParam}}{{i18n label}}{{/link-to}} + {{#if i18nLabel}} + {{#link-to route routeParam}}{{i18nLabel}}{{/link-to}} + {{else}} + {{#link-to route routeParam}}{{i18n label}}{{/link-to}} + {{/if}} {{else}} {{#if route}} {{#link-to route}}{{i18n label}}{{/link-to}} diff --git a/app/assets/javascripts/discourse/templates/user-invited-show.hbs b/app/assets/javascripts/discourse/templates/user-invited-show.hbs index a13bb5860c5..29c37bcb992 100644 --- a/app/assets/javascripts/discourse/templates/user-invited-show.hbs +++ b/app/assets/javascripts/discourse/templates/user-invited-show.hbs @@ -6,8 +6,8 @@
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 83902f434bb..bb550483d3c 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -181,6 +181,16 @@ class UsersController < ApplicationController can_see_invite_details: guardian.can_see_invite_details?(inviter) end + def invited_count + inviter = fetch_user_from_params + + pending_count = Invite.find_pending_invites_count(inviter) + redeemed_count = Invite.find_redeemed_invites_count(inviter) + + render json: {counts: { pending: pending_count, redeemed: redeemed_count, + total: (pending_count.to_i + redeemed_count.to_i) } } + end + def is_local_username users = params[:usernames] users = [params[:username]] if users.blank? diff --git a/app/models/invite.rb b/app/models/invite.rb index d4a509ab12e..6929084fcab 100644 --- a/app/models/invite.rb +++ b/app/models/invite.rb @@ -151,13 +151,13 @@ class Invite < ActiveRecord::Base group_ids end - def self.find_all_invites_from(inviter, offset=0) + def self.find_all_invites_from(inviter, offset=0, limit=SiteSetting.invites_per_page) Invite.where(invited_by_id: inviter.id) .includes(:user => :user_stat) .order('CASE WHEN invites.user_id IS NOT NULL THEN 0 ELSE 1 END', 'user_stats.time_read DESC', 'invites.redeemed_at DESC') - .limit(SiteSetting.invites_per_page) + .limit(limit) .offset(offset) .references('user_stats') end @@ -170,6 +170,14 @@ class Invite < ActiveRecord::Base find_all_invites_from(inviter, offset).where('invites.user_id IS NOT NULL').order('invites.redeemed_at DESC') end + def self.find_pending_invites_count(inviter) + find_all_invites_from(inviter, 0, nil).where('invites.user_id IS NULL').count + end + + def self.find_redeemed_invites_count(inviter) + find_all_invites_from(inviter, 0, nil).where('invites.user_id IS NOT NULL').count + end + def self.filter_by(email_or_username) if email_or_username where( diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 3eddbd92de1..472d780b431 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -609,9 +609,11 @@ en: truncated: "Showing the first {{count}} invites." redeemed: "Redeemed Invites" redeemed_tab: "Redeemed" + redeemed_tab_with_count: "Redeemed ({{count}})" redeemed_at: "Redeemed" pending: "Pending Invites" pending_tab: "Pending" + pending_tab_with_count: "Pending ({{count}})" topics_entered: "Topics Viewed" posts_read_count: "Posts Read" expired: "This invite has expired." diff --git a/config/routes.rb b/config/routes.rb index 235f8243256..c68223269f3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -275,6 +275,7 @@ Discourse::Application.routes.draw do get "users/:username/staff-info" => "users#staff_info", constraints: {username: USERNAME_ROUTE_FORMAT} get "users/:username/invited" => "users#invited", constraints: {username: USERNAME_ROUTE_FORMAT} + get "users/:username/invited_count" => "users#invited_count", constraints: {username: USERNAME_ROUTE_FORMAT} get "users/:username/invited/:filter" => "users#invited", constraints: {username: USERNAME_ROUTE_FORMAT} post "users/action/send_activation_email" => "users#send_activation_email" get "users/:username/activity" => "users#show", constraints: {username: USERNAME_ROUTE_FORMAT}