Merge branch 'tag_stream_refactor'
This commit is contained in:
commit
6653896b31
32 changed files with 501 additions and 158 deletions
|
|
@ -137,4 +137,21 @@ class ApplicationController < ActionController::Base
|
|||
@tags ||= current_user.followed_tags
|
||||
end
|
||||
|
||||
def save_sort_order
|
||||
if params[:sort_order].present?
|
||||
session[:sort_order] = (params[:sort_order] == 'created_at') ? 'created_at' : 'updated_at'
|
||||
elsif session[:sort_order].blank?
|
||||
session[:sort_order] = 'updated_at'
|
||||
else
|
||||
session[:sort_order] = (session[:sort_order] == 'created_at') ? 'created_at' : 'updated_at'
|
||||
end
|
||||
end
|
||||
|
||||
def sort_order
|
||||
is_mobile_device? ? 'created_at' : session[:sort_order]
|
||||
end
|
||||
|
||||
def max_time
|
||||
params[:max_time] ? Time.at(params[:max_time].to_i) : Time.now
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
class AppsController < ApplicationController
|
||||
def show
|
||||
@app = 'cubbies'
|
||||
@posts = ActivityStreams::Photo
|
||||
max_time = params[:max_time] ? Time.at(params[:max_time].to_i) : Time.now
|
||||
@posts = @posts.where(ActivityStreams::Photo.arel_table[:created_at].lt(max_time)
|
||||
).where(:public => true
|
||||
).order('posts.created_at DESC'
|
||||
).includes(:author => :profile).limit(30)
|
||||
@posts = ActivityStreams::Photo.where(:public => true).for_a_stream(max_time, 'created_at')
|
||||
@commenting_disabled = true
|
||||
@people = []
|
||||
@people_count = 0
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
require File.join(Rails.root, "lib", "aspect_stream")
|
||||
require File.join(Rails.root, "lib", 'stream', "aspect_stream")
|
||||
|
||||
class AspectsController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
|
|
@ -138,18 +138,4 @@ class AspectsController < ApplicationController
|
|||
end
|
||||
|
||||
private
|
||||
def save_sort_order
|
||||
if params[:sort_order].present?
|
||||
session[:sort_order] = (params[:sort_order] == 'created_at') ? 'created_at' : 'updated_at'
|
||||
elsif session[:sort_order].blank?
|
||||
session[:sort_order] = 'created_at'
|
||||
else
|
||||
session[:sort_order] = (session[:sort_order] == 'created_at') ? 'created_at' : 'updated_at'
|
||||
end
|
||||
end
|
||||
|
||||
def sort_order
|
||||
is_mobile_device? ? 'created_at' : session[:sort_order]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
20
app/controllers/mentions_controller.rb
Normal file
20
app/controllers/mentions_controller.rb
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
require File.join(Rails.root, 'lib','stream', 'mention_stream')
|
||||
|
||||
class MentionsController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
before_filter :save_sort_order, :only => :index
|
||||
|
||||
def index
|
||||
@stream = MentionStream.new(current_user, :max_time => params[:max_time], :order => sort_order)
|
||||
|
||||
if params[:only_posts]
|
||||
render :partial => 'shared/stream', :locals => {:posts => @stream.posts}
|
||||
else
|
||||
render 'aspects/index'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,12 +1,23 @@
|
|||
require File.join(Rails.root, '/lib/tag_stream')
|
||||
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
#
|
||||
require File.join(Rails.root, 'lib', 'stream', 'tag_stream')
|
||||
|
||||
class TagFollowingsController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
before_filter :save_sort_order, :only => :index
|
||||
|
||||
def index
|
||||
@stream = TagStream.new(current_user)
|
||||
@stream = TagStream.new(current_user, :max_time => params[:max_time], :order => sort_order)
|
||||
|
||||
render 'aspects/index', :locals => {:posts => @stream.posts}
|
||||
if params[:only_posts]
|
||||
render :partial => 'shared/stream', :locals => {:posts => @stream.posts}
|
||||
else
|
||||
render 'aspects/index'
|
||||
end
|
||||
end
|
||||
|
||||
# POST /tag_followings
|
||||
# POST /tag_followings.xml
|
||||
def create
|
||||
|
|
|
|||
|
|
@ -47,27 +47,17 @@ class TagsController < ApplicationController
|
|||
def show
|
||||
params[:name].downcase!
|
||||
@aspect = :tag
|
||||
|
||||
if current_user
|
||||
@posts = StatusMessage.
|
||||
joins("LEFT OUTER JOIN post_visibilities ON post_visibilities.post_id = posts.id").
|
||||
joins("LEFT OUTER JOIN contacts ON contacts.id = post_visibilities.contact_id").
|
||||
where(Contact.arel_table[:user_id].eq(current_user.id).or(
|
||||
StatusMessage.arel_table[:public].eq(true).or(
|
||||
StatusMessage.arel_table[:author_id].eq(current_user.person.id)
|
||||
)
|
||||
)).select('DISTINCT posts.*')
|
||||
@posts = StatusMessage.owned_or_visible_by_user(current_user)
|
||||
else
|
||||
@posts = StatusMessage.all_public
|
||||
end
|
||||
|
||||
params[:prefill] = "##{params[:name]} "
|
||||
@posts = @posts.tagged_with(params[:name])
|
||||
|
||||
max_time = params[:max_time] ? Time.at(params[:max_time].to_i) : Time.now
|
||||
@posts = @posts.where(StatusMessage.arel_table[:created_at].lt(max_time))
|
||||
@posts = @posts.includes({:author => :profile}, :comments, :photos).order('posts.created_at DESC').limit(15)
|
||||
@posts = @posts.tagged_with(params[:name]).for_a_stream(max_time, 'created_at')
|
||||
|
||||
@commenting_disabled = true
|
||||
params[:prefill] = "##{params[:name]} "
|
||||
|
||||
if params[:only_posts]
|
||||
render :partial => 'shared/stream', :locals => {:posts => @posts}
|
||||
|
|
@ -84,4 +74,5 @@ class TagsController < ApplicationController
|
|||
end
|
||||
@tag_followed
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,20 +11,24 @@ module StreamHelper
|
|||
elsif controller.instance_of?(PeopleController)
|
||||
person_path(@person, :max_time => @posts.last.created_at.to_i)
|
||||
elsif controller.instance_of?(TagFollowingsController)
|
||||
tag_followings_path(:max_time => @stream.posts.last.created_at.to_i)
|
||||
tag_followings_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream), :sort_order => session[:sort_order])
|
||||
elsif controller.instance_of?(MentionsController)
|
||||
mentions_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream), :sort_order => session[:sort_order])
|
||||
elsif controller.instance_of?(AspectsController)
|
||||
if opts[:ajax_stream]
|
||||
time = (Time.now() + 1).to_i
|
||||
|
||||
else
|
||||
time = @stream.posts.last.send(@stream.order.to_sym).to_i
|
||||
end
|
||||
aspects_path(:max_time => time, :sort_order => session[:sort_order], :a_ids => @stream.aspect_ids)
|
||||
aspects_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream), :a_ids => @stream.aspect_ids, :sort_order => session[:sort_order])
|
||||
else
|
||||
raise 'in order to use pagination for this new controller, update next_page_path in stream helper'
|
||||
end
|
||||
end
|
||||
|
||||
def time_for_scroll(ajax_stream, stream)
|
||||
if ajax_stream || stream.posts.empty?
|
||||
(Time.now() + 1).to_i
|
||||
else
|
||||
stream.posts.last.send(stream.order.to_sym).to_i
|
||||
end
|
||||
end
|
||||
|
||||
def time_for_sort post
|
||||
if controller.instance_of?(AspectsController)
|
||||
post.send(session[:sort_order].to_sym)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,20 @@ class Post < ActiveRecord::Base
|
|||
|
||||
validates :guid, :uniqueness => true
|
||||
|
||||
#scopes
|
||||
scope :all_public, where(:public => true, :pending => false)
|
||||
scope :includes_for_a_stream, includes({:author => :profile}, :mentions => {:person => :profile}) #note should include root and photos, but i think those are both on status_message
|
||||
|
||||
def self.for_a_stream(max_time, order)
|
||||
by_max_time(max_time, order).
|
||||
includes_for_a_stream.
|
||||
limit(15)
|
||||
end
|
||||
|
||||
def self.by_max_time(max_time, order='created_at')
|
||||
where("posts.#{order} < ?", max_time).order("posts.#{order} desc")
|
||||
end
|
||||
#############
|
||||
|
||||
def diaspora_handle
|
||||
read_attribute(:diaspora_handle) || self.author.diaspora_handle
|
||||
|
|
@ -140,4 +153,3 @@ class Post < ActiveRecord::Base
|
|||
update_all(:comments_count => self.comments.count)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,19 @@ class StatusMessage < Post
|
|||
|
||||
after_create :create_mentions
|
||||
|
||||
#scopes
|
||||
scope :where_person_is_mentioned, lambda{|person| joins(:mentions).where(:mentions => {:person_id => person.id})}
|
||||
|
||||
def self.owned_or_visible_by_user(user)
|
||||
joins("LEFT OUTER JOIN post_visibilities ON post_visibilities.post_id = posts.id").
|
||||
joins("LEFT OUTER JOIN contacts ON contacts.id = post_visibilities.contact_id").
|
||||
where(Contact.arel_table[:user_id].eq(user.id).or(
|
||||
StatusMessage.arel_table[:public].eq(true).or(
|
||||
StatusMessage.arel_table[:author_id].eq(user.person.id)
|
||||
)
|
||||
)).select('DISTINCT posts.*')
|
||||
end
|
||||
|
||||
def text(opts = {})
|
||||
self.formatted_message(opts)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,15 +6,12 @@
|
|||
#sort_by
|
||||
= t('.recently')
|
||||
%span.controls
|
||||
= link_to_if(session[:sort_order] == 'updated_at', t('.posted'), aspects_path(:a_ids => stream.aspect_ids, :sort_order => 'created_at' ))
|
||||
= link_to_if(session[:sort_order] == 'created_at', t('.commented_on'), stream.link(: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'), stream.link(:sort_order => 'created_at' ))
|
||||
|
||||
%h3
|
||||
- if stream.for_all_aspects?
|
||||
= t('.stream')
|
||||
- else
|
||||
= stream.aspects.to_sentence
|
||||
= stream.title
|
||||
|
||||
= 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'
|
||||
|
|
@ -23,11 +20,7 @@
|
|||
= render 'aspects/no_contacts_message'
|
||||
|
||||
#main_stream.stream{:data => {:guids => stream.aspect_ids.join(',')}}
|
||||
- if stream.ajax_stream?
|
||||
#pagination
|
||||
=link_to(t('more'), next_page_path(:ajax_stream => true), :class => 'paginate')
|
||||
|
||||
- elsif stream.posts.length > 0
|
||||
- if !stream.ajax_stream? && stream.posts.length > 0
|
||||
= render 'shared/stream', :posts => stream.posts
|
||||
#pagination
|
||||
=link_to(t('more'), next_page_path, :class => 'paginate')
|
||||
#pagination
|
||||
=link_to(t('more'), next_page_path(:ajax_stream => stream.ajax_stream?), :class => 'paginate')
|
||||
|
|
|
|||
|
|
@ -1,23 +1,13 @@
|
|||
#selected_aspect_contacts.section
|
||||
.title.no_icon
|
||||
%h5
|
||||
- if @stream.for_all_aspects? || @stream.aspect_ids.size > 1
|
||||
= "#{t('_contacts')}"
|
||||
- else
|
||||
= @stream.aspect.name
|
||||
= "(#{@stream.people.size})"
|
||||
|
||||
= @stream.contacts_title
|
||||
|
||||
.content
|
||||
- if @stream.people.size > 0
|
||||
- for person in @stream.people.sample(15)
|
||||
= person_image_link(person)
|
||||
|
||||
- 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 => @stream.aspect.id), :id => "view_all_contacts_link"
|
||||
|
||||
= link_to t('.view_all_contacts'), @stream.contacts_link, :id => "view_all_contacts_link"
|
||||
- else
|
||||
= t('.no_contacts')
|
||||
= link_to t('.manage_your_aspects'), contacts_link
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@
|
|||
.section
|
||||
= render 'aspects/aspect_listings'
|
||||
|
||||
.section
|
||||
%ul.left_nav
|
||||
.li
|
||||
%b= link_to t('.mentions'), mentions_path, :class => 'home_selector'
|
||||
|
||||
.section#followed_tags_listing
|
||||
= render 'tags/followed_tags_listings'
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@
|
|||
- if user_signed_in?
|
||||
%ul.left_nav
|
||||
%li
|
||||
%div.root_element
|
||||
= t('aspects.index.tags_following')
|
||||
%b=link_to t('aspects.index.tags_following'), tag_followings_path, :class => 'home_selector'
|
||||
|
||||
%ul.sub_nav
|
||||
- if tags.size > 0
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ Diaspora::Application.configure do
|
|||
config.action_mailer.raise_delivery_errors = false
|
||||
config.active_support.deprecation = :log
|
||||
#config.threadsafe!
|
||||
|
||||
# Monkeypatch around the nasty "2.5MB exception page" issue, caused by very large environment vars
|
||||
# This snippet via: http://stackoverflow.com/questions/3114993/exception-pages-in-development-mode-take-upwards-of-15-30-seconds-to-render-why
|
||||
# Relevant Rails ticket: https://rails.lighthouseapp.com/projects/8994/tickets/5027-_request_and_responseerb-and-diagnosticserb-take-an-increasingly-long-time-to-render-in-development-with-multiple-show-tables-calls
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ en:
|
|||
done_editing: "done editing"
|
||||
aspect_stream:
|
||||
stream: "Stream"
|
||||
mentions: "Mentions"
|
||||
recently: "recently:"
|
||||
commented_on: "commented on"
|
||||
posted: "posted"
|
||||
|
|
@ -155,6 +156,7 @@ en:
|
|||
acquaintances: "Acquaintances"
|
||||
friends: "Friends"
|
||||
index:
|
||||
mentions: "Mentions"
|
||||
donate: "Donate"
|
||||
keep_us_running: "Keep %{pod} running fast and buy servers their coffee fix with a monthly donation!"
|
||||
your_aspects: "Your Aspects"
|
||||
|
|
@ -824,7 +826,15 @@ en:
|
|||
index:
|
||||
revoke_access: "Revoke Access"
|
||||
no_applications: "You haven't registered any applications yet."
|
||||
|
||||
|
||||
streams:
|
||||
mentions:
|
||||
title: "Your Mentions"
|
||||
contacts_title: "People who mentioned you"
|
||||
tags:
|
||||
title: "Posts tagged: %{tags}"
|
||||
contacts_title: "People who dig these tags"
|
||||
|
||||
|
||||
users:
|
||||
logged_out:
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ Diaspora::Application.routes.draw do
|
|||
end
|
||||
|
||||
|
||||
# get "tag_followings" => "tag_followings#index", :as => 'tag_followings'
|
||||
get "tag_followings" => "tag_followings#index", :as => 'tag_followings'
|
||||
resources :mentions, :only => [:index]
|
||||
|
||||
get 'tags/:name' => 'tags#show', :as => 'tag'
|
||||
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ And /^I scroll down$/ do
|
|||
evaluate_script("window.scrollBy(0,3000000)")
|
||||
sleep 1
|
||||
wait_until(30) { evaluate_script('$("#infscr-loading:visible").length') == 0 }
|
||||
And "I wait for the ajax to finish"
|
||||
end
|
||||
|
||||
Then /^the notification dropdown should be visible$/ do
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ When /^I sign in as "([^"]*)"$/ do |email|
|
|||
@me = User.find_by_email(email)
|
||||
@me.password ||= 'password'
|
||||
Given 'I am signed in'
|
||||
And 'I wait for the ajax to finish'
|
||||
end
|
||||
|
||||
When /^I sign in with password "([^"]*)"$/ do |password|
|
||||
|
|
|
|||
70
lib/base_stream.rb
Normal file
70
lib/base_stream.rb
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
class BaseStream
|
||||
attr_accessor :max_time, :order, :user
|
||||
|
||||
def initialize(user, opts={})
|
||||
self.user = user
|
||||
self.max_time = opts[:max_time]
|
||||
self.order = opts[:order]
|
||||
end
|
||||
|
||||
|
||||
|
||||
#requied to implement said stream
|
||||
def link(opts={})
|
||||
Rails.application.routes.url_helpers.mentions_path(opts)
|
||||
end
|
||||
|
||||
def title
|
||||
'a title'
|
||||
end
|
||||
|
||||
def posts
|
||||
[]
|
||||
end
|
||||
|
||||
def people
|
||||
[]
|
||||
end
|
||||
|
||||
def contacts_title
|
||||
"title for a stream"
|
||||
end
|
||||
|
||||
def contacts_link
|
||||
'#'
|
||||
end
|
||||
|
||||
#helpers
|
||||
def ajax_stream?
|
||||
false
|
||||
end
|
||||
|
||||
def for_all_aspects?
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
#NOTE: MBS bad bad methods the fact we need these means our views are foobared. please kill them and make them
|
||||
#private methods on the streams that need them
|
||||
def aspects
|
||||
@user.aspects
|
||||
end
|
||||
|
||||
def aspect
|
||||
aspects.first
|
||||
end
|
||||
|
||||
def aspect_ids
|
||||
aspects.map{|x| x.id}
|
||||
end
|
||||
|
||||
def max_time=(time_string)
|
||||
@max_time = Time.at(time_string.to_i) unless time_string.blank?
|
||||
@max_time ||= (Time.now + 1)
|
||||
end
|
||||
|
||||
def order=(order_string)
|
||||
@order = order_string
|
||||
@order ||= 'created_at'
|
||||
end
|
||||
end
|
||||
|
|
@ -2,9 +2,8 @@
|
|||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class AspectStream
|
||||
|
||||
attr_reader :max_time, :order
|
||||
class AspectStream < BaseStream
|
||||
TYPES_OF_POST_IN_STREAM = ['StatusMessage', 'Reshare', 'ActivityStreams::Photo']
|
||||
|
||||
# @param user [User]
|
||||
# @param inputted_aspect_ids [Array<Integer>] Ids of aspects for given stream
|
||||
|
|
@ -13,10 +12,8 @@ class AspectStream
|
|||
# @opt order [String] Order of posts (i.e. 'created_at', 'updated_at')
|
||||
# @return [void]
|
||||
def initialize(user, inputted_aspect_ids, opts={})
|
||||
@user = user
|
||||
super(user, opts)
|
||||
@inputted_aspect_ids = inputted_aspect_ids
|
||||
@max_time = opts[:max_time]
|
||||
@order = opts[:order]
|
||||
end
|
||||
|
||||
# Filters aspects given the stream's aspect ids on initialization and the user.
|
||||
|
|
@ -26,7 +23,7 @@ class AspectStream
|
|||
# @return [ActiveRecord::Association<Aspect>] Filtered aspects given the stream's user
|
||||
def aspects
|
||||
@aspects ||= lambda do
|
||||
a = @user.aspects
|
||||
a = user.aspects
|
||||
a = a.where(:id => @inputted_aspect_ids) if @inputted_aspect_ids.length > 0
|
||||
a
|
||||
end.call
|
||||
|
|
@ -42,16 +39,20 @@ class AspectStream
|
|||
# @return [ActiveRecord::Association<Post>] AR association of posts
|
||||
def posts
|
||||
# NOTE(this should be something like Post.all_for_stream(@user, aspect_ids, {}) that calls visible_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)
|
||||
@posts ||= user.visible_posts(:by_members_of => aspect_ids,
|
||||
:type => TYPES_OF_POST_IN_STREAM,
|
||||
:order => "#{order} DESC",
|
||||
:max_time => max_time
|
||||
).for_a_stream(max_time, order)
|
||||
end
|
||||
|
||||
# @return [ActiveRecord::Association<Person>] AR association of people within stream's given aspects
|
||||
def people
|
||||
@people ||= Person.all_from_aspects(aspect_ids, @user).includes(:profile)
|
||||
@people ||= Person.all_from_aspects(aspect_ids, user).includes(:profile)
|
||||
end
|
||||
|
||||
def link(opts={})
|
||||
Rails.application.routes.url_helpers.aspects_path(opts.merge(:a_ids => aspect_ids))
|
||||
end
|
||||
|
||||
# The first aspect in #aspects, given the stream is not for all aspects, or #aspects size is 1
|
||||
|
|
@ -67,11 +68,35 @@ class AspectStream
|
|||
for_all_aspects?
|
||||
end
|
||||
|
||||
def title
|
||||
if self.for_all_aspects?
|
||||
I18n.t('aspects.aspect_stream.stream')
|
||||
else
|
||||
self.aspects.to_sentence
|
||||
end
|
||||
end
|
||||
|
||||
# Determine whether or not the stream is displaying across
|
||||
# all of the user's aspects.
|
||||
#
|
||||
# @return [Boolean]
|
||||
def for_all_aspects?
|
||||
@all_aspects ||= aspect_ids.length == @user.aspects.size
|
||||
@all_aspects ||= aspect_ids.length == user.aspects.size
|
||||
end
|
||||
|
||||
def contacts_title
|
||||
if self.for_all_aspects? || self.aspect_ids.size > 1
|
||||
I18n.t('_contacts')
|
||||
else
|
||||
"#{self.aspect.name}(#{self.people.size})"
|
||||
end
|
||||
end
|
||||
|
||||
def contacts_link
|
||||
if for_all_aspects? || aspect_ids.size > 1
|
||||
Rails.application.routes.url_helpers.contacts_path
|
||||
else
|
||||
Rails.application.routes.url_helpers.contacts_path(:a_id => aspect.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
28
lib/stream/mention_stream.rb
Normal file
28
lib/stream/mention_stream.rb
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class MentionStream< BaseStream
|
||||
def link(opts={})
|
||||
Rails.application.routes.url_helpers.mentions_path(opts)
|
||||
end
|
||||
|
||||
def title
|
||||
I18n.translate("streams.mentions.title")
|
||||
end
|
||||
|
||||
|
||||
# @return [ActiveRecord::Association<Post>] AR association of posts
|
||||
def posts
|
||||
@posts ||= StatusMessage.where_person_is_mentioned(self.user.person).for_a_stream(max_time, order)
|
||||
end
|
||||
|
||||
# @return [ActiveRecord::Association<Person>] AR association of people within stream's given aspects
|
||||
def people
|
||||
@people ||= posts.map{|p| p.author}.uniq
|
||||
end
|
||||
|
||||
def contacts_title
|
||||
I18n.translate('streams.mentions.contacts_title')
|
||||
end
|
||||
end
|
||||
49
lib/stream/tag_stream.rb
Normal file
49
lib/stream/tag_stream.rb
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class TagStream < BaseStream
|
||||
|
||||
def link(opts={})
|
||||
Rails.application.routes.url_helpers.tag_followings_path(opts)
|
||||
end
|
||||
|
||||
def title
|
||||
tags_titleized
|
||||
end
|
||||
|
||||
# @return [ActiveRecord::Association<Post>] AR association of posts
|
||||
def posts
|
||||
if tag_string.empty?
|
||||
[]
|
||||
else
|
||||
@posts ||= StatusMessage.owned_or_visible_by_user(user).
|
||||
tagged_with([tag_string], :any => true).
|
||||
where(:public => true).
|
||||
for_a_stream(@max_time, @order)
|
||||
end
|
||||
end
|
||||
|
||||
# @return [ActiveRecord::Association<Person>] AR association of people within stream's given aspects
|
||||
def people
|
||||
@people ||= posts.map{|p| p.author}.uniq
|
||||
end
|
||||
|
||||
def contacts_title
|
||||
I18n.translate('streams.tags.contacts_title')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def tag_string
|
||||
@tag_string ||= tags.join(', '){|tag| tag.name}.to_s
|
||||
end
|
||||
|
||||
def tags
|
||||
@tags = user.followed_tags
|
||||
end
|
||||
|
||||
def tags_titleized
|
||||
tag_string.split(',').map{|x| "##{x.strip}"}.to_sentence
|
||||
end
|
||||
end
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
class TagStream
|
||||
|
||||
attr_reader :max_time, :order
|
||||
|
||||
# @param user [User]
|
||||
# @param inputted_aspect_ids [Array<Integer>] Ids of aspects for given stream
|
||||
# @param aspect_ids [Array<Integer>] Aspects this stream is responsible for
|
||||
# @opt max_time [Integer] Unix timestamp of stream's post ceiling
|
||||
# @opt order [String] Order of posts (i.e. 'created_at', 'updated_at')
|
||||
# @return [void]
|
||||
def initialize(user, opts={})
|
||||
@tags = user.followed_tags
|
||||
@tag_string = @tags.join(', '){|tag| tag.name}.to_sym
|
||||
@user = user
|
||||
@max_time = opts[:max_time]
|
||||
@order = opts[:order]
|
||||
end
|
||||
|
||||
# Filters aspects given the stream's aspect ids on initialization and the user.
|
||||
# Will disclude aspects from inputted aspect ids if user is not associated with their
|
||||
# target aspects.
|
||||
#
|
||||
# @return [ActiveRecord::Association<Aspect>] Filtered aspects given the stream's user
|
||||
def aspects
|
||||
[@tag_string]
|
||||
end
|
||||
|
||||
# Maps ids into an array from #aspects
|
||||
#
|
||||
# @return [Array<Integer>] Aspect ids
|
||||
def aspect_ids
|
||||
[]
|
||||
end
|
||||
|
||||
# @return [ActiveRecord::Association<Post>] AR association of posts
|
||||
def posts
|
||||
# NOTE(this should be something like Post.all_for_stream(@user, aspect_ids, {}) that calls visible_posts
|
||||
@posts ||= StatusMessage.tagged_with([@tag_string], :any => true)
|
||||
|
||||
|
||||
end
|
||||
|
||||
# @return [ActiveRecord::Association<Person>] AR association of people within stream's given aspects
|
||||
def people
|
||||
@people ||= posts.map{|p| p.author}.uniq
|
||||
end
|
||||
|
||||
# The first aspect in #aspects, given the stream is not for all aspects, or #aspects size is 1
|
||||
# @note aspects.first is used for mobile. NOTE(this is a hack and should be fixed)
|
||||
# @return [Aspect,Symbol]
|
||||
def aspect
|
||||
@tags_string
|
||||
end
|
||||
|
||||
# Determine whether or not the stream is displaying across
|
||||
# all of the user's aspects.
|
||||
#
|
||||
# @return [Boolean]
|
||||
def for_all_aspects?
|
||||
true
|
||||
end
|
||||
end
|
||||
8
public/javascripts/pages/mentions-index.js
Normal file
8
public/javascripts/pages/mentions-index.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
Diaspora.Pages.MentionsIndex = function() {
|
||||
var self = this;
|
||||
|
||||
this.subscribe("page/ready", function(evt, document) {
|
||||
self.stream = self.instantiate("Stream", document.find("#aspect_stream_container"));
|
||||
self.infiniteScroll = self.instantiate("InfiniteScroll");
|
||||
});
|
||||
};
|
||||
8
public/javascripts/pages/tag-followings-index.js
Normal file
8
public/javascripts/pages/tag-followings-index.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
Diaspora.Pages.TagFollowingsIndex = function() {
|
||||
var self = this;
|
||||
|
||||
this.subscribe("page/ready", function(evt, document) {
|
||||
self.stream = self.instantiate("Stream", document.find("#aspect_stream_container"));
|
||||
self.infiniteScroll = self.instantiate("InfiniteScroll");
|
||||
});
|
||||
};
|
||||
11
spec/lib/base_stream_spec.rb
Normal file
11
spec/lib/base_stream_spec.rb
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
require 'spec_helper'
|
||||
require File.join(Rails.root, 'spec', 'shared_behaviors', 'stream')
|
||||
describe BaseStream do
|
||||
before do
|
||||
@stream = BaseStream.new(stub)
|
||||
end
|
||||
|
||||
describe 'shared behaviors' do
|
||||
it_should_behave_like 'it is a stream'
|
||||
end
|
||||
end
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
require 'aspect_stream'
|
||||
require 'spec_helper'
|
||||
|
||||
describe AspectStream do
|
||||
describe '#aspects' do
|
||||
|
|
@ -70,7 +70,7 @@ describe AspectStream do
|
|||
|
||||
it 'respects max_time' do
|
||||
stream = AspectStream.new(@alice, [1,2], :max_time => 123)
|
||||
@alice.should_receive(:visible_posts).with(hash_including(:max_time => 123)).and_return(stub.as_null_object)
|
||||
@alice.should_receive(:visible_posts).with(hash_including(:max_time => instance_of(Time))).and_return(stub.as_null_object)
|
||||
stream.posts
|
||||
end
|
||||
end
|
||||
|
|
@ -138,4 +138,10 @@ describe AspectStream do
|
|||
@stream.ajax_stream?.should be_false
|
||||
end
|
||||
end
|
||||
describe 'shared behaviors' do
|
||||
before do
|
||||
@stream = AspectStream.new(alice, alice.aspects.map(&:id))
|
||||
end
|
||||
it_should_behave_like 'it is a stream'
|
||||
end
|
||||
end
|
||||
12
spec/lib/stream/mention_stream_spec.rb
Normal file
12
spec/lib/stream/mention_stream_spec.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
require 'spec_helper'
|
||||
require File.join(Rails.root, 'spec', 'shared_behaviors', 'stream')
|
||||
|
||||
describe MentionStream do
|
||||
before do
|
||||
@stream = MentionStream.new(Factory(:user), :max_time => Time.now, :order => 'updated_at')
|
||||
end
|
||||
|
||||
describe 'shared behaviors' do
|
||||
it_should_behave_like 'it is a stream'
|
||||
end
|
||||
end
|
||||
12
spec/lib/stream/tag_stream_spec.rb
Normal file
12
spec/lib/stream/tag_stream_spec.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
require 'spec_helper'
|
||||
require File.join(Rails.root, 'spec', 'shared_behaviors', 'stream')
|
||||
|
||||
describe TagStream do
|
||||
before do
|
||||
@stream = TagStream.new(Factory(:user), :max_time => Time.now, :order => 'updated_at')
|
||||
end
|
||||
|
||||
describe 'shared behaviors' do
|
||||
it_should_behave_like 'it is a stream'
|
||||
end
|
||||
end
|
||||
|
|
@ -10,6 +10,47 @@ describe Post do
|
|||
@aspect = @user.aspects.create(:name => "winners")
|
||||
end
|
||||
|
||||
describe 'scopes' do
|
||||
describe '.for_a_stream' do
|
||||
before do
|
||||
time_interval = 1000
|
||||
time_past = 1000000
|
||||
@posts = (1..3).map do |n|
|
||||
aspect_to_post = alice.aspects.where(:name => "generic").first
|
||||
post = alice.post :status_message, :text => "#{alice.username} - #{n}", :to => aspect_to_post.id
|
||||
post.created_at = (post.created_at-time_past) - time_interval
|
||||
post.updated_at = (post.updated_at-time_past) + time_interval
|
||||
post.save
|
||||
time_interval += 1000
|
||||
post
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the posts ordered and limited by unix time' do
|
||||
Post.for_a_stream(Time.now + 1, "created_at").should == @posts
|
||||
Post.for_a_stream(Time.now + 1, "updated_at").should == @posts.reverse
|
||||
end
|
||||
|
||||
it 'includes everything in .includes_for_a_stream' do
|
||||
Post.should_receive(:includes_for_a_stream)
|
||||
Post.for_a_stream(Time.now + 1, "created_at")
|
||||
end
|
||||
it 'is limited to 15 posts' do
|
||||
Post.stub(:by_max_time).and_return(Post)
|
||||
Post.stub(:includes_for_a_stream).and_return(Post)
|
||||
Post.should_receive(:limit)
|
||||
Post.for_a_stream(Time.now + 1, "created_at")
|
||||
end
|
||||
end
|
||||
|
||||
describe 'includes for a stream' do
|
||||
it 'inclues author profile and mentions'
|
||||
it 'should include photos and root of reshares(but does not)'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
describe 'validations' do
|
||||
it 'validates uniqueness of guid and does not throw a db error' do
|
||||
message = Factory(:status_message)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,51 @@ describe StatusMessage do
|
|||
@aspect = @user.aspects.first
|
||||
end
|
||||
|
||||
describe 'scopes' do
|
||||
describe '.where_person_is_mentioned' do
|
||||
it 'returns status messages where the given person is mentioned' do
|
||||
@bo = bob.person
|
||||
@test_string = "@{Daniel; #{@bo.diaspora_handle}} can mention people like Raph"
|
||||
|
||||
Factory.create(:status_message, :text => @test_string )
|
||||
Factory.create(:status_message, :text => @test_string )
|
||||
Factory(:status_message)
|
||||
|
||||
StatusMessage.where_person_is_mentioned(@bo).count.should == 2
|
||||
end
|
||||
end
|
||||
|
||||
describe '.owned_or_visible_by_user' do
|
||||
before do
|
||||
@you = bob
|
||||
@public_post = Factory(:status_message, :public => true)
|
||||
@your_post = Factory(:status_message, :author => @you.person)
|
||||
@post_from_contact = eve.post(:status_message, :text => 'wooo', :to => eve.aspects.where(:name => 'generic').first)
|
||||
@post_from_stranger = Factory(:status_message, :public => false)
|
||||
end
|
||||
|
||||
it 'returns post from your contacts' do
|
||||
StatusMessage.owned_or_visible_by_user(@you).should include(@post_from_contact)
|
||||
end
|
||||
|
||||
it 'returns your posts' do
|
||||
StatusMessage.owned_or_visible_by_user(@you).should include(@your_post)
|
||||
end
|
||||
|
||||
it 'returns public posts' do
|
||||
StatusMessage.owned_or_visible_by_user(@you).should include(@public_post)
|
||||
end
|
||||
|
||||
it 'does not return non contacts, non-public post' do
|
||||
StatusMessage.owned_or_visible_by_user(@you).should_not include(@post_from_stranger)
|
||||
end
|
||||
|
||||
it 'should return the three visible posts' do
|
||||
StatusMessage.owned_or_visible_by_user(@you).count.should == 3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.before_create' do
|
||||
it 'calls build_tags' do
|
||||
status = Factory.build(:status_message)
|
||||
|
|
|
|||
45
spec/shared_behaviors/stream.rb
Normal file
45
spec/shared_behaviors/stream.rb
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'Streams' do
|
||||
shared_examples_for 'it is a stream' do
|
||||
context 'required methods for display' do
|
||||
it '#title' do
|
||||
@stream.title.should_not be_nil
|
||||
end
|
||||
|
||||
it '#posts' do
|
||||
@stream.posts.should_not be_nil
|
||||
end
|
||||
|
||||
it '#people' do
|
||||
@stream.people.should_not be_nil
|
||||
end
|
||||
|
||||
it 'has a #contacts title' do
|
||||
@stream.contacts_title.should_not be_nil
|
||||
end
|
||||
|
||||
it 'has a contacts link' do
|
||||
@stream.contacts_link.should_not be_nil
|
||||
end
|
||||
|
||||
it 'responds to ajax_stream' do
|
||||
@stream.ajax_stream?.should_not be_nil
|
||||
end
|
||||
|
||||
it 'responds to ajax_stream' do
|
||||
@stream.ajax_stream?.should_not be_nil
|
||||
end
|
||||
|
||||
it 'should make the stream a time object' do
|
||||
@stream.max_time = 123
|
||||
@stream.max_time.should be_a(Time)
|
||||
end
|
||||
|
||||
it 'should default order to created_at' do
|
||||
@stream.order=nil
|
||||
@stream.order.should == 'created_at'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in a new issue