Commit ca5ebf95375cd5dbb80a047dc79f4c31e36df899

Authored by Eduardo Tourinho Edington
1 parent 04962ef3

Pagination of comments and replies on profile wall.

The comments and replies are fetched only after the View all and More links are clicked.
app/controllers/public/profile_controller.rb
... ... @@ -210,6 +210,48 @@ class ProfileController < PublicController
210 210 render :partial => 'profile_network_activities', :locals => {:network_activities => @activities}
211 211 end
212 212  
  213 + def more_comments
  214 + activity_id = params[:activity].to_i
  215 + activity = ActionTracker::Record.find(:first, :conditions => {:id => activity_id, :user_id => @profile.id})
  216 + comments_count = activity.comments.count
  217 + comment_page = (params[:comment_page] || 1).to_i
  218 + comments_per_page = 5
  219 + no_more_pages = comments_count <= comment_page * comments_per_page
  220 +
  221 + render :update do |page|
  222 + page.insert_html :bottom, 'profile-wall-activities-comments-'+params[:activity],
  223 + :partial => 'comment', :collection => activity.comments.paginate(:per_page => comments_per_page, :page => comment_page)
  224 +
  225 + if no_more_pages
  226 + page.remove 'profile-wall-activities-comments-more-'+params[:activity]
  227 + else
  228 + page.replace_html 'profile-wall-activities-comments-more-'+params[:activity],
  229 + :partial => 'more_comments', :locals => {:activity => activity, :comment_page => comment_page}
  230 + end
  231 + end
  232 + end
  233 +
  234 + def more_replies
  235 + activity_id = params[:activity].to_i
  236 + activity = Scrap.find(:first, :conditions => {:id => activity_id, :receiver_id => @profile.id, :scrap_id => nil})
  237 + comments_count = activity.replies.count
  238 + comment_page = (params[:comment_page] || 1).to_i
  239 + comments_per_page = 5
  240 + no_more_pages = comments_count <= comment_page * comments_per_page
  241 +
  242 + render :update do |page|
  243 + page.insert_html :bottom, 'profile-wall-activities-comments-'+params[:activity],
  244 + :partial => 'profile_scrap', :collection => activity.replies.paginate(:per_page => comments_per_page, :page => comment_page), :as => :scrap
  245 +
  246 + if no_more_pages
  247 + page.remove 'profile-wall-activities-comments-more-'+params[:activity]
  248 + else
  249 + page.replace_html 'profile-wall-activities-comments-more-'+params[:activity],
  250 + :partial => 'more_replies', :locals => {:activity => activity, :comment_page => comment_page}
  251 + end
  252 + end
  253 + end
  254 +
213 255 def remove_scrap
214 256 begin
215 257 scrap = current_user.person.scraps(params[:scrap_id])
... ... @@ -343,6 +385,7 @@ class ProfileController &lt; PublicController
343 385 end
344 386 end
345 387  
  388 +
346 389 protected
347 390  
348 391 def check_access_to_profile
... ... @@ -393,4 +436,5 @@ class ProfileController &lt; PublicController
393 436 def relations_to_include
394 437 [:image, :domains, :preferred_domain, :environment]
395 438 end
  439 +
396 440 end
... ...
app/views/profile/_more_comments.rhtml 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +<div class='view-more-comments'>
  2 + <%= link_to_remote(_('More'), :url => { :profile => @profile.identifier, :controller => 'profile', :action => 'more_comments', :activity => activity, :comment_page => (comment_page + 1)}) %>
  3 +</div>
... ...
app/views/profile/_more_replies.rhtml 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +<div class='view-more-replies'>
  2 + <%= link_to_remote(_('More'), :url => { :profile => @profile.identifier, :controller => 'profile', :action => 'more_replies', :activity => activity, :comment_page => (comment_page + 1)}) %>
  3 +</div>
... ...
app/views/profile/_profile_activities_list.rhtml
... ... @@ -4,7 +4,7 @@
4 4 <% if activity.kind_of?(ActionTracker::Record) %>
5 5 <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'wall' } if activity.visible? %>
6 6 <% else %>
7   - <%= render :partial => 'profile_scrap', :locals => {:scrap => activity } %>
  7 + <%= render :partial => 'profile_scraps', :locals => { :activity => activity, :scrap => activity } %>
8 8 <% end %>
9 9 <% end %>
10 10 <% end %>
... ...
app/views/profile/_profile_comments.rhtml
1 1 <hr />
2 2  
3   -<% if activity.comments_count > 2 %>
  3 +<ul id="profile-wall-activities-comments-<%= activity.id %>" class="profile-wall-activities-comments" >
  4 +</ul>
  5 +<% if activity.comments_count > 0 %>
  6 +<div id="profile-wall-activities-comments-more-<%= activity.id %>" class="profile-wall-activities-comments" >
4 7 <div class='view-all-comments icon-chat'>
5   - <%= link_to(_("View all %s comments") % activity.comments_count, '#') %>
  8 + <%= link_to_remote(_("View all %s comments") % activity.comments_count, :url => { :profile => profile.identifier, :controller => 'profile', :action => 'more_comments', :activity => activity, :comment_page => (1)}) %>
6 9 </div>
  10 +</div>
7 11 <% end %>
8   -
9   -<ul class="profile-wall-activities-comments" style="<%= 'display:none;' if (activity.comments_count > 2) %>" >
10   - <%= render :partial => 'comment', :collection => activity.comments_as_thread %>
11   -</ul>
12   -
13 12 <%= render :partial => 'profile_comment_form', :locals => { :activity => activity, :tab_action => tab_action } %>
... ...
app/views/profile/_profile_scrap.rhtml
... ... @@ -16,13 +16,7 @@
16 16 </div>
17 17 </div>
18 18  
19   - <% if scrap.replies.count > 2 %>
20   - <div class='view-all-comments icon-chat'>
21   - <%= link_to(_("View all %s comments") % scrap.replies.count, '#') %>
22   - </div>
23   - <% end %>
24   -
25   - <ul class="profile-wall-activities-comments scrap-replies" style="width: auto; <%= 'display:none;' if (scrap.replies.count > 2) %>" >
  19 + <ul class="profile-wall-activities-comments scrap-replies" style="width: auto;" >
26 20 <% scrap.replies.map do |reply| %>
27 21 <%= render :partial => 'profile_scrap', :locals => {:scrap => reply} %>
28 22 <% end %>
... ...
app/views/profile/_profile_scraps.rhtml
1   -NÃO DEVE APARECER
  1 +<li class='profile-activity-item' id='profile-activity-item-<%= scrap.id %>'>
  2 + <div class='profile-activity-image'>
  3 + <%= link_to(profile_image(scrap.sender, :minor), scrap.sender.url) %>
  4 + </div>
  5 + <div class='profile-activity-description'>
  6 + <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p>
  7 + <p class='profile-activity-text'><%= txt2html scrap.content %></p>
  8 + <p class='profile-activity-time'><%= time_ago_as_sentence(scrap.created_at) %></p>
  9 + <div class='profile-wall-actions'>
  10 + <% if logged_in? && current_person.follows?(scrap.sender) %>
  11 + <span class='profile-activity-send-reply'>
  12 + <%= link_to_function s_('profile|Comment'), "hide_and_show(['#profile-wall-message-response-#{scrap.id}'],['#profile-wall-reply-#{scrap.id}', '#profile-wall-reply-form-#{scrap.id}']);$('reply_content_#{scrap.id}').value='';$('reply_content_#{scrap.id}').focus();return false", :class => "profile-send-reply" %>
  13 + </span>
  14 + <% end %>
  15 + <%= link_to_function(_('Remove'), 'remove_item_wall(this, %s, %s, %s); return false ;' % ["'.profile-activity-item'", url_for(:profile => params[:profile], :action => :remove_scrap, :scrap_id => scrap.id, :view => params[:view]).to_json, _('Are you sure you want to remove this scrap and all its replies?').to_json]) if logged_in? && user.can_control_scrap?(scrap) %>
  16 + </div>
  17 + </div>
  18 +
  19 +
  20 + <ul id="profile-wall-activities-comments-<%= activity.id %>" class="profile-wall-activities-comments scrap-replies" style="width: auto;" >
  21 + </ul>
  22 +
  23 + <% if scrap.replies.count > 0 %>
  24 + <div id="profile-wall-activities-comments-more-<%= activity.id %>" class="profile-wall-activities-comments">
  25 + <div class='view-all-comments icon-chat'>
  26 + <%= link_to_remote(_("View all %s comments") % scrap.replies.count, :url => { :profile => profile.identifier, :controller => 'profile', :action => 'more_replies', :activity => activity, :comment_page => (1)}) %>
  27 + </div>
  28 + </div>
  29 + <% end %>
  30 + <%= render :partial => 'profile_scrap_reply_form', :locals => { :scrap => scrap } %>
  31 + <hr />
  32 +</li>
2 33 \ No newline at end of file
... ...
public/stylesheets/application.css
... ... @@ -5681,6 +5681,13 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
5681 5681 padding-left: 20px;
5682 5682 }
5683 5683  
  5684 +.view-more-comments, .view-more-replies {
  5685 + border-bottom: 1px solid #d2d2d2 !important;
  5686 + border-top: 1px solid #fff;
  5687 + margin-bottom: 0;
  5688 + text-align: center;
  5689 +}
  5690 +
5684 5691 /* Profile activity relative dimensions */
5685 5692  
5686 5693 #leave_scrap {
... ...
test/functional/profile_controller_test.rb
... ... @@ -1170,6 +1170,58 @@ class ProfileControllerTest &lt; ActionController::TestCase
1170 1170 assert_redirected_to :controller => 'account', :action => 'login'
1171 1171 end
1172 1172  
  1173 + should "not index display activities comments" do
  1174 + login_as(profile.identifier)
  1175 + article = TinyMceArticle.create!(:profile => profile, :name => 'An Article about Free Software')
  1176 + ActionTracker::Record.destroy_all
  1177 + activity = ActionTracker::Record.create!(:user_id => profile.id, :user_type => 'Profile', :verb => 'create_article', :target_id => article.id, :target_type => 'Article', :params => {'name' => article.name, 'url' => article.url, 'lead' => article.lead, 'first_image' => article.first_image})
  1178 + 20.times {comment = fast_create(Comment, :source_id => article, :title => 'a comment', :body => 'lalala', :created_at => Time.now)}
  1179 + article.reload
  1180 + get :index, :profile => profile.identifier
  1181 + assert_tag 'ul', :attributes => {:class => 'profile-wall-activities-comments'}, :children => {:count => 0 }
  1182 + end
  1183 +
  1184 + should "view more comments paginated" do
  1185 + login_as(profile.identifier)
  1186 + article = TinyMceArticle.create!(:profile => profile, :name => 'An Article about Free Software')
  1187 + ActionTracker::Record.destroy_all
  1188 + activity = ActionTracker::Record.create!(:user_id => profile.id, :user_type => 'Profile', :verb => 'create_article', :target_id => article.id, :target_type => 'Article', :params => {'name' => article.name, 'url' => article.url, 'lead' => article.lead, 'first_image' => article.first_image})
  1189 + 20.times {comment = fast_create(Comment, :source_id => article, :title => 'a comment', :body => 'lalala', :created_at => Time.now)}
  1190 + article.reload
  1191 + assert_equal 20, article.comments.count
  1192 + get :more_comments, :activity => activity.id, :comment_page => 2
  1193 + assert_response :success
  1194 + assert_template '_comment'
  1195 + assert_select_rjs :insert_html do
  1196 + assert_select 'li', 5 # 5 comments per page
  1197 + end
  1198 + end
  1199 +
  1200 + should "not index display scraps replies" do
  1201 + login_as(profile.identifier)
  1202 + Scrap.destroy_all
  1203 + scrap = fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id)
  1204 + 20.times {fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id, :scrap_id => scrap.id)}
  1205 + profile.reload
  1206 + get :index, :profile => profile.identifier
  1207 + assert_tag 'ul', :attributes => {:class => 'profile-wall-activities-comments scrap-replies'}, :children => {:count => 0 }
  1208 + end
  1209 +
  1210 + should "view more replies paginated" do
  1211 + login_as(profile.identifier)
  1212 + Scrap.destroy_all
  1213 + scrap = fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id)
  1214 + 20.times {fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id, :scrap_id => scrap.id)}
  1215 + profile.reload
  1216 + assert_equal 20, scrap.replies.count
  1217 + get :more_replies, :activity => scrap.id, :comment_page => 2
  1218 + assert_response :success
  1219 + assert_template '_profile_scrap'
  1220 + assert_select_rjs :insert_html do
  1221 + assert_select 'li', 5 # 5 replies per page
  1222 + end
  1223 + end
  1224 +
1173 1225 should 'render empty response for not logged in users in check_membership' do
1174 1226 get :check_membership
1175 1227 assert_equal '', @response.body
... ...
vendor/plugins/action_tracker_has_comments/init.rb
... ... @@ -3,22 +3,13 @@
3 3 Rails.configuration.to_prepare do
4 4 ActionTracker::Record.module_eval do
5 5  
6   - has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :finder_sql => 'SELECT * FROM comments WHERE #{conditions_for_comments} ORDER BY created_at ASC', :counter_sql => 'SELECT * FROM comments WHERE #{conditions_for_comments}'
  6 + has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy,
  7 + :finder_sql => 'SELECT * FROM comments WHERE #{conditions_for_comments} ORDER BY created_at ASC',
  8 + :counter_sql => 'SELECT COUNT(*) FROM comments WHERE #{conditions_for_comments}'
7 9  
8 10 def conditions_for_comments
9 11 type, id = (self.target_type == 'Article' ? ['Article', self.target_id] : [self.class.to_s, self.id])
10   - "source_type = '#{type}' AND source_id = '#{id}'"
11   - end
12   -
13   - def comments_as_thread
14   - result = {}
15   - root = []
16   - self.comments.each do |c|
17   - c.replies = []
18   - result[c.id] ||= c
19   - c.reply_of_id.nil? ? root << c : result[c.reply_of_id].replies << c
20   - end
21   - root
  12 + "source_type = '#{type}' AND source_id = '#{id}' AND reply_of_id IS NULL"
22 13 end
23 14  
24 15 end
... ...