FEATURE: Show the posts count on the groups page. It seems a bit odd

that it uses a new AJAX call, but I wanted to keep the count separate
from the group object itself.
This commit is contained in:
Robin Ward 2014-02-12 14:00:45 -05:00
parent 6bbc3ec3e0
commit 669247977b
8 changed files with 57 additions and 8 deletions

View file

@ -7,6 +7,7 @@
@module Discourse @module Discourse
**/ **/
Discourse.GroupController = Discourse.ObjectController.extend({ Discourse.GroupController = Discourse.ObjectController.extend({
postsCount: null,
// It would be nice if bootstrap marked action lists as selected when their links // It would be nice if bootstrap marked action lists as selected when their links
// were 'active' not the `li` tags. // were 'active' not the `li` tags.

View file

@ -154,6 +154,12 @@ Discourse.Group.reopenClass({
}); });
}, },
findPostsCount: function(name) {
return Discourse.ajax("/groups/" + name + "/posts_count.json").then(function(g) {
return g.posts_count;
});
},
find: function(name) { find: function(name) {
return Discourse.ajax("/groups/" + name + ".json").then(function(g) { return Discourse.ajax("/groups/" + name + ".json").then(function(g) {
return Discourse.Group.create(g.basic_group); return Discourse.Group.create(g.basic_group);

View file

@ -12,4 +12,17 @@ Discourse.GroupRoute = Discourse.Route.extend({
return Discourse.Group.find(params.name); return Discourse.Group.find(params.name);
}, },
afterModel: function(model) {
var self = this;
return Discourse.Group.findPostsCount(model.get('name')).then(function (c) {
self.set('postsCount', c);
});
},
setupController: function(controller, model) {
controller.setProperties({
model: model,
postsCount: this.get('postsCount')
});
}
}); });

View file

@ -1,10 +1,17 @@
<div class="container"> <div class="container">
<section class='user-navigation'> <section class='user-navigation'>
<ul class='action-list nav-stacked'> <ul class='action-list nav-stacked'>
<li {{bind-attr class="showingIndex:active"}}>{{#link-to 'group.index' model}}{{i18n groups.posts}}{{/link-to}}</li> <li {{bind-attr class="showingIndex:active"}}>
<li {{bind-attr class="showingMembers:active"}}>{{#link-to 'group.members' model}}{{i18n groups.members}}{{/link-to}}</li> {{#link-to 'group.index' model}}{{i18n groups.posts}}
</ul> <span class='count'>({{postsCount}})</span>
</section> <span class='fa fa-chevron-right'></span>{{/link-to}}
</li>
<li {{bind-attr class="showingMembers:active"}}>
{{#link-to 'group.members' model}}{{i18n groups.members}}
<span class='fa fa-chevron-right'></span>{{/link-to}}
</li>
</ul>
</section>
<section class='user-main'> <section class='user-main'>
<section class='about'> <section class='about'>

View file

@ -6,10 +6,16 @@ class GroupsController < ApplicationController
render_serialized(group, BasicGroupSerializer) render_serialized(group, BasicGroupSerializer)
end end
def posts_count
group = Group.where(name: params.require(:group_id)).first
guardian.ensure_can_see!(group)
render json: {posts_count: group.posts_for(guardian).count}
end
def posts def posts
group = Group.where(name: params.require(:group_id)).first group = Group.where(name: params.require(:group_id)).first
guardian.ensure_can_see!(group) guardian.ensure_can_see!(group)
posts = group.posts_for(guardian, params[:before_post_id]) posts = group.posts_for(guardian, params[:before_post_id]).limit(20)
render_serialized posts.to_a, GroupPostSerializer render_serialized posts.to_a, GroupPostSerializer
end end

View file

@ -31,7 +31,7 @@ class Group < ActiveRecord::Base
validate :alias_level, inclusion: { in: ALIAS_LEVELS.values} validate :alias_level, inclusion: { in: ALIAS_LEVELS.values}
def posts_for(guardian, before_post_id) def posts_for(guardian, before_post_id=nil)
user_ids = group_users.map {|gu| gu.user_id} user_ids = group_users.map {|gu| gu.user_id}
result = Post.where(user_id: user_ids).includes(:user, :topic).references(:posts, :topics) result = Post.where(user_id: user_ids).includes(:user, :topic).references(:posts, :topics)
result = result.where('topics.archetype <> ?', Archetype.private_message) result = result.where('topics.archetype <> ?', Archetype.private_message)
@ -46,7 +46,7 @@ class Group < ActiveRecord::Base
end end
result = result.where('posts.id < ?', before_post_id) if before_post_id result = result.where('posts.id < ?', before_post_id) if before_post_id
result.order('posts.created_at desc').limit(20) result.order('posts.created_at desc')
end end
def self.trust_group_ids def self.trust_group_ids

View file

@ -167,6 +167,7 @@ Discourse::Application.routes.draw do
resources :groups do resources :groups do
get 'members' get 'members'
get 'posts' get 'posts'
get 'posts_count'
end end
resources :posts do resources :posts do

View file

@ -18,6 +18,21 @@ describe GroupsController do
end end
end end
describe "posts_count" do
it "ensures the group can be seen" do
Guardian.any_instance.expects(:can_see?).with(group).returns(false)
xhr :get, :posts_count, group_id: group.name
response.should_not be_success
end
it "performs the query and responds with JSON" do
Guardian.any_instance.expects(:can_see?).with(group).returns(true)
Group.any_instance.expects(:posts_for).returns(Group.none)
xhr :get, :posts_count, group_id: group.name
response.should be_success
end
end
describe "posts" do describe "posts" do
it "ensures the group can be seen" do it "ensures the group can be seen" do
Guardian.any_instance.expects(:can_see?).with(group).returns(false) Guardian.any_instance.expects(:can_see?).with(group).returns(false)
@ -27,7 +42,7 @@ describe GroupsController do
it "calls `posts_for` and responds with JSON" do it "calls `posts_for` and responds with JSON" do
Guardian.any_instance.expects(:can_see?).with(group).returns(true) Guardian.any_instance.expects(:can_see?).with(group).returns(true)
Group.any_instance.expects(:posts_for).returns([]) Group.any_instance.expects(:posts_for).returns(Group.none)
xhr :get, :posts, group_id: group.name xhr :get, :posts, group_id: group.name
response.should be_success response.should be_success
end end