FEATURE: First stab at groups page with member list

This commit is contained in:
Robin Ward 2014-02-07 10:44:03 -05:00
parent e511e8a80b
commit 3b617b04b0
14 changed files with 149 additions and 11 deletions

View File

@ -1,3 +1,11 @@
/**
The basic controller for a group
@class GroupController
@extends Discourse.ObjectController
@namespace Discourse
@module Discourse
**/
Discourse.GroupController = Discourse.ObjectController.extend({
// It would be nice if bootstrap marked action lists as selected when their links

View File

@ -0,0 +1,32 @@
/**
Handles displaying posts within a group
@class GroupIndexController
@extends Ember.ArrayController
@namespace Discourse
@module Discourse
**/
Discourse.GroupIndexController = Ember.ArrayController.extend({
needs: ['group'],
loading: false,
actions: {
loadMore: function() {
if (this.get('loading')) { return; }
this.set('loading', true);
var posts = this.get('model'),
self = this;
if (posts && posts.length) {
var lastPostId = posts[posts.length-1].get('id'),
group = this.get('controllers.group.model');
group.findPosts({beforePostId: lastPostId}).then(function(newPosts) {
posts.addObjects(newPosts);
self.set('loading', false);
});
}
}
}
});

View File

@ -126,8 +126,21 @@ Discourse.Group = Discourse.Model.extend({
var message = $.parseJSON(e.responseText).errors;
bootbox.alert(message);
});
}
},
findPosts: function(opts) {
opts = opts || {};
var data = {};
if (opts.beforePostId) { data.before_post_id = opts.beforePostId; }
return Discourse.ajax("/groups/" + this.get('name') + "/posts.json", { data: data }).then(function (posts) {
return posts.map(function (p) {
p.user = Discourse.User.create(p.user);
return Em.Object.create(p);
});
});
}
});
Discourse.Group.reopenClass({

View File

@ -1,6 +1,14 @@
/**
The route for the index of a Group
@class GroupIndexRoute
@extends Discourse.Route
@namespace Discourse
@module Discourse
**/
Discourse.GroupIndexRoute = Discourse.Route.extend({
model: function() {
return this.modelFor('group');
return this.modelFor('group').findPosts();
},
setupController: function(controller, model) {

View File

@ -1,3 +1,11 @@
/**
Set things up to display the members of a group
@class GroupMembersRoute
@extends Discourse.Route
@namespace Discourse
@module Discourse
**/
Discourse.GroupMembersRoute = Discourse.Route.extend({
model: function() {
return this.modelFor('group');

View File

@ -1,3 +1,11 @@
/**
The base route for a group
@class GroupRoute
@extends Discourse.Route
@namespace Discourse
@module Discourse
**/
Discourse.GroupRoute = Discourse.Route.extend({
model: function(params) {

View File

@ -1,3 +1,16 @@
GROUP INDEX
{{name}}
<div class='user-stream'>
{{#groupedEach model}}
<div class='item'>
<div class='clearfix info'>
{{#link-to 'user' user class="avatar-link"}}<div class='avatar-wrapper'>{{avatar user imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div>{{/link-to}}
<span class='time'>{{unboundDate path="created_at" leaveAgo="true"}}</span>
<span class="title">
<a href="{{unbound url}}">{{unbound title}}</a>
</span>
</div>
<p class='excerpt'>
{{{unbound cooked}}}
</p>
</div>
{{/groupedEach}}
</div>

View File

@ -44,11 +44,12 @@
<div class='bio'>{{{bio_cooked}}}</div>
{{#if custom_groups}}
<div class='groups'>
{{#each custom_groups}}
{{#link-to 'group' this}}{{name}}{{/link-to}}
{{/each}}
</div>
<div class='groups'>
{{i18n groups.title count=custom_groups.length}}:
{{#each custom_groups}}
{{#link-to 'group' this}}{{name}}{{/link-to}}
{{/each}}
</div>
{{/if}}
{{#if isSuspended}}

View File

@ -0,0 +1,4 @@
Discourse.GroupIndexView = Discourse.View.extend(Discourse.LoadMore, {
eyelineSelector: '.user-stream .item'
});

View File

@ -6,6 +6,13 @@ class GroupsController < ApplicationController
render_serialized(group, BasicGroupSerializer)
end
def posts
group = Group.where(name: params.require(:group_id)).first
guardian.ensure_can_see!(group)
posts = group.posts_for(guardian, params[:before_post_id])
render_serialized posts.to_a, GroupPostSerializer
end
def members
group = Group.where(name: params.require(:group_id)).first
guardian.ensure_can_see!(group)

View File

@ -31,6 +31,24 @@ class Group < ActiveRecord::Base
validate :alias_level, inclusion: { in: ALIAS_LEVELS.values}
def posts_for(guardian, before_post_id)
user_ids = group_users.map {|gu| gu.user_id}
result = Post.where(user_id: user_ids).includes(:user, :topic).references(:posts, :topics)
result = result.where('topics.archetype <> ?', Archetype.private_message)
unless guardian.is_staff?
allowed_ids = guardian.allowed_category_ids
if allowed_ids.length > 0
result = result.where('topics.category_id IS NULL or topics.category_id IN (?)', allowed_ids)
else
result = result.where('topics.category_id IS NULL')
end
end
result = result.where('posts.id < ?', before_post_id) if before_post_id
result.order('posts.created_at desc').limit(20)
end
def self.trust_group_ids
(10..19).to_a
end
@ -156,7 +174,6 @@ class Group < ActiveRecord::Base
end
end
def self.builtin
Enum.new(:moderators, :admins, :trust_level_1, :trust_level_2)
end

View File

@ -0,0 +1,15 @@
class GroupPostSerializer < ApplicationSerializer
attributes :id,
:cooked,
:created_at,
:title,
:url
has_one :user, serializer: BasicUserSerializer, embed: :objects
def title
object.topic.title
end
end

View File

@ -174,6 +174,9 @@ en:
sent_by_you: "Sent by <a href='{{userUrl}}'>you</a>"
groups:
title:
one: "group"
other: "groups"
members: "Members"
posts: "Posts"
alias_levels:

View File

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