diff --git a/app/controllers/aspects_controller.rb b/app/controllers/aspects_controller.rb index def9ea151..c4fc158a2 100644 --- a/app/controllers/aspects_controller.rb +++ b/app/controllers/aspects_controller.rb @@ -2,6 +2,8 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. +require File.join(Rails.root, "lib", "aspect_stream") + class AspectsController < ApplicationController before_filter :authenticate_user! before_filter :save_sort_order, :only => :index @@ -11,38 +13,18 @@ class AspectsController < ApplicationController respond_to :json, :only => [:show, :create] helper_method :tags, :tag_followings - helper_method :all_aspects_selected? helper_method :selected_people def index - @aspects = current_user.aspects - @aspects = @aspects.where(:id => params[:a_ids]) if params[:a_ids] - - @aspect_ids = @aspects.map { |a| a.id } - @posts = current_user.visible_posts(:by_members_of => @aspect_ids, - :type => ['StatusMessage','Reshare', 'ActivityStreams::Photo'], - :order => session[:sort_order] + ' DESC', - :max_time => params[:max_time].to_i - ).includes(:mentions => {:person => :profile}, :author => :profile) + @stream = AspectStream.new(current_user, params[:a_ids], + :order => session[:sort_order], + :max_time => params[:max_time]) if params[:only_posts] - render :partial => 'shared/stream', :locals => {:posts => @posts} - else - @contact_count = selected_people(@aspect_ids).count - - # aspects.first is used for mobile - # the :all is currently used for view switching logic - @aspect = (params[:a_ids] ? @aspects.first : :all) + render :partial => 'shared/stream', :locals => {:posts => @stream.posts} end end - def selected_people(aspect_ids) - @selected_people ||= Person.joins(:contacts => :aspect_memberships). - where(:contacts => {:user_id => current_user.id}, - :aspect_memberships => {:aspect_id => @aspect_ids}). - select("DISTINCT people.*").includes(:profile) - end - def create @aspect = current_user.aspects.create(params[:aspect]) @@ -156,10 +138,6 @@ class AspectsController < ApplicationController params[:max_time] ||= Time.now + 1 end - def all_aspects_selected? - @aspect == :all - end - def tag_followings if current_user if @tag_followings == nil diff --git a/app/helpers/stream_helper.rb b/app/helpers/stream_helper.rb index bc6abbd0c..0def79982 100644 --- a/app/helpers/stream_helper.rb +++ b/app/helpers/stream_helper.rb @@ -11,7 +11,7 @@ module StreamHelper elsif controller.instance_of?(PeopleController) person_path(@person, :max_time => @posts.last.created_at.to_i) elsif controller.instance_of?(AspectsController) - aspects_path(:max_time => @posts.last.send(session[:sort_order].to_sym).to_i, :a_ids => params[:a_ids]) + aspects_path(:max_time => @stream.posts.last.send(@stream.order.to_sym).to_i, :a_ids => @stream.aspect_ids) else raise 'in order to use pagination for this new controller, update next_page_path in stream helper' end diff --git a/app/views/aspects/_aspect_stream.haml b/app/views/aspects/_aspect_stream.haml index 50936ef70..4acd1f9f6 100644 --- a/app/views/aspects/_aspect_stream.haml +++ b/app/views/aspects/_aspect_stream.haml @@ -6,24 +6,24 @@ #sort_by = t('.recently') %span.controls - = link_to_if(session[:sort_order] == 'created_at', t('.commented_on'), aspects_path(:a_ids => params[:a_ids], :sort_order => 'updated_at')) + = link_to_if(session[:sort_order] == 'created_at', t('.commented_on'), aspects_path(:a_ids => stream.aspect_ids, :sort_order => 'updated_at')) ยท - = link_to_if(session[:sort_order] == 'updated_at', t('.posted'), aspects_path(:a_ids => params[:a_ids], :sort_order => 'created_at' )) + = link_to_if(session[:sort_order] == 'updated_at', t('.posted'), aspects_path(:a_ids => stream.aspect_ids, :sort_order => 'created_at' )) %h3 - - if all_aspects_selected? + - if stream.for_all_aspects? = t('.stream') - else - = @aspects.to_sentence + = stream.aspects.to_sentence -= render 'shared/publisher', :selected_aspects => @aspects, :aspect_ids => aspect_ids, :aspect => @aspect += render 'shared/publisher', :selected_aspects => stream.aspects, :aspect_ids => stream.aspect_ids, :for_all_aspects => stream.for_all_aspects?, :aspect => stream.aspect = render 'aspects/no_posts_message' - if current_user.contacts.size < 2 = render 'aspects/no_contacts_message' -#main_stream.stream{:data => {:guids => aspect_ids.join(',')}} - - if posts.length > 0 - = render 'shared/stream', :posts => posts +#main_stream.stream{:data => {:guids => stream.aspect_ids.join(',')}} + - if stream.posts.length > 0 + = render 'shared/stream', :posts => stream.posts #pagination =link_to(t('more'), next_page_path, :class => 'paginate') diff --git a/app/views/aspects/_selected_contacts.html.haml b/app/views/aspects/_selected_contacts.html.haml index 1d359f362..7ef4e2177 100644 --- a/app/views/aspects/_selected_contacts.html.haml +++ b/app/views/aspects/_selected_contacts.html.haml @@ -1,22 +1,22 @@ #selected_aspect_contacts.section .title.no_icon %h5 - - if all_aspects_selected? || !@aspect || @aspect_ids.size > 1 + - if @stream.for_all_aspects? || @stream.aspect_ids.size > 1 = "#{t('_contacts')}" - else - = @aspect.name - = "(#{count})" + = @stream.aspect.name + = "(#{@stream.people.size})" .content - - if people.size > 0 - - for person in people - = person_image_link person + - if @stream.people.size > 0 + - for person in @stream.people + = person_image_link(person) - - if all_aspects_selected? || @aspect_ids.size > 1 + - if @stream.for_all_aspects? || @stream.aspect_ids.size > 1 = link_to t('.view_all_contacts'), contacts_link, :id => "view_all_contacts_link" - else - = link_to t('.view_all_contacts'), contacts_path(:a_id => @aspect.id), :id => "view_all_contacts_link" + = link_to t('.view_all_contacts'), contacts_path(:a_id => @stream.aspect.id), :id => "view_all_contacts_link" - else = t('.no_contacts') diff --git a/app/views/aspects/index.html.haml b/app/views/aspects/index.html.haml index f0e93b1e7..a7c6be02e 100644 --- a/app/views/aspects/index.html.haml +++ b/app/views/aspects/index.html.haml @@ -26,12 +26,9 @@ .span-13.append-1 #aspect_stream_container.stream_container - = render 'aspect_stream', - :aspect => @aspect, - :aspect_ids => @aspect_ids, - :posts => @posts + = render 'aspect_stream', :stream => @stream .span-5.rightBar.last - = render 'selected_contacts', :people => selected_people(@aspect_ids).sample(20), :count => @contact_count + = render 'selected_contacts', :stream => @stream = render 'shared/right_sections' diff --git a/app/views/aspects/index.js.erb b/app/views/aspects/index.js.erb index acf2b8961..b030d7e46 100644 --- a/app/views/aspects/index.js.erb +++ b/app/views/aspects/index.js.erb @@ -1,3 +1,3 @@ -$('#aspect_stream_container').html("<%= escape_javascript(render('aspects/aspect_stream', :aspect => @aspect, :aspect_ids => @aspect_ids, :posts => @posts)) %>"); -$('#selected_aspect_contacts').html("<%= escape_javascript(render('aspects/selected_contacts', :people => @selected_people.sample(20), :count => @contact_count )) %>"); +$('#aspect_stream_container').html("<%= escape_javascript(render('aspects/aspect_stream', :stream => @stream)) %>"); +$('#selected_aspect_contacts').html("<%= escape_javascript(render('aspects/selected_contacts', :people => @stream.people.sample(20), :count => @stream.people.size)) %>"); $('#aspect_stream_container a[rel*=facebox]').facebox(); diff --git a/app/views/aspects/index.mobile.haml b/app/views/aspects/index.mobile.haml index e7e22f20a..f56a9e2a1 100644 --- a/app/views/aspects/index.mobile.haml +++ b/app/views/aspects/index.mobile.haml @@ -3,18 +3,18 @@ -# the COPYRIGHT file. #aspect_header - - if @aspect == :all + - if @stream.for_all_aspects? = t('all_aspects') - else - = @aspect + = @stream.aspect = link_to t('.post_a_message'), '#publisher_page', :id => 'publisher_button' #main_stream.stream - = render 'shared/stream', :posts => @posts - -if @posts.length > 0 + = render 'shared/stream', :posts => @stream.posts + -if @stream.posts.length > 0 #pagination %a.more-link.paginate{:href => next_page_path} %h2= t("more") - content_for :subpages do - = render 'shared/publisher', :aspect_ids => @aspect_ids, :selected_aspects => @aspects, :aspect => @aspect + = render 'shared/publisher', :aspect_ids => @stream.aspect_ids, :selected_aspects => @stream.aspects, :aspect => @stream.aspect diff --git a/app/views/shared/_publisher.html.haml b/app/views/shared/_publisher.html.haml index 3b534281a..ec988f72e 100644 --- a/app/views/shared/_publisher.html.haml +++ b/app/views/shared/_publisher.html.haml @@ -32,7 +32,7 @@ .public_toggle %span#publisher_service_icons = t("shared.publisher.click_to_share_with") - - if aspect == :all || aspect == :profile + - if((defined?(for_all_aspects) && for_all_aspects) || aspect == :profile) = status.hidden_field(:public) = image_tag "icons/globe.png", :title => t('javascripts.publisher.limited'), :class => 'public_icon dim', :width => 16, :height => 16 - if current_user.services diff --git a/app/views/shared/_publisher.mobile.haml b/app/views/shared/_publisher.mobile.haml index 446846282..2f37726b8 100644 --- a/app/views/shared/_publisher.mobile.haml +++ b/app/views/shared/_publisher.mobile.haml @@ -25,12 +25,12 @@ = status.text_area :text - - for aspect_id in @aspect_ids + - for aspect_id in aspect_ids = hidden_field_tag 'aspect_ids[]', aspect_id.to_s %fieldset - - unless params[:a_ids] + - unless aspect_ids %input{:type => 'checkbox', :name => 'status_message[public]', :id => 'public', :class => 'custom', :value => 'true'} %label{:for => 'public'} = t('.make_public') diff --git a/lib/aspect_stream.rb b/lib/aspect_stream.rb new file mode 100644 index 000000000..f90fde6fe --- /dev/null +++ b/lib/aspect_stream.rb @@ -0,0 +1,59 @@ +# Copyright (c) 2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +class AspectStream + + attr_reader :aspects, :aspect_ids, :max_time, :order + + # @param user [User] + # @param aspect_ids [Array] Aspects this stream is responsible for + def initialize(user, aspect_ids, opts={}) + @user = user + @aspects = user.aspects + @aspects = @aspects.where(:id => aspect_ids) if aspect_ids.present? + @aspect_ids = self.aspect_ids + + # ugly hack for now + @max_time = opts[:max_time].to_i + @order = opts[:order] + end + + # @return [Array] + def aspect_ids + @aspect_ids ||= @aspects.map { |a| a.id } + end + + # @return [ActiveRecord::Association] AR association of posts + def posts + @posts ||= @user.visible_posts(:by_members_of => @aspect_ids, + :type => ['StatusMessage','Reshare', 'ActivityStreams::Photo'], + :order => @order + ' DESC', + :max_time => @max_time + ).includes(:mentions => {:person => :profile}, :author => :profile) + end + + # @return [ActiveRecord::Association] AR association of people within stream's given aspects + def people + @people ||= Person.joins(:contacts => :aspect_memberships). + where(:contacts => {:user_id => @user.id}, + :aspect_memberships => {:aspect_id => @aspect_ids}). + select("DISTINCT people.*").includes(:profile) + end + + # @note aspects.first is used for mobile. + # The :all is currently used for view switching logic + # @return [Aspect,Symbol] + def aspect + for_all_aspects? ? :all : @aspects.first + end + + # Determine whether or not the stream is displaying across + # all of the user's aspects. + # + # @return [Boolean] + def for_all_aspects? + @aspect_ids.length == @aspects.length + end + +end diff --git a/spec/controllers/aspects_controller_spec.rb b/spec/controllers/aspects_controller_spec.rb index 2edd48b90..61fa9a19b 100644 --- a/spec/controllers/aspects_controller_spec.rb +++ b/spec/controllers/aspects_controller_spec.rb @@ -66,61 +66,63 @@ describe AspectsController do end describe "#index" do - it "generates a jasmine fixture", :fixture => true do - get :index - save_fixture(html_for("body"), "aspects_index") - end + context 'jasmine fixtures' do + it "generates a jasmine fixture", :fixture => true do + get :index + save_fixture(html_for("body"), "aspects_index") + end - it "generates a jasmine fixture with a prefill", :fixture => true do - get :index, :prefill => "reshare things" - save_fixture(html_for("body"), "aspects_index_prefill") - end + it "generates a jasmine fixture with a prefill", :fixture => true do + get :index, :prefill => "reshare things" + save_fixture(html_for("body"), "aspects_index_prefill") + end - it 'generates a jasmine fixture with services', :fixture => true do - alice.services << Services::Facebook.create(:user_id => alice.id) - alice.services << Services::Twitter.create(:user_id => alice.id) - get :index, :prefill => "reshare things" - save_fixture(html_for("body"), "aspects_index_services") - end + it 'generates a jasmine fixture with services', :fixture => true do + alice.services << Services::Facebook.create(:user_id => alice.id) + alice.services << Services::Twitter.create(:user_id => alice.id) + get :index, :prefill => "reshare things" + save_fixture(html_for("body"), "aspects_index_services") + end - it 'generates a jasmine fixture with posts', :fixture => true do - bob.post(:status_message, :text => "Is anyone out there?", :to => @bob.aspects.where(:name => "generic").first.id) - message = alice.post(:status_message, :text => "hello "*800, :to => @alices_aspect_2.id) - 5.times { bob.comment("what", :post => message) } - get :index - save_fixture(html_for("body"), "aspects_index_with_posts") - end + it 'generates a jasmine fixture with posts', :fixture => true do + bob.post(:status_message, :text => "Is anyone out there?", :to => @bob.aspects.where(:name => "generic").first.id) + message = alice.post(:status_message, :text => "hello "*800, :to => @alices_aspect_2.id) + 5.times { bob.comment("what", :post => message) } + get :index + save_fixture(html_for("body"), "aspects_index_with_posts") + end - it "generates a jasmine fixture with a post with comments", :fixture => true do - message = bob.post(:status_message, :text => "HALO WHIRLED", :to => @bob.aspects.where(:name => "generic").first.id) - 5.times { bob.comment("what", :post => message) } - get :index - save_fixture(html_for("body"), "aspects_index_post_with_comments") - end + it "generates a jasmine fixture with a post with comments", :fixture => true do + message = bob.post(:status_message, :text => "HALO WHIRLED", :to => @bob.aspects.where(:name => "generic").first.id) + 5.times { bob.comment("what", :post => message) } + get :index + save_fixture(html_for("body"), "aspects_index_post_with_comments") + end - it 'generates a jasmine fixture with a followed tag', :fixture => true do - @tag = ActsAsTaggableOn::Tag.create!(:name => "partytimeexcellent") - TagFollowing.create!(:tag => @tag, :user => alice) - get :index - save_fixture(html_for("body"), "aspects_index_with_one_followed_tag") - end + it 'generates a jasmine fixture with a followed tag', :fixture => true do + @tag = ActsAsTaggableOn::Tag.create!(:name => "partytimeexcellent") + TagFollowing.create!(:tag => @tag, :user => alice) + get :index + save_fixture(html_for("body"), "aspects_index_with_one_followed_tag") + end - it "generates a jasmine fixture with a post containing a video", :fixture => true do - stub_request(:get, "http://gdata.youtube.com/feeds/api/videos/UYrkQL1bX4A?v=2"). - with(:headers => {'Accept'=>'*/*'}). - to_return(:status => 200, :body => "LazyTown song - Cooking By The Book", :headers => {}) - alice.post(:status_message, :text => "http://www.youtube.com/watch?v=UYrkQL1bX4A", :to => @alices_aspect_2.id) - get :index - save_fixture(html_for("body"), "aspects_index_with_video_post") - end + it "generates a jasmine fixture with a post containing a video", :fixture => true do + stub_request(:get, "http://gdata.youtube.com/feeds/api/videos/UYrkQL1bX4A?v=2"). + with(:headers => {'Accept'=>'*/*'}). + to_return(:status => 200, :body => "LazyTown song - Cooking By The Book", :headers => {}) + alice.post(:status_message, :text => "http://www.youtube.com/watch?v=UYrkQL1bX4A", :to => @alices_aspect_2.id) + get :index + save_fixture(html_for("body"), "aspects_index_with_video_post") + end - it "generates a jasmine fixture with a post that has been liked", :fixture => true do - message = alice.post(:status_message, :text => "hello "*800, :to => @alices_aspect_2.id) - alice.build_like(:positive => true, :target => message).save - bob.build_like(:positive => true, :target => message).save + it "generates a jasmine fixture with a post that has been liked", :fixture => true do + message = alice.post(:status_message, :text => "hello "*800, :to => @alices_aspect_2.id) + alice.build_like(:positive => true, :target => message).save + bob.build_like(:positive => true, :target => message).save - get :index - save_fixture(html_for("body"), "aspects_index_with_a_post_with_likes") + get :index + save_fixture(html_for("body"), "aspects_index_with_a_post_with_likes") + end end context "mobile" do @@ -135,25 +137,9 @@ describe AspectsController do end end - context 'with getting_started = true' do - before do - alice.getting_started = true - alice.save - end - - it 'does not redirect mobile users to getting_started' do - get :index, :format => :mobile - response.should_not be_redirect - end - - it 'does not redirect ajax to getting_started' do - get :index, :format => :js - response.should_not be_redirect - end - end - context 'with posts in multiple aspects' do before do + pending 'this spec needs to be moved into AspectStream spec' @posts = [] 2.times do |n| user = Factory(:user) @@ -179,6 +165,7 @@ describe AspectsController do get :index assigns[:posts].include?(@status).should be_true end + it "does not pull back hidden posts" do @vis.update_attributes(:hidden => true) get :index