Commit 75524307b8962414354c692e19a677611fb4852c

Authored by Daniela Feitosa
2 parents 91bf3f94 ba6034cc

Merging AI1826 with master

Conflicts:
	app/models/article.rb
	app/models/profile.rb
	app/models/uploaded_file.rb
	public/javascripts/application.js
	public/stylesheets/application.css
	test/unit/article_test.rb
	test/unit/category_finder_test.rb
	test/unit/enterprise_test.rb
Showing 86 changed files with 1672 additions and 772 deletions   Show diff stats
app/controllers/public/profile_controller.rb
@@ -3,17 +3,15 @@ class ProfileController < PublicController @@ -3,17 +3,15 @@ class ProfileController < PublicController
3 needs_profile 3 needs_profile
4 before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] 4 before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add]
5 before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse] 5 before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse]
6 - before_filter :login_required, :only => [:add, :join, :join_not_logged, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_scraps, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report] 6 + before_filter :login_required, :only => [:add, :join, :join_not_logged, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity]
7 7
8 helper TagsHelper 8 helper TagsHelper
9 9
10 def index 10 def index
11 - @activities = @profile.tracked_actions.paginate(:per_page => 30, :page => params[:page])  
12 - @wall_items = []  
13 - @network_activities = !@profile.is_a?(Person) ? @profile.tracked_notifications.paginate(:per_page => 30, :page => params[:page]) : [] 11 + @network_activities = !@profile.is_a?(Person) ? @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page]) : []
14 if logged_in? && current_person.follows?(@profile) 12 if logged_in? && current_person.follows?(@profile)
15 - @network_activities = @profile.tracked_notifications.paginate(:per_page => 30, :page => params[:page]) if @network_activities.empty?  
16 - @wall_items = @profile.scraps_received.not_replies.paginate(:per_page => 30, :page => params[:page]) 13 + @network_activities = @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page]) if @network_activities.empty?
  14 + @activities = @profile.activities.paginate(:per_page => 15, :page => params[:page])
17 end 15 end
18 @tags = profile.article_tags 16 @tags = profile.article_tags
19 unless profile.display_info_to?(user) 17 unless profile.display_info_to?(user)
@@ -180,22 +178,33 @@ class ProfileController < PublicController @@ -180,22 +178,33 @@ class ProfileController < PublicController
180 @scrap.receiver= receiver 178 @scrap.receiver= receiver
181 @tab_action = params[:tab_action] 179 @tab_action = params[:tab_action]
182 @message = @scrap.save ? _("Message successfully sent.") : _("You can't leave an empty message.") 180 @message = @scrap.save ? _("Message successfully sent.") : _("You can't leave an empty message.")
183 - @scraps = @profile.scraps_received.not_replies.paginate(:per_page => 30, :page => params[:page]) if params[:not_load_scraps].nil?  
184 - render :partial => 'leave_scrap' 181 + activities = @profile.activities.paginate(:per_page => 15, :page => params[:page]) if params[:not_load_scraps].nil?
  182 + render :partial => 'profile_activities_list', :locals => {:activities => activities}
185 end 183 end
186 184
187 - def view_more_scraps  
188 - @scraps = @profile.scraps_received.not_replies.paginate(:per_page => 30, :page => params[:page])  
189 - render :partial => 'profile_scraps', :locals => {:scraps => @scraps} 185 + def leave_comment_on_activity
  186 + @comment = Comment.new(params[:comment])
  187 + @comment.author = user
  188 + @activity = ActionTracker::Record.find(params[:source_id])
  189 + @comment.source_type, @comment.source_id = (@activity.target_type == 'Article' ? ['Article', @activity.target_id] : [@activity.class.to_s, @activity.id])
  190 + @tab_action = params[:tab_action]
  191 + @message = @comment.save ? _("Comment successfully added.") : _("You can't leave an empty comment.")
  192 + if @tab_action == 'wall'
  193 + activities = @profile.activities.paginate(:per_page => 15, :page => params[:page]) if params[:not_load_scraps].nil?
  194 + render :partial => 'profile_activities_list', :locals => {:activities => activities}
  195 + else
  196 + network_activities = @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page])
  197 + render :partial => 'profile_network_activities', :locals => {:network_activities => network_activities}
  198 + end
190 end 199 end
191 200
192 def view_more_activities 201 def view_more_activities
193 - @activities = @profile.tracked_actions.paginate(:per_page => 30, :page => params[:page])  
194 - render :partial => 'profile_activities', :locals => {:activities => @activities} 202 + @activities = @profile.activities.paginate(:per_page => 10, :page => params[:page])
  203 + render :partial => 'profile_activities_list', :locals => {:activities => @activities}
195 end 204 end
196 205
197 def view_more_network_activities 206 def view_more_network_activities
198 - @activities = @profile.tracked_notifications.paginate(:per_page => 30, :page => params[:page]) 207 + @activities = @profile.tracked_notifications.paginate(:per_page => 10, :page => params[:page])
199 render :partial => 'profile_network_activities', :locals => {:network_activities => @activities} 208 render :partial => 'profile_network_activities', :locals => {:network_activities => @activities}
200 end 209 end
201 210
@@ -213,7 +222,11 @@ class ProfileController < PublicController @@ -213,7 +222,11 @@ class ProfileController < PublicController
213 begin 222 begin
214 raise if !can_edit_profile 223 raise if !can_edit_profile
215 activity = ActionTracker::Record.find(params[:activity_id]) 224 activity = ActionTracker::Record.find(params[:activity_id])
216 - activity.destroy 225 + if params[:only_hide]
  226 + activity.update_attribute(:visible, false)
  227 + else
  228 + activity.destroy
  229 + end
217 render :text => _('Activity successfully removed.') 230 render :text => _('Activity successfully removed.')
218 rescue 231 rescue
219 render :text => _('You could not remove this activity') 232 render :text => _('You could not remove this activity')
@@ -285,6 +298,16 @@ class ProfileController < PublicController @@ -285,6 +298,16 @@ class ProfileController < PublicController
285 end 298 end
286 end 299 end
287 300
  301 + def remove_comment
  302 + #FIXME Check whether these permissions are enough
  303 + @comment = Comment.find(params[:comment_id])
  304 + if (user == @comment.author || user == profile || user.has_permission?(:moderate_comments, profile))
  305 + @comment.destroy
  306 + session[:notice] = _('Comment successfully deleted')
  307 + end
  308 + redirect_to :action => :index
  309 + end
  310 +
288 protected 311 protected
289 312
290 def check_access_to_profile 313 def check_access_to_profile
app/helpers/application_helper.rb
@@ -1218,15 +1218,12 @@ module ApplicationHelper @@ -1218,15 +1218,12 @@ module ApplicationHelper
1218 else _('1 minute') 1218 else _('1 minute')
1219 end 1219 end
1220 1220
1221 - when 2..44 then _('%{distance} minutes') % { :distance => distance_in_minutes }  
1222 - when 45..89 then _('about 1 hour')  
1223 - when 90..1439 then _('about %{distance} hours') % { :distance => (distance_in_minutes.to_f / 60.0).round }  
1224 - when 1440..2879 then _('1 day')  
1225 - when 2880..43199 then _('%{distance} days') % { :distance => (distance_in_minutes / 1440).round }  
1226 - when 43200..86399 then _('about 1 month')  
1227 - when 86400..525599 then _('%{distance} months') % { :distance => (distance_in_minutes / 43200).round }  
1228 - when 525600..1051199 then _('about 1 year')  
1229 - else _('over %{distance} years') % { :distance => (distance_in_minutes / 525600).round } 1221 + when 2..44 then _('%{distance} minutes ago') % { :distance => distance_in_minutes }
  1222 + when 45..89 then _('about 1 hour ago')
  1223 + when 90..1439 then _('about %{distance} hours ago') % { :distance => (distance_in_minutes.to_f / 60.0).round }
  1224 + when 1440..2879 then _('1 day ago')
  1225 + when 2880..10079 then _('%{distance} days ago') % { :distance => (distance_in_minutes / 1440).round }
  1226 + else show_time(from_time)
1230 end 1227 end
1231 end 1228 end
1232 1229
app/helpers/forum_helper.rb
@@ -42,9 +42,9 @@ module ForumHelper @@ -42,9 +42,9 @@ module ForumHelper
42 def last_topic_update(article) 42 def last_topic_update(article)
43 info = article.info_from_last_update 43 info = article.info_from_last_update
44 if info[:author_url] 44 if info[:author_url]
45 - time_ago_as_sentence(info[:date]) + ' ' + _('ago') + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url]) 45 + time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url])
46 else 46 else
47 - time_ago_as_sentence(info[:date]) + ' ' + _('ago') + ' ' + _('by') + ' ' + info[:author_name] 47 + time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + info[:author_name]
48 end 48 end
49 end 49 end
50 50
app/models/action_tracker_notification.rb
@@ -3,6 +3,8 @@ class ActionTrackerNotification < ActiveRecord::Base @@ -3,6 +3,8 @@ class ActionTrackerNotification < ActiveRecord::Base
3 belongs_to :profile 3 belongs_to :profile
4 belongs_to :action_tracker, :class_name => 'ActionTracker::Record', :foreign_key => 'action_tracker_id' 4 belongs_to :action_tracker, :class_name => 'ActionTracker::Record', :foreign_key => 'action_tracker_id'
5 5
  6 + has_many :comments, :through => :action_tracker, :class_name => 'Comment', :foreign_key => 'source_id'
  7 +
6 validates_presence_of :profile_id, :action_tracker_id 8 validates_presence_of :profile_id, :action_tracker_id
7 validates_uniqueness_of :action_tracker_id, :scope => :profile_id 9 validates_uniqueness_of :action_tracker_id, :scope => :profile_id
8 10
app/models/article.rb
@@ -8,9 +8,7 @@ class Article < ActiveRecord::Base @@ -8,9 +8,7 @@ class Article < ActiveRecord::Base
8 _('Content') 8 _('Content')
9 end 9 end
10 10
11 - track_actions :create_article, :after_create, :keep_params => [:name, :url], :if => Proc.new { |a| a.is_trackable? && !a.image? }, :custom_target => :action_tracker_target  
12 - track_actions :update_article, :before_update, :keep_params => [:name, :url], :if => Proc.new { |a| a.is_trackable? && (a.body_changed? || a.name_changed?) }, :custom_target => :action_tracker_target  
13 - track_actions :remove_article, :before_destroy, :keep_params => [:name], :if => Proc.new { |a| a.is_trackable? }, :custom_target => :action_tracker_target 11 + track_actions :create_article, :after_create, :keep_params => [:name, :url, :lead, :first_image], :if => Proc.new { |a| a.is_trackable? && !a.image? }
14 12
15 # xss_terminate plugin can't sanitize array fields 13 # xss_terminate plugin can't sanitize array fields
16 before_save :sanitize_tag_list 14 before_save :sanitize_tag_list
@@ -23,7 +21,7 @@ class Article < ActiveRecord::Base @@ -23,7 +21,7 @@ class Article < ActiveRecord::Base
23 21
24 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' 22 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id'
25 23
26 - has_many :comments, :dependent => :destroy, :order => 'created_at asc' 24 + has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc'
27 25
28 has_many :article_categorizations, :conditions => [ 'articles_categories.virtual = ?', false ] 26 has_many :article_categorizations, :conditions => [ 'articles_categories.virtual = ?', false ]
29 has_many :categories, :through => :article_categorizations 27 has_many :categories, :through => :article_categorizations
@@ -74,7 +72,7 @@ class Article < ActiveRecord::Base @@ -74,7 +72,7 @@ class Article < ActiveRecord::Base
74 validate :translation_must_have_language 72 validate :translation_must_have_language
75 73
76 def is_trackable? 74 def is_trackable?
77 - self.published? && self.notifiable? && self.advertise? 75 + self.published? && self.notifiable? && self.advertise? && self.profile.public_profile
78 end 76 end
79 77
80 def external_link=(link) 78 def external_link=(link)
@@ -147,7 +145,7 @@ class Article < ActiveRecord::Base @@ -147,7 +145,7 @@ class Article < ActiveRecord::Base
147 before_update do |article| 145 before_update do |article|
148 article.advertise = true 146 article.advertise = true
149 end 147 end
150 - 148 +
151 # retrieves all articles belonging to the given +profile+ that are not 149 # retrieves all articles belonging to the given +profile+ that are not
152 # sub-articles of any other article. 150 # sub-articles of any other article.
153 named_scope :top_level_for, lambda { |profile| 151 named_scope :top_level_for, lambda { |profile|
@@ -597,6 +595,21 @@ class Article < ActiveRecord::Base @@ -597,6 +595,21 @@ class Article < ActiveRecord::Base
597 _('Created at: ') 595 _('Created at: ')
598 end 596 end
599 597
  598 + def activity
  599 + ActionTracker::Record.find_by_target_type_and_target_id 'Article', self.id
  600 + end
  601 +
  602 + def create_activity
  603 + if is_trackable? && !image?
  604 + save_action_for_verb 'create_article', [:name, :url, :lead, :first_image], Proc.new{}, :author
  605 + end
  606 + end
  607 +
  608 + def first_image
  609 + img = Hpricot(self.lead.to_s).search('img[@src]').first || Hpricot(self.body.to_s).search('img').first
  610 + img.nil? ? '' : img.attributes['src']
  611 + end
  612 +
600 private 613 private
601 614
602 # FIXME: workaround for development env. 615 # FIXME: workaround for development env.
app/models/comment.rb
1 class Comment < ActiveRecord::Base 1 class Comment < ActiveRecord::Base
2 2
3 - track_actions :leave_comment, :after_create, :keep_params => ["article.title", "article.url", "title", "url", "body"], :custom_target => :action_tracker_target  
4 -  
5 validates_presence_of :body 3 validates_presence_of :body
6 - belongs_to :article, :counter_cache => true 4 +
  5 + belongs_to :source, :counter_cache => true, :polymorphic => true
  6 + alias :article :source
  7 + alias :article= :source=
  8 +
7 belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id' 9 belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id'
8 has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy 10 has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy
9 belongs_to :reply_of, :class_name => 'Comment', :foreign_key => 'reply_of_id' 11 belongs_to :reply_of, :class_name => 'Comment', :foreign_key => 'reply_of_id'
@@ -70,13 +72,25 @@ class Comment &lt; ActiveRecord::Base @@ -70,13 +72,25 @@ class Comment &lt; ActiveRecord::Base
70 after_save :notify_article 72 after_save :notify_article
71 after_destroy :notify_article 73 after_destroy :notify_article
72 def notify_article 74 def notify_article
73 - article.comments_updated 75 + article.comments_updated if article.kind_of?(Article)
74 end 76 end
75 77
76 after_create do |comment| 78 after_create do |comment|
77 - if comment.article.notify_comments? && !comment.article.profile.notification_emails.empty? 79 + if comment.source.kind_of?(Article) && comment.article.notify_comments? && !comment.article.profile.notification_emails.empty?
78 Comment::Notifier.deliver_mail(comment) 80 Comment::Notifier.deliver_mail(comment)
79 end 81 end
  82 +
  83 + if comment.source.kind_of?(Article)
  84 + comment.article.create_activity if comment.article.activity.nil?
  85 + if comment.article.activity
  86 + comment.article.activity.increment!(:comments_count)
  87 + comment.article.activity.update_attribute(:visible, true)
  88 + end
  89 + end
  90 + end
  91 +
  92 + after_destroy do |comment|
  93 + comment.article.activity.decrement!(:comments_count) if comment.source.kind_of?(Article) && comment.article.activity
80 end 94 end
81 95
82 def replies 96 def replies
app/models/community.rb
@@ -87,4 +87,8 @@ class Community &lt; Organization @@ -87,4 +87,8 @@ class Community &lt; Organization
87 {:title => __('Community Info and settings'), :icon => 'edit-profile-group'} 87 {:title => __('Community Info and settings'), :icon => 'edit-profile-group'}
88 end 88 end
89 89
  90 + def activities
  91 + Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.target_id = #{self.id} UNION SELECT at.id, at.updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} at INNER JOIN articles a ON at.target_id = a.id WHERE a.profile_id = #{self.id} AND at.target_type = 'Article' ORDER BY updated_at DESC")
  92 + end
  93 +
90 end 94 end
app/models/enterprise.rb
@@ -180,4 +180,8 @@ class Enterprise &lt; Organization @@ -180,4 +180,8 @@ class Enterprise &lt; Organization
180 true 180 true
181 end 181 end
182 182
  183 + def activities
  184 + Scrap.find_by_sql("SELECT id, updated_at, 'Scrap' AS klass FROM scraps WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, 'ActionTracker::Record' AS klass FROM action_tracker WHERE action_tracker.target_id = #{self.id} UNION SELECT action_tracker.id, action_tracker.updated_at, 'ActionTracker::Record' AS klass FROM action_tracker INNER JOIN articles ON action_tracker.target_id = articles.id WHERE articles.profile_id = #{self.id} AND action_tracker.target_type = 'Article' ORDER BY action_tracker.updated_at DESC")
  185 + end
  186 +
183 end 187 end
app/models/event.rb
@@ -124,6 +124,10 @@ class Event &lt; Article @@ -124,6 +124,10 @@ class Event &lt; Article
124 true 124 true
125 end 125 end
126 126
  127 + def notifiable?
  128 + true
  129 + end
  130 +
127 include Noosfero::TranslatableContent 131 include Noosfero::TranslatableContent
128 include MaybeAddHttp 132 include MaybeAddHttp
129 133
app/models/external_feed.rb
@@ -14,6 +14,7 @@ class ExternalFeed &lt; ActiveRecord::Base @@ -14,6 +14,7 @@ class ExternalFeed &lt; ActiveRecord::Base
14 article = TinyMceArticle.new(:name => title, :profile => blog.profile, :body => content, :published_at => date, :source => link, :profile => blog.profile, :parent => blog) 14 article = TinyMceArticle.new(:name => title, :profile => blog.profile, :body => content, :published_at => date, :source => link, :profile => blog.profile, :parent => blog)
15 unless blog.children.exists?(:slug => article.slug) 15 unless blog.children.exists?(:slug => article.slug)
16 article.save! 16 article.save!
  17 + article.delay.create_activity
17 end 18 end
18 end 19 end
19 20
app/models/forum.rb
@@ -28,4 +28,14 @@ class Forum &lt; Folder @@ -28,4 +28,14 @@ class Forum &lt; Folder
28 def self.icon_name(article = nil) 28 def self.icon_name(article = nil)
29 'forum' 29 'forum'
30 end 30 end
  31 +
  32 + def notifiable?
  33 + true
  34 + end
  35 +
  36 + def first_paragraph
  37 + return '' if body.blank?
  38 + paragraphs = Hpricot(body).search('p')
  39 + paragraphs.empty? ? '' : paragraphs.first.to_html
  40 + end
31 end 41 end
app/models/image.rb
@@ -13,7 +13,7 @@ class Image &lt; ActiveRecord::Base @@ -13,7 +13,7 @@ class Image &lt; ActiveRecord::Base
13 :thumbnails => { :big => '150x150', 13 :thumbnails => { :big => '150x150',
14 :thumb => '100x100', 14 :thumb => '100x100',
15 :portrait => '64x64', 15 :portrait => '64x64',
16 - :minor => '50x50', 16 + :minor => '50x50>',
17 :icon => '20x20!' }, 17 :icon => '20x20!' },
18 :max_size => 5.megabytes # remember to update validate message below 18 :max_size => 5.megabytes # remember to update validate message below
19 19
app/models/person.rb
@@ -442,6 +442,10 @@ class Person &lt; Profile @@ -442,6 +442,10 @@ class Person &lt; Profile
442 user.save! 442 user.save!
443 end 443 end
444 444
  445 + def activities
  446 + Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.user_id = #{self.id} ORDER BY updated_at DESC")
  447 + end
  448 +
445 protected 449 protected
446 450
447 def followed_by?(profile) 451 def followed_by?(profile)
app/models/profile.rb
@@ -840,6 +840,11 @@ private :generate_url, :url_options @@ -840,6 +840,11 @@ private :generate_url, :url_options
840 name 840 name
841 end 841 end
842 842
  843 + # Override in your subclasses
  844 + def activities
  845 + []
  846 + end
  847 +
843 private 848 private
844 def self.f_categories_label_proc(environment) 849 def self.f_categories_label_proc(environment)
845 ids = environment.top_level_category_as_facet_ids 850 ids = environment.top_level_category_as_facet_ids
app/models/scrap.rb
@@ -12,6 +12,7 @@ class Scrap &lt; ActiveRecord::Base @@ -12,6 +12,7 @@ class Scrap &lt; ActiveRecord::Base
12 named_scope :not_replies, :conditions => {:scrap_id => nil} 12 named_scope :not_replies, :conditions => {:scrap_id => nil}
13 13
14 track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.receiver != s.sender}, :custom_target => :action_tracker_target 14 track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.receiver != s.sender}, :custom_target => :action_tracker_target
  15 +
15 track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.receiver == s.sender} 16 track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.receiver == s.sender}
16 17
17 after_create do |scrap| 18 after_create do |scrap|
app/models/uploaded_file.rb
@@ -8,7 +8,7 @@ class UploadedFile &lt; Article @@ -8,7 +8,7 @@ class UploadedFile &lt; Article
8 _('File') 8 _('File')
9 end 9 end
10 10
11 - track_actions :upload_image, :after_create, :keep_params => ["view_url", "thumbnail_path", "parent.url", "parent.name"], :if => Proc.new { |a| a.published? && a.image? && !a.parent.nil? && a.parent.gallery? } 11 + track_actions :upload_image, :after_create, :keep_params => ["view_url", "thumbnail_path", "parent.url", "parent.name"], :if => Proc.new { |a| a.published? && a.image? && !a.parent.nil? && a.parent.gallery? }, :custom_target => :action_tracker_target
12 12
13 include ShortFilename 13 include ShortFilename
14 14
@@ -29,7 +29,7 @@ class UploadedFile &lt; Article @@ -29,7 +29,7 @@ class UploadedFile &lt; Article
29 end 29 end
30 30
31 def thumbnail_path 31 def thumbnail_path
32 - self.image? ? self.full_filename(:thumb).gsub(File.join(RAILS_ROOT, 'public'), '') : nil 32 + self.image? ? self.full_filename(:display).gsub(File.join(RAILS_ROOT, 'public'), '') : nil
33 end 33 end
34 34
35 def display_title 35 def display_title
@@ -144,4 +144,9 @@ class UploadedFile &lt; Article @@ -144,4 +144,9 @@ class UploadedFile &lt; Article
144 def uploaded_file? 144 def uploaded_file?
145 true 145 true
146 end 146 end
  147 +
  148 + def action_tracker_target
  149 + self
  150 + end
  151 +
147 end 152 end
app/views/profile/_add_member_in_community.rhtml 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity, :tab_action => tab_action } %>
app/views/profile/_comment.rhtml 0 → 100644
@@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
  1 +<% Comment %>
  2 +<% Profile %>
  3 +<% Person %>
  4 +
  5 +<li class="article-comment" style='border-bottom:none;'>
  6 + <div class="article-comment-inner">
  7 +
  8 + <div class="comment-content comment-logged-in">
  9 +
  10 + <% if comment.author %>
  11 + <%= link_to image_tag(profile_icon(comment.author, :minor)),
  12 + Person.find(comment.author_id).url,
  13 + :class => 'comment-picture',
  14 + :title => comment.author_name
  15 + %>
  16 + <% end %>
  17 +
  18 + <div class="comment-details">
  19 + <div class="comment-text">
  20 + <%= link_to(comment.author_name, comment.author.url) %>
  21 + <% unless comment.title.blank? %>
  22 + <span class="comment-title"><%= comment.title %></span><br/>
  23 + <% end %>
  24 + <%= txt2html comment.body %>
  25 + </div>
  26 + <div class="profile-activity-time">
  27 + <%= time_ago_as_sentence(comment.created_at) %>
  28 + </div>
  29 + </div>
  30 +
  31 + <% if logged_in? && (user == profile || user == comment.author || user.has_permission?(:moderate_comments, profile)) %>
  32 + <% button_bar(:style => 'float: right; margin-top: 0px;') do %>
  33 + <%= icon_button(:delete, _('Remove'), { :action => :remove_comment, :comment_id => comment.id }, :method => :get, :confirm => _('Are you sure you want to remove this comment and all its replies?')) %>
  34 + <% end %>
  35 + <% end %>
  36 + <br style="clear: both;" />
  37 +
  38 + <div class="comment_reply post_comment_box closed">
  39 + <% if @comment && @comment.errors.any? && @comment.reply_of_id.to_i == comment.id %>
  40 + <%= error_messages_for :comment %>
  41 + <script type="text/javascript">
  42 + jQuery(function() {
  43 + document.location.href = '#<%= comment.anchor %>';
  44 + add_comment_reply_form('#comment-reply-to-<%= comment.id %>', <%= comment.id %>);
  45 + });
  46 + </script>
  47 + <% end %>
  48 + <%= report_abuse(comment.author, :comment_link, comment) if comment.author %>
  49 + <%= link_to_function _('Reply'),
  50 + "var f = add_comment_reply_form(this, %s); f.find('input[name=comment[title]], textarea').val(''); return false" % comment.id,
  51 + :class => 'comment-footer comment-footer-link comment-footer-hide',
  52 + :id => 'comment-reply-to-' + comment.id.to_s
  53 + %>
  54 + </div>
  55 +
  56 + </div>
  57 +
  58 + <% unless comment.replies.blank? %>
  59 + <ul class="comment-replies">
  60 + <% comment.replies.each do |reply| %>
  61 + <%= render :partial => 'comment', :locals => { :comment => reply } %>
  62 + <% end %>
  63 + </ul>
  64 + <% end %>
  65 +
  66 + </div>
  67 +</li>
app/views/profile/_create_article.rhtml 0 → 100644
@@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
  1 +<div class='profile-activity-image'>
  2 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  3 +</div>
  4 +<div class='profile-activity-description profile-activity-article-<%= activity.target.class.icon_name %>'>
  5 + <p class='profile-activity-text'>
  6 + <%= link_to activity.user.short_name(20), activity.user.url %>
  7 + <%= _("on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url) if activity.target.profile.is_a?(Community) %>
  8 + </p>
  9 + <div class='profile-activity-lead'>
  10 + <div class='article-name'><%= link_to(activity.params['name'], activity.params['url']) %></div>
  11 + <span title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-new<%= activity.target.class.icon_name %>'></span>
  12 + <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xA0|\xC2|\s)+/, ' ').gsub(/^\s+/, '') %> <small><%= link_to(_('See more'), activity.params['url']) unless activity.get_lead.blank? %></small>
  13 + </div>
  14 + <%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %>
  15 + <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p>
  16 + <div class='profile-wall-actions'>
  17 + <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %>
  18 + <%= link_to_remote(content_tag(:span, _('Remove')), :url =>{:action => 'remove_activity', :activity_id => activity.id, :only_hide => true}, :confirm => _('Are you sure?'), :update => "profile-activity-item-#{activity.id}") if logged_in? && current_person == @profile %>
  19 + </div>
  20 +</div>
  21 +
  22 +<%= render :partial => 'profile_comments', :locals => { :activity => activity, :tab_action => tab_action } %>
app/views/profile/_default_activity.rhtml 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<div class='profile-activity-image'>
  2 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  3 +</div>
  4 +<div class='profile-activity-description'>
  5 + <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>
  6 + <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p>
  7 + <div class='profile-wall-actions'>
  8 + <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %>
  9 + <%= link_to_remote(content_tag(:span, _('Remove')), :confirm => _('Are you sure?'), :url =>{:action => 'remove_activity', :activity_id => activity.id}, :update => "profile-activity-item-#{activity.id}") if logged_in? && current_person == @profile %>
  10 + </div>
  11 +</div>
  12 +
  13 +<%= render :partial => 'profile_comments', :locals => { :activity => activity, :tab_action => tab_action } %>
app/views/profile/_join_community.rhtml 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +_add_member_in_community.rhtml
0 \ No newline at end of file 2 \ No newline at end of file
app/views/profile/_leave_comment_on_activity.rhtml 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +NÃO É PRA APARECER
app/views/profile/_leave_scrap.rhtml
1 -<%= @message %>  
2 -<% unless @scraps.nil? %>  
3 - <%= render :partial => 'profile_scraps', :locals => {:scraps => @scraps} %>  
4 -<% end %> 1 +<div class='profile-activity-image'>
  2 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  3 +</div>
  4 +<div class='profile-activity-description'>
  5 + <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>
  6 + <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p>
  7 + <div class='profile-wall-actions'>
  8 + <%= link_to_remote(content_tag(:span, _('Remove')), :confirm => _('Are you sure?'), :url =>{:action => 'remove_activity', :activity_id => activity.id}, :update => "profile-activity-item-#{activity.id}") if logged_in? && current_person == @profile %>
  9 + </div>
  10 +</div>
  11 +
  12 +<br/>
app/views/profile/_leave_scrap_to_self.rhtml 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +_leave_scrap.rhtml
0 \ No newline at end of file 2 \ No newline at end of file
app/views/profile/_new_friendship.rhtml 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +_add_member_in_community.rhtml
0 \ No newline at end of file 2 \ No newline at end of file
app/views/profile/_profile.rhtml
1 -<tr>  
2 - <td colspan='2'> 1 +NÃO DEVE APARECER
3 2
4 - <% plugins_tabs = @plugins.dispatch(:profile_tabs).  
5 - map { |tab| {:title => tab[:title], :id => tab[:id], :content => instance_eval(&tab[:content]), :start => tab[:title]} }%>  
6 -  
7 - <% tabs = plugins_tabs.select { |tab| tab[:start] } %>  
8 -  
9 - <% if logged_in? && current_person.follows?(@profile) %>  
10 - <% tabs << {:title => _('Wall'), :id => 'profile-wall', :content => (render :partial => 'profile_wall')} %>  
11 - <% end %>  
12 -  
13 - <% if @profile.organization? %>  
14 - <% tabs << {:title => _('What\'s new'), :id => 'profile-network', :content => (render :partial => 'profile_network')} %>  
15 - <% tabs << {:title => _('Profile'), :id => 'organization-profile', :content => (render :partial => 'organization_profile')} %>  
16 - <% elsif @profile.person? %>  
17 - <% if logged_in? && current_person.follows?(@profile) %>  
18 - <% tabs << {:title => _('Network'), :id => 'profile-network', :content => (render :partial => 'profile_network')} %>  
19 - <% end %>  
20 -  
21 - <% tabs << {:title => _('Activity'), :id => 'profile-activity', :content => (render :partial => 'profile_activity')} %>  
22 - <% tabs << {:title => _('Profile'), :id => 'person-profile', :content => (render :partial => 'person_profile')} %>  
23 - <% end %>  
24 -  
25 - <% tabs += plugins_tabs.select { |tab| !tab[:start] } %>  
26 -  
27 - <%= render_tabs(tabs) %>  
28 -  
29 - </td>  
30 -</tr>  
app/views/profile/_profile_activities.rhtml
@@ -1,18 +0,0 @@ @@ -1,18 +0,0 @@
1 -<% activities.each do |activity| %>  
2 - <li class='profile-activity-item <%= activity.verb %>' id='profile-activity-item-<%= activity.id %>'>  
3 - <div class='profile-activity-image'>  
4 - <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>  
5 - </div>  
6 - <div class='profile-activity-description'>  
7 - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) + ' ' + _('ago') %></p>  
8 - <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>  
9 - <%= button_to_remote(:delete, content_tag(:span, _('Remove')), :url =>{:action => 'remove_activity', :activity_id => activity.id}, :update => "profile-activity-item-#{activity.id}") if can_edit_profile %>  
10 - </div>  
11 - <hr />  
12 - </li>  
13 -<% end %>  
14 -<% if activities.current_page < activities.total_pages %>  
15 - <div id='profile_activities_page_<%= activities.current_page %>'>  
16 - <%= button_to_remote :add, _('View more'), :url => {:action => 'view_more_activities', :page => (activities.current_page + 1)}, :update => "profile_activities_page_#{activities.current_page}" %>  
17 - </div>  
18 -<% end %>  
app/views/profile/_profile_activities_list.rhtml 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +<% unless activities.nil? %>
  2 + <% activities.each do |a| %>
  3 + <% activity = a.klass.constantize.find(a.id) %>
  4 + <% if activity.kind_of?(ActionTracker::Record) %>
  5 + <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'wall' } if activity.visible? %>
  6 + <% else %>
  7 + <%= render :partial => 'profile_scrap', :locals => {:scrap => activity } %>
  8 + <% end %>
  9 + <% end %>
  10 +<% end %>
  11 +
  12 +<% if activities.current_page < activities.total_pages %>
  13 + <div id='profile_activities_page_<%= activities.current_page %>'>
  14 + <%= button_to_remote :add, _('View more'), :url => {:action => 'view_more_activities', :page => (activities.current_page + 1)}, :update => "profile_activities_page_#{activities.current_page}" %>
  15 + </div>
  16 +<% end %>
app/views/profile/_profile_activities_scraps.rhtml 0 → 100644
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 +NÂO DEVE APARECER!!
  2 +
app/views/profile/_profile_activity.rhtml
1 -<div id='profile-activity'>  
2 - <h3><%= _("%s's activity") % @profile.name %></h3>  
3 - <ul>  
4 - <%= render :partial => 'profile_activities', :locals => {:activities => @activities} %>  
5 - </ul>  
6 -</div> 1 +<li class='profile-activity-item <%= activity.verb %>' id='profile-activity-item-<%= activity.id %>'>
  2 + <%= render :partial => activity.verb, :locals => { :activity => activity, :tab_action => tab_action }%>
  3 + <hr />
  4 +</li>
app/views/profile/_profile_comment_form.rhtml 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +<div id='profile-wall-reply-<%= activity.id%>'>
  2 + <div id='profile-wall-reply-form-<%= activity.id%>'>
  3 + <p class='profile-wall-reply'>
  4 + <% update_area = tab_action == 'wall' ? 'profile_activities' : 'network-activities' %>
  5 + <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_comment_on_activity', :tab_action => tab_action}, :html => { :class => 'profile-wall-reply-form', 'data-update' => update_area } do %>
  6 + <%= text_area :comment, :body, {:id => "reply_content_#{activity.id}",
  7 + :cols => 50,
  8 + :rows => 1,
  9 + :class => 'submit-with-keypress',
  10 + :title => _('Leave your comment'),
  11 + :onfocus => ('if(this.value==this.title){this.value="";this.style.color="#000"};this.style.backgroundImage="url(' + profile_icon(current_person, :icon, false) + ')"' if logged_in?),
  12 + :onblur => ('if(this.value==""){this.value=this.title;this.style.color="#ccc"};this.style.backgroundImage="none"' if logged_in?),
  13 + :value => _('Leave your comment'),
  14 + :style => 'color: #ccc' } %>
  15 + <%= hidden_field_tag :source_id, activity.id, :id => "activity_id_#{activity.id}" %>
  16 + <% end %>
  17 + </p>
  18 + </div>
  19 + <div id='profile-wall-message-response-<%=activity.id%>' class='profile-wall-message-response'></div>
  20 +</div>
app/views/profile/_profile_comments.rhtml 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<hr />
  2 +
  3 +<% if activity.comments_count > 2 %>
  4 + <div class='view-all-comments icon-chat'>
  5 + <%= link_to(_("View all %s comments") % activity.comments_count, '#') %>
  6 + </div>
  7 +<% 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 +<%= render :partial => 'profile_comment_form', :locals => { :activity => activity, :tab_action => tab_action } %>
app/views/profile/_profile_network.rhtml
1 <h3><%= _("%s's network activity") % @profile.name %></h3> 1 <h3><%= _("%s's network activity") % @profile.name %></h3>
2 -<ul> 2 +<ul id='network-activities' class='profile-activities'>
3 <%= render :partial => 'profile_network_activities', :locals => {:network_activities => @network_activities} %> 3 <%= render :partial => 'profile_network_activities', :locals => {:network_activities => @network_activities} %>
4 </ul> 4 </ul>
app/views/profile/_profile_network_activities.rhtml
1 - <% network_activities.each do |activity| %>  
2 - <li class='profile-network-item <%= activity.verb %>' id='profile-network-item-<%= activity.id %>'>  
3 - <div class='profile-network-image'>  
4 - <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>  
5 - <% if logged_in? && current_person.follows?(activity.user) && current_person != activity.user %>  
6 - <p class='profile-network-send-message'><%= link_to_function _('Scrap'), "hide_and_show(['#profile-network-message-response-#{activity.id}'],['#profile-network-message-#{activity.id}', '#profile-network-form-#{activity.id}']);$('content_#{activity.id}').value='';return false", :class => "profile-send-message", :title => _("Send a message to %s") % activity.user.name %></p>  
7 - <% end %>  
8 - </div>  
9 - <div class='profile-network-description'>  
10 - <p class='profile-network-time'><%= time_ago_as_sentence(activity.created_at) + ' ' + _('ago') %></p>  
11 - <p class='profile-network-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>  
12 - <%= button_to_remote(:delete, content_tag(:span, _('Remove')), :url =>{:action => 'remove_notification', :activity_id => activity.id}, :update => "profile-network-item-#{activity.id}") if can_edit_profile %>  
13 - <p class='profile-network-where'><%= _('In community %s') % link_to(activity.target.name, activity.target.url) if !profile.is_a?(Community) && activity.target.is_a?(Community) %></p>  
14 - </div>  
15 - <div id='profile-network-message-<%= activity.id%>' style='display:none;'>  
16 - <div id='profile-network-form-<%= activity.id%>' style='display:none;'>  
17 - <p class='profile-network-message'>  
18 - <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :not_load_scraps => true}, :update => "profile-network-message-response-#{activity.id}", :success =>"hide_and_show(['#profile-network-form-#{activity.id}'],['#profile-network-message-response-#{activity.id}'])" do %>  
19 - <%= limited_text_area :scrap, :content, 420, "content_#{activity.id}", :cols => 50, :rows => 2 %>  
20 - <%= hidden_field_tag 'receiver_id', activity.user.id %>  
21 - <%= submit_button :add, _('Leave a message') %>  
22 - <%= button_to_function :cancel, _('Cancel'), "hide_and_show(['#profile-network-message-#{activity.id}'],[]);return false" %>  
23 - <% end %>  
24 - </p>  
25 - </div>  
26 - <div id='profile-network-message-response-<%=activity.id%>' class='profile-network-message-response'></div>  
27 - </div>  
28 - <hr />  
29 - </li>  
30 - <% end %> 1 +<% network_activities.each do |activity| %>
  2 + <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'network' } if activity.visible? %>
  3 +<% end %>
31 <% if network_activities.current_page < network_activities.total_pages %> 4 <% if network_activities.current_page < network_activities.total_pages %>
32 <div id='profile_network_activities_page_<%= network_activities.current_page %>'> 5 <div id='profile_network_activities_page_<%= network_activities.current_page %>'>
33 <%= button_to_remote :add, _('View more'), :url => {:action => 'view_more_network_activities', :page => (network_activities.current_page + 1)}, :update => "profile_network_activities_page_#{network_activities.current_page}" %> 6 <%= button_to_remote :add, _('View more'), :url => {:action => 'view_more_network_activities', :page => (network_activities.current_page + 1)}, :update => "profile_network_activities_page_#{network_activities.current_page}" %>
app/views/profile/_profile_scrap.rhtml
1 -<li class='profile-wall-item' id='profile-wall-item-<%= scrap.id %>'>  
2 - <div class='profile-wall-image'> 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) %> 3 <%= link_to(profile_image(scrap.sender, :minor), scrap.sender.url) %>
4 - <% if logged_in? && current_person.follows?(scrap.sender) && current_person != scrap.sender %>  
5 - <p class='profile-wall-send-message'><%= link_to_function _('Scrap'), "hide_and_show(['#profile-wall-message-response-#{scrap.id}'],['#profile-wall-message-#{scrap.id}', '#profile-wall-form-#{scrap.id}']);$('content_#{scrap.id}').value='';return false", :class => "profile-send-message", :title => _("Send a message to %s") % scrap.sender.name %></p>  
6 - <% end %>  
7 </div> 4 </div>
8 - <% comment_balloon :class => 'profile-wall-description' do %>  
9 - <p class='profile-wall-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p>  
10 - <p class='profile-wall-time'><%= time_ago_as_sentence(scrap.created_at) + ' ' + _('ago') %></p>  
11 - <p class='profile-wall-text'><%= txt2html scrap.content %></p>  
12 - <%= button_to_remote(:delete, content_tag(:span, _('Remove')), :url =>{:action => 'remove_scrap', :scrap_id => scrap.id}, :update => "profile-wall-item-#{scrap.id}") if logged_in? && user.can_control_scrap?(scrap) %>  
13 - <% if logged_in? && current_person.follows?(scrap.sender) && scrap.root.nil? %>  
14 - <p class='profile-wall-send-reply'><%= link_to_function _('Reply'), "hide_and_show(['#profile-wall-reply-response-#{scrap.id}'],['#profile-wall-reply-#{scrap.id}', '#profile-wall-reply-form-#{scrap.id}']);$('reply_content_#{scrap.id}').value='';$('scrap_id_#{scrap.id}').value='#{scrap.id}';return false", :class => "profile-send-reply icon-reply" %></p> 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>
15 <% end %> 14 <% end %>
  15 + <%= link_to_remote(content_tag(:span, _('Remove')), :confirm => _('Are you sure?'), :url =>{:action => 'remove_scrap', :scrap_id => scrap.id}, :update => "profile-activity-item-#{scrap.id}") if logged_in? && user.can_control_scrap?(scrap) %>
  16 + </div>
  17 + </div>
  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>
16 <% end %> 23 <% end %>
17 - <ul class="profile-wall-scrap-replies"> 24 +
  25 + <ul class="profile-wall-activities-comments scrap-replies" style="width: auto; <%= 'display:none;' if (scrap.replies.count > 2) %>" >
18 <% scrap.replies.map do |reply| %> 26 <% scrap.replies.map do |reply| %>
19 <%= render :partial => 'profile_scrap', :locals => {:scrap => reply} %> 27 <%= render :partial => 'profile_scrap', :locals => {:scrap => reply} %>
20 <% end %> 28 <% end %>
21 </ul> 29 </ul>
22 - <div id='profile-wall-message-<%= scrap.id%>' style='display:none;'>  
23 - <div id='profile-wall-form-<%= scrap.id%>' style='display:none;'>  
24 - <p class='profile-wall-message'>  
25 - <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :not_load_scraps => true}, :update => "profile-wall-message-response-#{scrap.id}", :success =>"hide_and_show(['#profile-wall-form-#{scrap.id}'],['#profile-wall-message-response-#{scrap.id}'])" do %>  
26 - <%= limited_text_area :scrap, :content, 420, "content_#{scrap.id}", :cols => 50, :rows => 2 %>  
27 - <%= hidden_field_tag 'receiver_id', scrap.sender.id %>  
28 - <%= submit_button :add, _('Leave a scrap') %>  
29 - <%= button_to_function :cancel, _('Cancel'), "hide_and_show(['#profile-wall-message-#{scrap.id}'],[]);return false" %>  
30 - <% end %>  
31 - </p>  
32 - </div>  
33 - <div id='profile-wall-message-response-<%=scrap.id%>' class='profile-wall-message-response'></div>  
34 - </div>  
35 - <div id='profile-wall-reply-<%= scrap.id%>' style='display:none;'>  
36 - <div id='profile-wall-reply-form-<%= scrap.id%>' style='display:none;'>  
37 - <p class='profile-wall-reply'>  
38 - <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap'}, :update => "profile_scraps", :success =>"hide_and_show(['#profile-wall-reply-form-#{scrap.id}'],['#profile-wall-reply-response-#{scrap.id}'])" do %>  
39 - <%= limited_text_area :scrap, :content, 420, "reply_content_#{scrap.id}", :cols => 50, :rows => 2 %>  
40 - <%= hidden_field :scrap, :scrap_id, :id => "scrap_id_#{scrap.id}" %>  
41 - <%= hidden_field_tag 'receiver_id', scrap.sender.id %>  
42 - <%= submit_button :add, _('Leave a scrap') %>  
43 - <%= button_to_function :cancel, _('Cancel'), "hide_and_show(['#profile-wall-reply-#{scrap.id}'],[]);return false" %>  
44 - <% end %>  
45 - </p>  
46 - </div>  
47 - <div id='profile-wall-message-response-<%=scrap.id%>' class='profile-wall-message-response'></div>  
48 - </div> 30 + <%= render :partial => 'profile_scrap_reply_form', :locals => { :scrap => scrap } %>
49 <hr /> 31 <hr />
50 </li> 32 </li>
app/views/profile/_profile_scrap_reply_form.rhtml 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +<div id='profile-wall-reply-<%= scrap.id%>' style='display:none'>
  2 + <div id='profile-wall-reply-form-<%= scrap.id%>' style='display:none'>
  3 + <p class='profile-wall-reply'>
  4 + <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap'}, :update => "profile_activities", :html => { :class => 'profile-wall-reply-form'} do %>
  5 + <%= text_area :scrap, :content, { :id => "reply_content_#{scrap.id}",
  6 + :cols => 50,
  7 + :rows => 1,
  8 + :class => 'submit-with-keypress',
  9 + :title => _('Leave your comment'),
  10 + :onfocus => ('if(this.value==this.title){this.value="";this.style.color="#000"};this.style.backgroundImage="url(' + profile_icon(current_person, :icon, false) + ')"' if logged_in?),
  11 + :onblur => ('if(this.value==""){this.value=this.title;this.style.color="#ccc"};this.style.backgroundImage="none"' if logged_in?),
  12 + :value => _('Leave your comment')
  13 + } %>
  14 + <%= hidden_field_tag 'scrap[scrap_id]', scrap.id %>
  15 + <%= hidden_field_tag 'receiver_id', scrap.sender.id %>
  16 + <% end %>
  17 + </p>
  18 + </div>
  19 + <div id='profile-wall-message-response-<%=scrap.id%>' class='profile-wall-message-response'></div>
  20 +</div>
app/views/profile/_profile_scraps.rhtml
1 -<% scraps.map do |scrap| %>  
2 - <%= render :partial => 'profile_scrap', :locals => {:scrap => scrap} %>  
3 -<% end %>  
4 -<% if scraps.current_page < scraps.total_pages %>  
5 - <div id='profile_scraps_page_<%= scraps.current_page %>'>  
6 - <%= button_to_remote :add, _('View more'), :url => {:action => 'view_more_scraps', :page => (scraps.current_page + 1)}, :update => "profile_scraps_page_#{scraps.current_page}" %>  
7 - </div>  
8 -<% end %> 1 +NÃO DEVE APARECER
app/views/profile/_profile_wall.rhtml
1 <h3><%= _("%s's wall") % @profile.name %></h3> 1 <h3><%= _("%s's wall") % @profile.name %></h3>
2 <div id='leave_scrap'> 2 <div id='leave_scrap'>
3 <%= flash[:error] %> 3 <%= flash[:error] %>
4 - <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_scraps', :success => "$('leave_scrap_content').value=''" do %> 4 + <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_activities', :success => "$('leave_scrap_content').value=''" do %>
5 <%= limited_text_area :scrap, :content, 420, 'leave_scrap_content', :cols => 50, :rows => 2 %> 5 <%= limited_text_area :scrap, :content, 420, 'leave_scrap_content', :cols => 50, :rows => 2 %>
6 - <%= submit_button :scrap, _('Leave a scrap') %> 6 + <%= submit_button :new, _('Share') %>
7 <% end %> 7 <% end %>
8 </div> 8 </div>
9 <div id='leave_scrap_response'></div> 9 <div id='leave_scrap_response'></div>
10 -<ul id='profile_scraps'>  
11 - <%= render :partial => 'profile_scraps', :locals => {:scraps => @wall_items} %> 10 +<ul id='profile_activities' class='profile-activities'>
  11 + <%= render :partial => 'profile_activities_list', :locals => {:activities => @activities} %>
12 </ul> 12 </ul>
app/views/profile/_update_article.rhtml 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +NAO É PRA APARECER
app/views/profile/_upload_image.rhtml 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +<div class="activity-gallery-images-count-<%= activity.get_view_url.size %>">
  2 + <div class='profile-activity-image'>
  3 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  4 + </div>
  5 + <div class='profile-activity-description'>
  6 + <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>
  7 + <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p>
  8 + <div class='profile-wall-actions'>
  9 + <%= link_to(s_('profile|Comment'), '#', { :class => 'focus-on-comment'}) unless activity.get_view_url.size == 1 %>
  10 + <%= link_to_remote(content_tag(:span, _('Remove')), :confirm => _('Are you sure?'), :url =>{:action => 'remove_activity', :activity_id => activity.id}, :update => "profile-activity-item-#{activity.id}") if logged_in? && current_person == @profile %>
  11 + </div>
  12 + </div>
  13 +</div>
  14 +<div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div>
  15 +
  16 +<% if activity.get_view_url.size == 1 %>
  17 + <%= render :partial => 'profile_comments', :locals => { :activity => activity, :tab_action => tab_action } %>
  18 +<% end %>
  19 +
  20 +<br/>
app/views/profile/index.rhtml
@@ -17,6 +17,31 @@ @@ -17,6 +17,31 @@
17 17
18 <% if @profile.public? || (logged_in? && current_person.follows?(@profile)) %> 18 <% if @profile.public? || (logged_in? && current_person.follows?(@profile)) %>
19 <table class='profile'> 19 <table class='profile'>
20 - <%= render :partial => 'profile' %> 20 + <tr>
  21 + <td colspan='2'>
  22 + <% plugins_tabs = @plugins.dispatch(:profile_tabs).
  23 + map { |tab| {:title => tab[:title], :id => tab[:id], :content => instance_eval(&tab[:content]), :start => tab[:title]} }%>
  24 +
  25 + <% tabs = plugins_tabs.select { |tab| tab[:start] } %>
  26 +
  27 + <% if @profile.organization? %>
  28 + <% tabs << {:title => _('Profile'), :id => 'organization-profile', :content => (render :partial => 'organization_profile')} %>
  29 + <% if logged_in? && current_person.follows?(@profile) %>
  30 + <% tabs << {:title => _('Wall'), :id => 'profile-wall', :content => (render :partial => 'profile_wall')} %>
  31 + <% end %>
  32 + <% tabs << {:title => _('What\'s new'), :id => 'profile-network', :content => (render :partial => 'profile_network')} %>
  33 + <% elsif @profile.person? %>
  34 + <% tabs << {:title => _('Profile'), :id => 'person-profile', :content => (render :partial => 'person_profile')} %>
  35 + <% if logged_in? && current_person.follows?(@profile) %>
  36 + <% tabs << {:title => _('Wall'), :id => 'profile-wall', :content => (render :partial => 'profile_wall')} %>
  37 + <% tabs << {:title => _('Network'), :id => 'profile-network', :content => (render :partial => 'profile_network')} %>
  38 + <% end %>
  39 + <% end %>
  40 +
  41 + <% tabs += plugins_tabs.select { |tab| !tab[:start] } %>
  42 +
  43 + <%= render_tabs(tabs) %>
  44 + </td>
  45 + </tr>
21 </table> 46 </table>
22 <% end %> 47 <% end %>
app/views/tasks/_abuse_complaint_accept_details.rhtml
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 <% task.abuse_reports.each do |abuse_report| %> 2 <% task.abuse_reports.each do |abuse_report| %>
3 <div> 3 <div>
4 <strong style="word-wrap: break-word; display: block; padding-right: 40px">"<%= abuse_report.reason %>"</strong> <br /> 4 <strong style="word-wrap: break-word; display: block; padding-right: 40px">"<%= abuse_report.reason %>"</strong> <br />
5 - <i><%= _('Reported by %{reporter} %{time}.') % {:reporter => abuse_report.reporter.name, :time => time_ago_as_sentence(abuse_report.created_at) + ' ' + _('ago')}%></i> <br /> 5 + <i><%= _('Reported by %{reporter} %{time}.') % {:reporter => abuse_report.reporter.name, :time => time_ago_as_sentence(abuse_report.created_at) }%></i> <br />
6 <% if !abuse_report.content.blank? %> 6 <% if !abuse_report.content.blank? %>
7 <button class="display-abuse-report-details" data-report="<%=abuse_report.id%>"><%=_('View details')%></button> 7 <button class="display-abuse-report-details" data-report="<%=abuse_report.id%>"><%=_('View details')%></button>
8 <div style='display: none' id=<%= 'abuse-report-details-'+abuse_report.id.to_s %> class="abuse-report-details"> 8 <div style='display: none' id=<%= 'abuse-report-details-'+abuse_report.id.to_s %> class="abuse-report-details">
config/initializers/action_tracker.rb
@@ -5,18 +5,7 @@ require &#39;noosfero/i18n&#39; @@ -5,18 +5,7 @@ require &#39;noosfero/i18n&#39;
5 ActionTrackerConfig.verbs = { 5 ActionTrackerConfig.verbs = {
6 6
7 :create_article => { 7 :create_article => {
8 - :description => lambda { n_('published 1 article: %{title}', 'published %{num} articles: %{title}', get_name.size) % { :num => get_name.size, :title => '{{ta.collect_group_with_index(:name){ |n,i| link_to(truncate(n), ta.get_url[i]) }.to_sentence(:connector => "%s")}}' % _("and") } },  
9 - :type => :groupable  
10 - },  
11 -  
12 - :update_article => {  
13 - :description => lambda { n_('updated 1 article: %{title}', 'updated %{num} articles: %{title}', get_name.uniq.size) % { :num => get_name.uniq.size, :title => '{{ta.collect_group_with_index(:name){ |n,i| link_to(truncate(n), ta.get_url[i]) }.uniq.to_sentence(:connector => "%s")}}' % _("and") } },  
14 - :type => :groupable  
15 - },  
16 -  
17 - :remove_article => {  
18 - :description => lambda { n_('removed 1 article: %{title}', 'removed %{num} articles: %{title}', get_name.size) % { :num => get_name.size, :title => '{{ta.get_name.collect{ |n| truncate(n) }.to_sentence(:connector => "%s")}}' % _("and") } },  
19 - :type => :groupable 8 + :description => lambda { _('published an article: %{title}') % { :title => '{{link_to(truncate(ta.get_name), ta.get_url)}}' } }
20 }, 9 },
21 10
22 :new_friendship => { 11 :new_friendship => {
@@ -33,24 +22,11 @@ ActionTrackerConfig.verbs = { @@ -33,24 +22,11 @@ ActionTrackerConfig.verbs = {
33 :description => lambda { _('has joined the community.') }, 22 :description => lambda { _('has joined the community.') },
34 }, 23 },
35 24
36 - :remove_member_in_community => {  
37 - :description => lambda { _('has left the community.') },  
38 - },  
39 -  
40 - :leave_community => {  
41 - :description => lambda { n_('has left 1 community:<br />%{name}', 'has left %{num} communities:<br />%{name}', get_resource_name.size) % { :num => get_resource_name.size, :name => '{{ta.collect_group_with_index(:resource_name){ |n,i| link_to(image_tag(ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png")), ta.get_resource_url[i], :title => n)}.join}}' } },  
42 - :type => :groupable  
43 - },  
44 -  
45 :upload_image => { 25 :upload_image => {
46 - :description => lambda { n_('uploaded 1 image:<br />%{thumbnails}<br />%{details}', 'uploaded %{num} images:<br />%{thumbnails}<br />%{details}', get_view_url.size) % { :num => get_view_url.size, :thumbnails => '{{ta.collect_group_with_index(:thumbnail_path){ |t,i| content_tag(:span, link_to(image_tag(t), ta.get_view_url[i]))}.last(3).join}}', :details => '{{unique_with_count(ta.collect_group_with_index(:parent_name){ |n,i| link_to(n, ta.get_parent_url[i])}, "%s").join("<br />")}}' % _("in the gallery") } }, 26 + :description => lambda { n_('uploaded 1 image<br />%{thumbnails}<br style="clear: both;" />', 'uploaded %{num} images<br />%{thumbnails}<br style="clear: both;" />', get_view_url.size) % { :num => get_view_url.size, :thumbnails => '{{ta.collect_group_with_index(:thumbnail_path){ |t,i| content_tag(:span, link_to(image_tag(t), ta.get_view_url[i]))}.last(3).join}}' } },
47 :type => :groupable 27 :type => :groupable
48 }, 28 },
49 29
50 - :leave_comment => {  
51 - :description => lambda { _('has left a comment entitled "%{title}" on the article %{article}: <br /> "%{comment}" (%{read})') % { :title => "{{truncate(ta.get_title)}}", :article => "{{link_to(truncate(ta.get_article_title), ta.get_article_url)}}", :comment => "{{truncate(ta.get_body, 50)}}", :read => '{{link_to("%s", ta.get_url)}}' % _("read") } }  
52 - },  
53 -  
54 :leave_scrap => { 30 :leave_scrap => {
55 :description => lambda { _('sent a message to %{receiver}: <br /> "%{message}"') % { :receiver => "{{link_to(ta.get_receiver_name, ta.get_receiver_url)}}", :message => "{{auto_link_urls(ta.get_content)}}" } } 31 :description => lambda { _('sent a message to %{receiver}: <br /> "%{message}"') % { :receiver => "{{link_to(ta.get_receiver_name, ta.get_receiver_url)}}", :message => "{{auto_link_urls(ta.get_content)}}" } }
56 }, 32 },
db/migrate/20111211204445_add_polymorphism_on_comment.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +class AddPolymorphismOnComment < ActiveRecord::Migration
  2 + def self.up
  3 + rename_column :comments, :article_id, :source_id
  4 + add_column :comments, :source_type, :string
  5 + execute("update comments set source_type = 'Article'")
  6 + end
  7 +
  8 + def self.down
  9 + remove_column :comments, :source_type
  10 + rename_column :comments, :source_id, :article_id
  11 + end
  12 +end
db/migrate/20111211233957_add_comment_count_to_action_tracker.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class AddCommentCountToActionTracker < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :action_tracker, :comments_count, :integer, :default => 0
  4 + end
  5 +
  6 + def self.down
  7 + remove_column :action_tracker, :comments_count, :integer
  8 + end
  9 +end
db/migrate/20111228202739_remove_useless_tracked_actions.rb 0 → 100644
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +class RemoveUselessTrackedActions < ActiveRecord::Migration
  2 + def self.up
  3 + select_all("SELECT id FROM action_tracker").each do |tracker|
  4 + verbs = ['update_article', 'remove_article', 'leave_comment', 'leave_community', 'remove_member_in_community']
  5 + activity = ActionTracker::Record.find_by_id(tracker['id'])
  6 + if activity
  7 + if (activity.updated_at.to_time < Time.now.months_ago(3)) || verbs.include?(activity.verb)
  8 + activity.destroy
  9 + end
  10 + end
  11 + end
  12 + end
  13 +
  14 + def self.down
  15 + say "this migration can't be reverted"
  16 + end
  17 +end
db/migrate/20120228154642_add_visibility_to_action_tracker.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class AddVisibilityToActionTracker < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :action_tracker, :visible, :boolean, :default => true
  4 + end
  5 +
  6 + def self.down
  7 + remove_column :action_tracker, :visible, :boolean
  8 + end
  9 +end
db/migrate/20120228202739_adapt_create_articles_activity.rb 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +class AdaptCreateArticlesActivity < ActiveRecord::Migration
  2 +
  3 + # Removing 'create_article' activities that grouped articles.
  4 + # Creating new activities only to recent articles (not grouping)
  5 + def self.up
  6 + select_all("SELECT id FROM action_tracker WHERE verb = 'create_article'").each do |tracker|
  7 + activity = ActionTracker::Record.find_by_id(tracker['id'])
  8 + if activity
  9 + activity.destroy
  10 + end
  11 + end
  12 +
  13 + select_all("SELECT id FROM articles").each do |art|
  14 + article = Article.find(art['id'])
  15 + if article && article.created_at >= 8.days.ago && article.author && article.author.kind_of?(Person)
  16 + article.create_activity
  17 + end
  18 + end
  19 + end
  20 +
  21 + def self.down
  22 + say "this migration can't be reverted"
  23 + end
  24 +end
@@ -29,6 +29,8 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do @@ -29,6 +29,8 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do
29 t.string "verb" 29 t.string "verb"
30 t.datetime "created_at" 30 t.datetime "created_at"
31 t.datetime "updated_at" 31 t.datetime "updated_at"
  32 + t.integer "comments_count", :default => 0
  33 + t.boolean "visible", :default => true
32 end 34 end
33 35
34 add_index "action_tracker", ["target_id", "target_type"], :name => "index_action_tracker_on_dispatcher_id_and_dispatcher_type" 36 add_index "action_tracker", ["target_id", "target_type"], :name => "index_action_tracker_on_dispatcher_id_and_dispatcher_type"
@@ -200,7 +202,7 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do @@ -200,7 +202,7 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do
200 create_table "comments", :force => true do |t| 202 create_table "comments", :force => true do |t|
201 t.string "title" 203 t.string "title"
202 t.text "body" 204 t.text "body"
203 - t.integer "article_id" 205 + t.integer "source_id"
204 t.integer "author_id" 206 t.integer "author_id"
205 t.string "name" 207 t.string "name"
206 t.string "email" 208 t.string "email"
@@ -208,6 +210,7 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do @@ -208,6 +210,7 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do
208 t.integer "reply_of_id" 210 t.integer "reply_of_id"
209 t.string "ip_address" 211 t.string "ip_address"
210 t.boolean "spam" 212 t.boolean "spam"
  213 + t.string "source_type"
211 end 214 end
212 215
213 create_table "contact_lists", :force => true do |t| 216 create_table "contact_lists", :force => true do |t|
lib/notify_activity_to_profiles_job.rb
1 class NotifyActivityToProfilesJob < Struct.new(:tracked_action_id) 1 class NotifyActivityToProfilesJob < Struct.new(:tracked_action_id)
2 NOTIFY_ONLY_COMMUNITY = [ 2 NOTIFY_ONLY_COMMUNITY = [
3 - 'add_member_in_community',  
4 - 'remove_member_in_community', 3 + 'add_member_in_community'
5 ] 4 ]
6 5
7 NOT_NOTIFY_COMMUNITY = [ 6 NOT_NOTIFY_COMMUNITY = [
8 - 'join_community',  
9 - 'leave_community', 7 + 'join_community'
10 ] 8 ]
11 def perform 9 def perform
12 return unless ActionTracker::Record.exists?(tracked_action_id) 10 return unless ActionTracker::Record.exists?(tracked_action_id)
@@ -17,14 +15,23 @@ class NotifyActivityToProfilesJob &lt; Struct.new(:tracked_action_id) @@ -17,14 +15,23 @@ class NotifyActivityToProfilesJob &lt; Struct.new(:tracked_action_id)
17 return 15 return
18 end 16 end
19 17
  18 + # Notify the user
20 ActionTrackerNotification.create(:profile_id => tracked_action.user.id, :action_tracker_id => tracked_action.id) 19 ActionTrackerNotification.create(:profile_id => tracked_action.user.id, :action_tracker_id => tracked_action.id)
21 20
  21 + # Notify all friends
22 ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select f.friend_id, #{tracked_action.id} from friendships as f where person_id=#{tracked_action.user.id} and f.friend_id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id})") 22 ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select f.friend_id, #{tracked_action.id} from friendships as f where person_id=#{tracked_action.user.id} and f.friend_id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id})")
23 23
24 if target.is_a?(Community) 24 if target.is_a?(Community)
25 - ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select distinct profiles.id, #{tracked_action.id} from role_assignments, profiles where profiles.type = 'Person' and profiles.id = role_assignments.accessor_id and profiles.id != #{tracked_action.user.id} and role_assignments.resource_type = 'Profile' and role_assignments.resource_id = #{target.id}")  
26 -  
27 ActionTrackerNotification.create(:profile_id => target.id, :action_tracker_id => tracked_action.id) unless NOT_NOTIFY_COMMUNITY.include?(tracked_action.verb) 25 ActionTrackerNotification.create(:profile_id => target.id, :action_tracker_id => tracked_action.id) unless NOT_NOTIFY_COMMUNITY.include?(tracked_action.verb)
  26 +
  27 + ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select distinct profiles.id, #{tracked_action.id} from role_assignments, profiles where profiles.type = 'Person' and profiles.id = role_assignments.accessor_id and profiles.id != #{tracked_action.user.id} and profiles.id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id}) and role_assignments.resource_type = 'Profile' and role_assignments.resource_id = #{target.id}")
  28 + end
  29 +
  30 + if target.is_a?(Article) && target.profile.is_a?(Community)
  31 + ActionTrackerNotification.create(:profile_id => target.profile.id, :action_tracker_id => tracked_action.id) unless NOT_NOTIFY_COMMUNITY.include?(tracked_action.verb)
  32 +
  33 + ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select distinct profiles.id, #{tracked_action.id} from role_assignments, profiles where profiles.type = 'Person' and profiles.id = role_assignments.accessor_id and profiles.id != #{tracked_action.user.id} and profiles.id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id}) and role_assignments.resource_type = 'Profile' and role_assignments.resource_id = #{target.profile.id}")
28 end 34 end
  35 +
29 end 36 end
30 end 37 end
public/designs/icons/tango/style.css
@@ -91,7 +91,7 @@ @@ -91,7 +91,7 @@
91 .icon-lock { background-image: url(Tango/16x16/actions/lock.png) } 91 .icon-lock { background-image: url(Tango/16x16/actions/lock.png) }
92 .icon-chat { background-image: url(Tango/16x16/apps/internet-group-chat.png); background-repeat: no-repeat } 92 .icon-chat { background-image: url(Tango/16x16/apps/internet-group-chat.png); background-repeat: no-repeat }
93 .icon-reply { background-image: url(Tango/16x16/actions/mail-reply-sender.png) } 93 .icon-reply { background-image: url(Tango/16x16/actions/mail-reply-sender.png) }
94 -.icon-newforum { background-image: url(Tango/16x16/apps/system-users.png) } 94 +.icon-newforum { background-image: url(Tango/16x16/apps/internet-group-chat.png) }
95 .icon-forum { background-image: url(Tango/16x16/apps/system-users.png) } 95 .icon-forum { background-image: url(Tango/16x16/apps/system-users.png) }
96 .icon-gallery { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) } 96 .icon-gallery { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) }
97 .icon-newgallery { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) } 97 .icon-newgallery { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) }
public/designs/templates/default/stylesheets/style.css
@@ -24,3 +24,9 @@ @@ -24,3 +24,9 @@
24 #profile-wall ul { 24 #profile-wall ul {
25 width: 460px; 25 width: 460px;
26 } 26 }
  27 +#profile-activity ul.comment-replies,
  28 +#profile-network ul.comment-replies,
  29 +#profile-wall ul.comment-replies {
  30 + width: auto;
  31 +}
  32 +
public/designs/templates/leftbar/stylesheets/style.css
@@ -23,3 +23,48 @@ @@ -23,3 +23,48 @@
23 #profile-wall ul { 23 #profile-wall ul {
24 width: 620px; 24 width: 620px;
25 } 25 }
  26 +
  27 +.profile-activity-lead {
  28 + width: 534px;
  29 +}
  30 +
  31 +#profile-wall textarea {
  32 + width: 534px;
  33 +}
  34 +
  35 +#profile-wall #leave_scrap textarea {
  36 + width: 640px;
  37 +}
  38 +
  39 +#profile-wall li textarea {
  40 + width: 548px;
  41 +}
  42 +
  43 +.profile-activity-article-forum .profile-activity-lead {
  44 + background: url(/images/forum-activity-bg-onecol.png);
  45 + width: 489px;
  46 +}
  47 +
  48 +#profile-wall li.profile-activity-item.upload_image span,
  49 +#profile-wall li.profile-activity-item.upload_image span img,
  50 +#profile-wall li.profile-activity-item.upload_image span a,
  51 +#profile-network li.profile-activity-item.upload_image span,
  52 +#profile-network li.profile-activity-item.upload_image span img,
  53 +#profile-network li.profile-activity-item.upload_image span a {
  54 + width: 178px;
  55 + height: 144px;
  56 +}
  57 +
  58 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  59 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a img,
  60 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a,
  61 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  62 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a img,
  63 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a {
  64 + max-width: 540px;
  65 +}
  66 +
  67 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a,
  68 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a {
  69 + background-image: url(/images/gallery-image-activity-border-big-onecol.png);
  70 +}
public/designs/templates/rightbar/stylesheets/style.css
@@ -23,3 +23,43 @@ @@ -23,3 +23,43 @@
23 #profile-wall ul { 23 #profile-wall ul {
24 width: 620px; 24 width: 620px;
25 } 25 }
  26 +
  27 +.profile-activity-lead {
  28 + width: 534px;
  29 +}
  30 +
  31 +#profile-wall textarea {
  32 + width: 534px;
  33 +}
  34 +
  35 +#profile-wall #leave_scrap textarea {
  36 + width: 640px;
  37 +}
  38 +
  39 +#profile-wall li textarea {
  40 + width: 548px;
  41 +}
  42 +
  43 +.profile-activity-article-forum .profile-activity-lead {
  44 + background: url(/images/forum-activity-bg-onecol.png);
  45 + width: 489px;
  46 +}
  47 +
  48 +#profile-wall li.profile-activity-item.upload_image span,
  49 +#profile-wall li.profile-activity-item.upload_image span img,
  50 +#profile-wall li.profile-activity-item.upload_image span a,
  51 +#profile-network li.profile-activity-item.upload_image span,
  52 +#profile-network li.profile-activity-item.upload_image span img,
  53 +#profile-network li.profile-activity-item.upload_image span a {
  54 + width: 178px;
  55 + height: 144px;
  56 +}
  57 +
  58 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  59 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a img,
  60 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a,
  61 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  62 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a img,
  63 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a {
  64 + max-width: 540px;
  65 +}
public/images/forum-activity-bg-onecol.png 0 → 100644

1.73 KB

public/images/forum-activity-bg.png 0 → 100644

1.72 KB

public/images/forum-activity-icon.png 0 → 100644

477 Bytes

public/images/gallery-image-activity-border-big-onecol.png 0 → 100644

2.21 KB

public/images/gallery-image-activity-border-big.png 0 → 100644

1.32 KB

public/images/gallery-image-activity-border-onecol.png 0 → 100644

1.44 KB

public/images/gallery-image-activity-border.png 0 → 100644

1.01 KB

public/javascripts/application.js
@@ -711,6 +711,41 @@ Array.min = function(array) { @@ -711,6 +711,41 @@ Array.min = function(array) {
711 return Math.min.apply(Math, array); 711 return Math.min.apply(Math, array);
712 }; 712 };
713 713
  714 +jQuery(function($){
  715 + $('.submit-with-keypress').live('keydown', function(e) {
  716 + field = this;
  717 + if (e.keyCode == 13) {
  718 + e.preventDefault();
  719 + var form = $(field).closest("form");
  720 + $.ajax({
  721 + url: form.attr("action"),
  722 + data: form.serialize(),
  723 + beforeSend: function() {
  724 + loading_for_button($(field));
  725 + },
  726 + success: function(data) {
  727 + var update = form.attr('data-update');
  728 + $('#'+update).html(data);
  729 + $(field).val($(field).attr('title'));
  730 + }
  731 + });
  732 + return false;
  733 + }
  734 + });
  735 +
  736 + $('.view-all-comments').live('click', function(e) {
  737 + var link = this;
  738 + $(link).parent().find('.profile-wall-activities-comments').show();
  739 + $(link).hide();
  740 + return false;
  741 + });
  742 + $('.focus-on-comment').live('click', function(e) {
  743 + var link = this;
  744 + $(link).parents('.profile-activity-item').find('textarea').focus();
  745 + return false;
  746 + });
  747 +});
  748 +
714 /** 749 /**
715 * @author Remy Sharp 750 * @author Remy Sharp
716 * @url http://remysharp.com/2007/01/25/jquery-tutorial-text-box-hints/ 751 * @url http://remysharp.com/2007/01/25/jquery-tutorial-text-box-hints/
public/stylesheets/application.css
@@ -240,6 +240,13 @@ td.field-name { @@ -240,6 +240,13 @@ td.field-name {
240 text-align: left; 240 text-align: left;
241 vertical-align: top; 241 vertical-align: top;
242 } 242 }
  243 +
  244 +table.profile .ui-tabs .ui-tabs-panel {
  245 + border-left: 0;
  246 + border-right: 0;
  247 + border-bottom: 0;
  248 +}
  249 +
243 table.profile th { 250 table.profile th {
244 border-bottom: 2px solid #eeeeec; 251 border-bottom: 2px solid #eeeeec;
245 padding: 10px 0px 0px 0px; 252 padding: 10px 0px 0px 0px;
@@ -1034,6 +1041,11 @@ a.comment-picture { @@ -1034,6 +1041,11 @@ a.comment-picture {
1034 .comment-logged-out .comment-text { 1041 .comment-logged-out .comment-text {
1035 color: #888; 1042 color: #888;
1036 } 1043 }
  1044 +
  1045 +.comment-title {
  1046 + font-size: 12px;
  1047 + font-weight: bold;
  1048 +}
1037 .comment-created-at { 1049 .comment-created-at {
1038 padding-right: 9px; 1050 padding-right: 9px;
1039 } 1051 }
@@ -1205,7 +1217,9 @@ a.comment-picture { @@ -1205,7 +1217,9 @@ a.comment-picture {
1205 -webkit-border-radius: 5px; 1217 -webkit-border-radius: 5px;
1206 border-radius: 5px; 1218 border-radius: 5px;
1207 } 1219 }
1208 -.comment-replies .article-comment-inner { 1220 +
  1221 +.comment-replies .article-comment-inner,
  1222 +.scrap-replies {
1209 border: 1px solid #fff; 1223 border: 1px solid #fff;
1210 padding: 0; 1224 padding: 0;
1211 -moz-border-radius: 4px; 1225 -moz-border-radius: 4px;
@@ -4651,8 +4665,187 @@ h1#agenda-title { @@ -4651,8 +4665,187 @@ h1#agenda-title {
4651 } 4665 }
4652 #profile-activity li, #profile-network li, #profile-wall li { 4666 #profile-activity li, #profile-network li, #profile-wall li {
4653 display: block; 4667 display: block;
4654 - padding: 0;  
4655 - margin-bottom: 8px; 4668 + padding: 3px;
  4669 + margin-bottom: 3px;
  4670 + background-color: #fff;
  4671 + border-bottom: 1px solid #e8e8e8;
  4672 + position: relative;
  4673 +}
  4674 +
  4675 +#profile-activity li, #profile-network li, #profile-wall li {
  4676 +}
  4677 +
  4678 +.profile-activity-lead img {
  4679 + width: 124px;
  4680 + float: left;
  4681 + margin-right: 5px;
  4682 +}
  4683 +
  4684 +.profile-activity-lead {
  4685 + width: 370px;
  4686 + display: inline-block;
  4687 + text-align: left;
  4688 + margin: 5px 0;
  4689 +}
  4690 +
  4691 +.profile-activity-lead .article-name {
  4692 + font-weight: bold;
  4693 + margin-bottom: 5px;
  4694 +}
  4695 +
  4696 +.profile-activity-article-forum .profile-activity-lead {
  4697 + height: 50px;
  4698 + width: 297px;
  4699 + padding-left: 60px;
  4700 + float: none;
  4701 + overflow: hidden;
  4702 + background: transparent url(/images/forum-activity-bg.png) left center no-repeat;
  4703 +}
  4704 +
  4705 +.profile-activity-article-forum .see-forum {
  4706 + text-align: right;
  4707 +}
  4708 +
  4709 +.profile-activity-article-forum .see-forum a {
  4710 + background: transparent url(/images/forum-activity-icon.png) left center no-repeat;
  4711 + padding-left: 30px;
  4712 + font-weight: bold;
  4713 + color: #dadada !important;
  4714 + text-decoration: none;
  4715 + font-size: 11px;
  4716 +}
  4717 +
  4718 +.profile-activity-article-forum .profile-activity-lead b {
  4719 + font-weight: normal;
  4720 +}
  4721 +
  4722 +#profile-activity li a, #profile-network li a, #profile-wall li a,
  4723 +#profile-wall .profile-wall-send-reply {
  4724 + color: #333;
  4725 +}
  4726 +
  4727 +#profile-activity li a, #profile-network li a, #profile-wall li a {
  4728 + font-weight: bold;
  4729 + text-decoration: none;
  4730 +}
  4731 +
  4732 +#profile-activity li a:hover, #profile-network li a:hover, #profile-wall li a:hover {
  4733 + text-decoration: underline;
  4734 +}
  4735 +
  4736 +.profile-activity-text {
  4737 + margin: 0;
  4738 + color: #000;
  4739 +}
  4740 +
  4741 +#profile-wall li.profile-activity-item.upload_image span,
  4742 +#profile-wall li.profile-activity-item.upload_image span a,
  4743 +#profile-network li.profile-activity-item.upload_image span,
  4744 +#profile-network li.profile-activity-item.upload_image span a {
  4745 + width: 110px;
  4746 + height: 100px;
  4747 + display: block;
  4748 + overflow: hidden;
  4749 + position: absolute;
  4750 +}
  4751 +
  4752 +#profile-wall li.profile-activity-item.upload_image span a img,
  4753 +#profile-network li.profile-activity-item.upload_image span a img {
  4754 + width: 110px;
  4755 + height: 100px;
  4756 +}
  4757 +
  4758 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  4759 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a,
  4760 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a img,
  4761 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  4762 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a img {
  4763 + width: auto;
  4764 + max-width: 383px;
  4765 + height: auto;
  4766 +}
  4767 +
  4768 +#profile-wall li.profile-activity-item.upload_image span img,
  4769 +#profile-network li.profile-activity-item.upload_image span img {
  4770 + display: block;
  4771 +}
  4772 +
  4773 +#profile-wall li.profile-activity-item.upload_image span,
  4774 +#profile-network li.profile-activity-item.upload_image span {
  4775 + position: relative;
  4776 + display: inline-block;
  4777 + margin: 5px 0px 0px 5px;
  4778 +}
  4779 +
  4780 +#profile-wall li.profile-activity-item.upload_image .profile-activity-text span,
  4781 +#profile-network li.profile-activity-item.upload_image .profile-activity-text span {
  4782 + border: 4px solid #D2D2D2;
  4783 + border-radius: 4px;
  4784 + -webkit-border-radius: 4px;
  4785 + -moz-border-radius: 4px;
  4786 +}
  4787 +
  4788 +#profile-wall li.profile-activity-item.upload_image span a,
  4789 +#profile-network li.profile-activity-item.upload_image span a {
  4790 + text-indent: -5000em;
  4791 +}
  4792 +
  4793 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a,
  4794 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a {
  4795 + position: relative;
  4796 +}
  4797 +
  4798 +#profile-wall li.profile-activity-item.upload_image .article-comment span,
  4799 +#profile-wall li.profile-activity-item.upload_image .profile-wall-actions span,
  4800 +#profile-network li.profile-activity-item.upload_image .article-comment span,
  4801 +#profile-network li.profile-activity-item.upload_image .profile-wall-actions span {
  4802 + display: inline;
  4803 + position: static;
  4804 + margin: 0;
  4805 + float: none;
  4806 + width: auto;
  4807 + height: auto;
  4808 + font-weight: normal;
  4809 +}
  4810 +
  4811 +#profile-wall li.profile-activity-item ul.profile-wall-activities-comments,
  4812 +#profile-network li.profile-activity-item ul.profile-wall-activities-comments {
  4813 + margin-top: 0;
  4814 +}
  4815 +
  4816 +#profile-wall li.profile-activity-item.upload_image .profile-activity-text,
  4817 +#profile-network li.profile-activity-item.upload_image .profile-activity-text,
  4818 +#profile-network li.profile-activity-item ul.profile-wall-activities-comments {
  4819 + padding-left: 50px;
  4820 +}
  4821 +
  4822 +#profile-wall li.profile-activity-item.join_community .profile-activity-text a img,
  4823 +#profile-wall li.profile-activity-item.new_friendship .profile-activity-text a img,
  4824 +#profile-network li.profile-activity-item.join_community .profile-activity-text a img,
  4825 +#profile-network li.profile-activity-item.new_friendship .profile-activity-text a img {
  4826 + margin: 5px 5px 0 0;
  4827 + padding: 1px;
  4828 + border: 1px solid #ccc;
  4829 +}
  4830 +
  4831 +#profile-wall li.profile-activity-item.create_article,
  4832 +#profile-netowrk li.profile-activity-item.create_article {
  4833 + position: relative;
  4834 +}
  4835 +
  4836 +.profile-activity-icon {
  4837 + width: 16px;
  4838 + height: 16px;
  4839 + display: inline-block;
  4840 + position: absolute;
  4841 + top: 0px;
  4842 + right: 0px;
  4843 +}
  4844 +
  4845 +#profile-activity .profile-wall-scrap-replies li,
  4846 +#profile-network .profile-wall-scrap-replies li,
  4847 +#profile-wall .profile-wall-scrap-replies li {
  4848 + border-bottom: none;
4656 } 4849 }
4657 #profile-activity .profile-activity-image, #profile-network .profile-network-image, #profile-wall .profile-wall-image { 4850 #profile-activity .profile-activity-image, #profile-network .profile-network-image, #profile-wall .profile-wall-image {
4658 float: left; 4851 float: left;
@@ -4664,12 +4857,12 @@ h1#agenda-title { @@ -4664,12 +4857,12 @@ h1#agenda-title {
4664 } 4857 }
4665 #profile-activity .profile-activity-description, #profile-network .profile-network-description, #profile-wall .profile-wall-description { 4858 #profile-activity .profile-activity-description, #profile-network .profile-network-description, #profile-wall .profile-wall-description {
4666 float: left; 4859 float: left;
4667 - min-height: 60px; 4860 + Xmin-height: 60px;
4668 margin: 0; 4861 margin: 0;
4669 padding: 0; 4862 padding: 0;
4670 border: 1px solid #ccc; 4863 border: 1px solid #ccc;
4671 overflow: hidden; 4864 overflow: hidden;
4672 - background-color: #fff; 4865 + Xbackground-color: #fff;
4673 position: relative; 4866 position: relative;
4674 } 4867 }
4675 #profile-wall .profile-wall-description { 4868 #profile-wall .profile-wall-description {
@@ -4678,7 +4871,10 @@ h1#agenda-title { @@ -4678,7 +4871,10 @@ h1#agenda-title {
4678 #profile-activity .profile-activity-description .icon-delete span, #profile-network .profile-network-description .icon-delete span, #profile-wall .profile-wall-description .icon-delete span { 4871 #profile-activity .profile-activity-description .icon-delete span, #profile-network .profile-network-description .icon-delete span, #profile-wall .profile-wall-description .icon-delete span {
4679 display: none; 4872 display: none;
4680 } 4873 }
4681 -#profile-activity .profile-activity-description .icon-delete, #profile-network .profile-network-description .icon-delete, #profile-wall .profile-wall-description .icon-delete { 4874 +
  4875 +#profile-activity .profile-activity-description .icon-delete,
  4876 +#profile-network .profile-activity-description .icon-delete,
  4877 +#profile-wall .profile-wall-description .icon-delete {
4682 position: absolute; 4878 position: absolute;
4683 top: 4px; 4879 top: 4px;
4684 right: 4px; 4880 right: 4px;
@@ -4688,21 +4884,55 @@ h1#agenda-title { @@ -4688,21 +4884,55 @@ h1#agenda-title {
4688 -webkit-border-radius: 3px; 4884 -webkit-border-radius: 3px;
4689 -moz-border-radius: 3px; 4885 -moz-border-radius: 3px;
4690 } 4886 }
4691 -#profile-activity .profile-activity-text, #profile-network .profile-network-text, #profile-wall .profile-wall-text { 4887 +
  4888 +#profile-activity .profile-activity-text,
  4889 +#profile-network .profile-activity-text,
  4890 +#profile-wall .profile-wall-text {
4692 font-size: 13px; 4891 font-size: 13px;
4693 - margin: 5px; 4892 + margin: 2px 5px;
4694 } 4893 }
4695 #profile-wall .profile-wall-text { 4894 #profile-wall .profile-wall-text {
4696 padding-top: 0; 4895 padding-top: 0;
4697 } 4896 }
4698 -#profile-activity .profile-activity-time, #profile-network .profile-network-time, #profile-wall .profile-wall-time { 4897 +
  4898 +.profile-activities .profile-activity-time,
  4899 +#profile-network .profile-activity-time,
  4900 +#profile-wall .profile-wall-time {
4699 font-size: 11px; 4901 font-size: 11px;
4700 margin: 5px; 4902 margin: 5px;
4701 color: #babdb6; 4903 color: #babdb6;
  4904 + text-align: right;
  4905 +}
  4906 +
  4907 +#profile-wall .profile-wall-send-reply,
  4908 +.profile-activities .profile-activity-time,
  4909 +#profile-network .profile-activity-time,
  4910 +#profile-wall .profile-wall-time,
  4911 +.profile-wall-actions a {
  4912 + display: block;
  4913 + float: right;
  4914 + font-size: 10px;
  4915 + margin: 2px 0 3px 10px;
  4916 + color: #ccc;
  4917 + padding: 0;
  4918 +}
  4919 +
  4920 +#profile-wall li .profile-wall-actions a,
  4921 +#profile-activity li .profile-wall-actions a,
  4922 +#profile-network li .profile-wall-actions a,
  4923 +#profile-wall .profile-wall-send-reply a {
  4924 + text-decoration: none;
  4925 + color: #333;
  4926 + font-weight: normal;
  4927 +}
  4928 +
  4929 +#profile-wall li .profile-wall-actions a:hover,
  4930 +#profile-network li .profile-wall-actions a:hover,
  4931 +#profile-wall .profile-wall-send-reply a:hover {
  4932 + text-decoration: underline;
4702 } 4933 }
4703 #profile-activity hr, #profile-network hr, #profile-wall hr { 4934 #profile-activity hr, #profile-network hr, #profile-wall hr {
4704 - clear: both;  
4705 - border: 0; 4935 + display: none;
4706 } 4936 }
4707 #profile-activity .profile-activity-send-message, #profile-network .profile-network-send-message, #profile-wall .profile-wall-send-message { 4937 #profile-activity .profile-activity-send-message, #profile-network .profile-network-send-message, #profile-wall .profile-wall-send-message {
4708 font-size: 10px; 4938 font-size: 10px;
@@ -4762,9 +4992,13 @@ h1#agenda-title { @@ -4762,9 +4992,13 @@ h1#agenda-title {
4762 } 4992 }
4763 .profile-wall-sender, .profile-wall-time, .profile-wall-description, .profile-activity-sender, .profile-activity-time, .profile-activity-description, .profile-network-sender, .profile-network-time, .profile-network-description { 4993 .profile-wall-sender, .profile-wall-time, .profile-wall-description, .profile-activity-sender, .profile-activity-time, .profile-activity-description, .profile-network-sender, .profile-network-time, .profile-network-description {
4764 padding-left: 5px; 4994 padding-left: 5px;
  4995 + margin: 5px;
4765 } 4996 }
4766 -.profile-network-sender, .profile-wall-sender {  
4767 - margin: 2px 0; 4997 +
  4998 +.profile-network-sender,
  4999 +.profile-activity-sender,
  5000 +.profile-wall-sender {
  5001 + margin: 0;
4768 } 5002 }
4769 #profile-activity .profile-activity-time, #profile-network .profile-network-time, #profile-wall .profile-wall-time { 5003 #profile-activity .profile-activity-time, #profile-network .profile-network-time, #profile-wall .profile-wall-time {
4770 margin: 0; 5004 margin: 0;
@@ -4775,7 +5009,16 @@ h1#agenda-title { @@ -4775,7 +5009,16 @@ h1#agenda-title {
4775 padding: 2px; 5009 padding: 2px;
4776 overflow: hidden; 5010 overflow: hidden;
4777 } 5011 }
4778 -.profile-network-message, .profile-wall-message { 5012 +
  5013 +#profile-network li textarea:focus,
  5014 +#profile-wall li textarea:focus {
  5015 + background-position: left center;
  5016 + background-repeat: no-repeat;
  5017 + text-indent: 28px;
  5018 +}
  5019 +
  5020 +.profile-network-message,
  5021 +.profile-wall-message {
4779 margin: 0; 5022 margin: 0;
4780 } 5023 }
4781 .limited-text-area p { 5024 .limited-text-area p {
@@ -4801,19 +5044,24 @@ h1#agenda-title { @@ -4801,19 +5044,24 @@ h1#agenda-title {
4801 overflow: hidden; 5044 overflow: hidden;
4802 } 5045 }
4803 .profile-send-reply { 5046 .profile-send-reply {
4804 - background-color: #eee;  
4805 - border: 1px solid #aaa;  
4806 - padding: 2px;  
4807 - padding-left: 20px;  
4808 - background-repeat: no-repeat;  
4809 - background-position: 2px center; 5047 + xbackground-color: #eee;
  5048 + xborder: 1px solid #aaa;
  5049 + xpadding: 2px;
  5050 + xpadding-left: 20px;
  5051 + xbackground-repeat: no-repeat;
  5052 + xbackground-position: 2px center;
4810 color: #aaa; 5053 color: #aaa;
4811 - text-decoration: none;  
4812 - margin-left: 8px; 5054 + Xtext-decoration: none;
  5055 + Xmargin-left: 8px;
4813 } 5056 }
4814 #content .profile-send-reply:hover { 5057 #content .profile-send-reply:hover {
4815 text-decoration: none; 5058 text-decoration: none;
4816 } 5059 }
  5060 +
  5061 +#profile-wall .profile-wall-actions {
  5062 + text-align: right;
  5063 +}
  5064 +
4817 #profile-wall .profile-wall-scrap-replies .profile-wall-description { 5065 #profile-wall .profile-wall-scrap-replies .profile-wall-description {
4818 background: transparent; 5066 background: transparent;
4819 } 5067 }
@@ -4826,6 +5074,105 @@ h1#agenda-title { @@ -4826,6 +5074,105 @@ h1#agenda-title {
4826 .limited-text-area div.fieldWithErrors { 5074 .limited-text-area div.fieldWithErrors {
4827 background: transparent; 5075 background: transparent;
4828 } 5076 }
  5077 +
  5078 +#profile-wall ul.profile-wall-activities-comments,
  5079 +#profile-network ul.profile-wall-activities-comments {
  5080 + margin-top: 35px;
  5081 + padding-left: 50px;
  5082 + width: auto;
  5083 +}
  5084 +
  5085 +#profile-wall ul.profile-wall-activities-comments ul,
  5086 +#profile-network ul.profile-wall-activities-comments ul {
  5087 + padding-left: 0px;
  5088 +}
  5089 +
  5090 +#profile-wall .profile-wall-activities-comments li,
  5091 +#profile-network .profile-wall-activities-comments li {
  5092 + background: #f0f0f1;
  5093 + border-bottom: 1px solid #d2d2d2 !important;
  5094 + border-top: 1px solid #fff;
  5095 + margin-bottom: 0;
  5096 +}
  5097 +
  5098 +#profile-wall .profile-wall-activities-comments img,
  5099 +#profile-network .profile-wall-activities-comments img {
  5100 + max-width: 50px;
  5101 + max-height: 50px;
  5102 +}
  5103 +
  5104 +#profile-wall .profile-wall-activities-comments .comment_reply,
  5105 +#profile-wall .profile-wall-activities-comments h4,
  5106 +#profile-network .profile-wall-activities-comments .comment_reply,
  5107 +#profile-network .profile-wall-activities-comments h4 {
  5108 + display: none;
  5109 +}
  5110 +
  5111 +#profile-wall .profile-wall-activities-comments .comment-picture,
  5112 +#profile-network .profile-wall-activities-comments .comment-picture {
  5113 + width: 50px;
  5114 + text-align: center;
  5115 +}
  5116 +
  5117 +#profile-wall .profile-wall-activities-comments .comment-text p,
  5118 +#profile-network .profile-wall-activities-comments .comment-text p {
  5119 + margin: 0;
  5120 +}
  5121 +
  5122 +#profile-wall .profile-wall-activities-comments .profile-activity-time,
  5123 +#profile-network .profile-wall-activities-comments .profile-activity-time {
  5124 + clear: both;
  5125 +}
  5126 +
  5127 +#profile-wall .profile-wall-activities-comments .comment-details,
  5128 +#profile-network .profile-wall-activities-comments .comment-details {
  5129 + padding: 0;
  5130 +}
  5131 +
  5132 +#profile-wall .profile-wall-activities-comments .article-comment .button-bar,
  5133 +#profile-network .profile-wall-activities-comments .article-comment .button-bar {
  5134 + float: right;
  5135 + padding: 0;
  5136 + text-align: right;
  5137 + position: static;
  5138 + clear: none;
  5139 + display: none;
  5140 +}
  5141 +
  5142 +#profile-wall .profile-wall-activities-comments .article-comment:hover .button-bar,
  5143 +#profile-network .profile-wall-activities-comments .article-comment:hover .button-bar {
  5144 + display: block;
  5145 +}
  5146 +
  5147 +#profile-wall .profile-wall-activities-comments .article-comment .button-bar a.button,
  5148 +#profile-network .profile-wall-activities-comments .article-comment .button-bar a.button {
  5149 + background: transparent;
  5150 + border: 0;
  5151 + height: auto;
  5152 + line-height: auto;
  5153 + color: #333;
  5154 + text-decoration: none;
  5155 + font-size: 10px;
  5156 + padding: 0;
  5157 + margin: 0;
  5158 + display: inline;
  5159 + position: static;
  5160 + float: none;
  5161 + font-weight: normal;
  5162 +}
  5163 +
  5164 +#profile-wall .profile-wall-activities-comments .article-comment .button-bar a.button:hover,
  5165 +#profile-network .profile-wall-activities-comments .article-comment .button-bar a.button:hover {
  5166 + text-decoration: underline;
  5167 +}
  5168 +
  5169 +#profile-wall .profile-wall-activities-comments .article-comment .button-bar .button span,
  5170 +#profile-network .profile-wall-activities-comments .article-comment .button-bar .button span {
  5171 + display: inline;
  5172 + position: static;
  5173 + display: inline;
  5174 +}
  5175 +
4829 /* friends online {{{ */ 5176 /* friends online {{{ */
4830 5177
4831 #chat-online-users { 5178 #chat-online-users {
@@ -4948,15 +5295,36 @@ h1#agenda-title { @@ -4948,15 +5295,36 @@ h1#agenda-title {
4948 margin-left: 0; 5295 margin-left: 0;
4949 } 5296 }
4950 #profile-wall .comment-balloon-content { 5297 #profile-wall .comment-balloon-content {
4951 - padding: 3px 0 3px 15px; 5298 + padding: 3px 0px;
4952 } 5299 }
4953 .profile-wall-reply { 5300 .profile-wall-reply {
4954 margin: 0; 5301 margin: 0;
4955 } 5302 }
  5303 +
  5304 +.profile-wall-reply-form {
  5305 + display: block;
  5306 + background: #f0f0f1;
  5307 + border-bottom: 1px solid #d2d2d2;
  5308 + border-top: 1px solid #fff;
  5309 + margin-left: 50px;
  5310 + padding: 0 5px;
  5311 +}
  5312 +
  5313 +.scrap-replies .profile-wall-reply-form {
  5314 + margin-left: 0px;
  5315 +}
  5316 +
4956 .profile-wall-scrap-replies { 5317 .profile-wall-scrap-replies {
4957 float: right; 5318 float: right;
4958 margin-right: 2px; 5319 margin-right: 2px;
4959 } 5320 }
  5321 +
  5322 +.view-all-comments {
  5323 + clear: both;
  5324 + margin-left: 50px;
  5325 + padding-left: 20px;
  5326 +}
  5327 +
4960 /* Profile activity relative dimensions */ 5328 /* Profile activity relative dimensions */
4961 5329
4962 #leave_scrap { 5330 #leave_scrap {
@@ -4965,15 +5333,37 @@ h1#agenda-title { @@ -4965,15 +5333,37 @@ h1#agenda-title {
4965 #leave_scrap textarea { 5333 #leave_scrap textarea {
4966 width: 98%; 5334 width: 98%;
4967 } 5335 }
4968 -#profile-activity .profile-activity-image, #profile-network .profile-network-image, #profile-wall .profile-wall-image {  
4969 - width: 19%; 5336 +
  5337 +.profile-activities .profile-activity-image,
  5338 +#profile-network .profile-activity-image,
  5339 +#profile-wall .profile-wall-image {
  5340 + width: 50px;
  5341 + margin: 5px;
  5342 + float: left;
4970 } 5343 }
4971 -#profile-activity .profile-activity-description, #profile-network .profile-network-description, #profile-wall .profile-wall-description {  
4972 - width: 80%; 5344 +
  5345 +#profile-activity .profile-activity-description,
  5346 +#profile-network .profile-activity-description,
  5347 +#profile-wall .profile-wall-description {
4973 word-wrap: break-word; 5348 word-wrap: break-word;
4974 } 5349 }
4975 -#profile-wall .profile-wall-scrap-replies textarea, #profile-network textarea, #profile-wall textarea {  
4976 - width: 99%; 5350 +
  5351 +#profile-wall textarea {
  5352 + width: 375px;
  5353 +}
  5354 +
  5355 +#profile-wall li textarea {
  5356 + width: 388px;
  5357 +}
  5358 +
  5359 +#profile-wall .profile-wall-scrap-replies textarea,
  5360 +#profile-network textarea, #profile-wall textarea,
  5361 +#profile-wall li .profile-wall-reply-form textarea {
  5362 + width: 98%;
  5363 +}
  5364 +
  5365 +#profile-wall #leave_scrap textarea {
  5366 + width: 442px;
4977 } 5367 }
4978 .profile-wall-scrap-replies { 5368 .profile-wall-scrap-replies {
4979 width: 100%; 5369 width: 100%;
test/factories.rb
@@ -374,7 +374,7 @@ module Noosfero::Factory @@ -374,7 +374,7 @@ module Noosfero::Factory
374 ############################################### 374 ###############################################
375 375
376 def defaults_for_scrap(params = {}) 376 def defaults_for_scrap(params = {})
377 - { :content => 'soment content ', :sender_id => 1, :receiver_id => 1, :created_at => DateTime.now }.merge(params) 377 + { :content => 'some content ', :sender_id => 1, :receiver_id => 1, :created_at => DateTime.now }.merge(params)
378 end 378 end
379 379
380 ############################################### 380 ###############################################
@@ -442,7 +442,7 @@ module Noosfero::Factory @@ -442,7 +442,7 @@ module Noosfero::Factory
442 442
443 def defaults_for_comment(params = {}) 443 def defaults_for_comment(params = {})
444 name = "comment_#{rand(1000)}" 444 name = "comment_#{rand(1000)}"
445 - { :title => name, :body => "my own comment", :article_id => 1 }.merge(params) 445 + { :title => name, :body => "my own comment", :source_id => 1 }.merge(params)
446 end 446 end
447 447
448 ############################################### 448 ###############################################
test/functional/profile_controller_test.rb
@@ -714,25 +714,23 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -714,25 +714,23 @@ class ProfileControllerTest &lt; ActionController::TestCase
714 assert_no_tag :tag => 'p', :content => 'A scrap' 714 assert_no_tag :tag => 'p', :content => 'A scrap'
715 end 715 end
716 716
717 - should 'see all activities of the current profile' do  
718 - p1= Person.first 717 + should 'not display activities of the current profile when he is not followed by the viewer' do
  718 + p1= fast_create(Person)
719 p2= fast_create(Person) 719 p2= fast_create(Person)
720 - assert !p1.is_a_friend?(p2)  
721 - p3= fast_create(Person)  
722 - assert !p1.is_a_friend?(p3)  
723 - ActionTracker::Record.destroy_all  
724 - Scrap.create!(defaults_for_scrap(:sender => p1, :receiver => p1))  
725 - a1 = ActionTracker::Record.last 720 +
  721 + UserStampSweeper.any_instance.stubs(:current_user).returns(p1)
  722 + scrap1 = Scrap.create!(defaults_for_scrap(:sender => p1, :receiver => p2))
  723 +
726 UserStampSweeper.any_instance.stubs(:current_user).returns(p2) 724 UserStampSweeper.any_instance.stubs(:current_user).returns(p2)
727 - Scrap.create!(defaults_for_scrap(:sender => p2, :receiver => p3))  
728 - a2 = ActionTracker::Record.last  
729 - UserStampSweeper.any_instance.stubs(:current_user).returns(p3)  
730 - Scrap.create!(defaults_for_scrap(:sender => p3, :receiver => p1))  
731 - a3 = ActionTracker::Record.last 725 + scrap2 = Scrap.create!(defaults_for_scrap(:sender => p2, :receiver => p1))
  726 +
  727 + UserStampSweeper.any_instance.stubs(:current_user).returns(p1)
  728 + TinyMceArticle.create!(:profile => p1, :name => 'An article about free software')
  729 + a1 = ActionTracker::Record.last
  730 +
732 login_as(profile.identifier) 731 login_as(profile.identifier)
733 get :index, :profile => p1.identifier 732 get :index, :profile => p1.identifier
734 - assert_not_nil assigns(:activities)  
735 - assert_equal [a1], assigns(:activities) 733 + assert_nil assigns(:activities)
736 end 734 end
737 735
738 should 'see the activities_items paginated' do 736 should 'see the activities_items paginated' do
@@ -744,26 +742,27 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -744,26 +742,27 @@ class ProfileControllerTest &lt; ActionController::TestCase
744 assert_equal 30, assigns(:activities).count 742 assert_equal 30, assigns(:activities).count
745 end 743 end
746 744
747 - should 'see not see the friends activities in the current profile activity' do  
748 - p1= Person.first 745 + should 'not see the friends activities in the current profile' do
749 p2= fast_create(Person) 746 p2= fast_create(Person)
750 - assert !p1.is_a_friend?(p2) 747 + assert !profile.is_a_friend?(p2)
751 p3= fast_create(Person) 748 p3= fast_create(Person)
752 - p1.add_friend(p3)  
753 - assert p1.is_a_friend?(p3) 749 + p3.add_friend(profile)
  750 + assert p3.is_a_friend?(profile)
754 ActionTracker::Record.destroy_all 751 ActionTracker::Record.destroy_all
755 - Scrap.create!(defaults_for_scrap(:sender => p1, :receiver => p1))  
756 - a1 = ActionTracker::Record.last  
757 - UserStampSweeper.any_instance.stubs(:current_user).returns(p2)  
758 - Scrap.create!(defaults_for_scrap(:sender => p2, :receiver => p3))  
759 - a2 = ActionTracker::Record.last 752 +
  753 + scrap1 = Scrap.create!(defaults_for_scrap(:sender => p2, :receiver => p3))
  754 + scrap2 = Scrap.create!(defaults_for_scrap(:sender => p2, :receiver => profile))
  755 +
760 UserStampSweeper.any_instance.stubs(:current_user).returns(p3) 756 UserStampSweeper.any_instance.stubs(:current_user).returns(p3)
761 - Scrap.create!(defaults_for_scrap(:sender => p3, :receiver => p1))  
762 - a3 = ActionTracker::Record.last 757 + article1 = TinyMceArticle.create!(:profile => p3, :name => 'An article about free software')
  758 +
  759 + UserStampSweeper.any_instance.stubs(:current_user).returns(p2)
  760 + article2 = TinyMceArticle.create!(:profile => p2, :name => 'Another article about free software')
  761 +
763 login_as(profile.identifier) 762 login_as(profile.identifier)
764 - get :index, :profile => p1.identifier 763 + get :index, :profile => p3.identifier
765 assert_not_nil assigns(:activities) 764 assert_not_nil assigns(:activities)
766 - assert_equal [a1], assigns(:activities) 765 + assert_equivalent [scrap1, article1.activity], assigns(:activities).map { |a| a.klass.constantize.find(a.id) }
767 end 766 end
768 767
769 should 'see all the activities in the current profile network' do 768 should 'see all the activities in the current profile network' do
@@ -931,13 +930,29 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -931,13 +930,29 @@ class ProfileControllerTest &lt; ActionController::TestCase
931 assert_template 'index' 930 assert_template 'index'
932 end 931 end
933 932
934 - should 'have wall_itens defined' do  
935 - p1= ActionTracker::Record.current_user_from_model 933 + should 'not have activities defined if not logged in' do
  934 + p1= fast_create(Person)
  935 + get :index, :profile => p1.identifier
  936 + assert_nil assigns(:actvities)
  937 + end
  938 +
  939 + should 'not have activities defined if logged in but is not following profile' do
  940 + login_as(profile.identifier)
  941 + p1= fast_create(Person)
936 get :index, :profile => p1.identifier 942 get :index, :profile => p1.identifier
937 - assert_equal [], assigns(:wall_items) 943 + assert_nil assigns(:activities)
938 end 944 end
939 945
940 - should 'the wall_itens be the received scraps in people profile' do 946 + should 'have activities defined if logged in and is following profile' do
  947 + login_as(profile.identifier)
  948 + p1= fast_create(Person)
  949 + p1.add_friend(profile)
  950 + ActionTracker::Record.destroy_all
  951 + get :index, :profile => p1.identifier
  952 + assert_equal [], assigns(:activities)
  953 + end
  954 +
  955 + should 'the activities be the received scraps in people profile' do
941 p1 = ActionTracker::Record.current_user_from_model 956 p1 = ActionTracker::Record.current_user_from_model
942 p2 = fast_create(Person) 957 p2 = fast_create(Person)
943 p3 = fast_create(Person) 958 p3 = fast_create(Person)
@@ -952,10 +967,10 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -952,10 +967,10 @@ class ProfileControllerTest &lt; ActionController::TestCase
952 @controller.stubs(:current_user).returns(user) 967 @controller.stubs(:current_user).returns(user)
953 Person.any_instance.stubs(:follows?).returns(true) 968 Person.any_instance.stubs(:follows?).returns(true)
954 get :index, :profile => p1.identifier 969 get :index, :profile => p1.identifier
955 - assert_equal [s2,s3], assigns(:wall_items) 970 + assert_equal [s2,s3], assigns(:activities)
956 end 971 end
957 972
958 - should 'the wall_itens be the received scraps in community profile' do 973 + should 'the activities be the received scraps in community profile' do
959 c = fast_create(Community) 974 c = fast_create(Community)
960 p1 = fast_create(Person) 975 p1 = fast_create(Person)
961 p2 = fast_create(Person) 976 p2 = fast_create(Person)
@@ -971,12 +986,12 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -971,12 +986,12 @@ class ProfileControllerTest &lt; ActionController::TestCase
971 @controller.stubs(:current_user).returns(user) 986 @controller.stubs(:current_user).returns(user)
972 Person.any_instance.stubs(:follows?).returns(true) 987 Person.any_instance.stubs(:follows?).returns(true)
973 get :index, :profile => c.identifier 988 get :index, :profile => c.identifier
974 - assert_equal [s2,s3], assigns(:wall_items) 989 + assert_equal [s2,s3], assigns(:activities)
975 end 990 end
976 991
977 - should 'the wall_itens be paginated in people profiles' do 992 + should 'the activities be paginated in people profiles' do
978 p1 = Person.first 993 p1 = Person.first
979 - 40.times{fast_create(Scrap, :sender_id => p1.id)} 994 + 40.times{fast_create(Scrap, :sender_id => p1.id, :created_at => Time.now)}
980 995
981 @controller.stubs(:logged_in?).returns(true) 996 @controller.stubs(:logged_in?).returns(true)
982 user = mock() 997 user = mock()
@@ -986,10 +1001,10 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -986,10 +1001,10 @@ class ProfileControllerTest &lt; ActionController::TestCase
986 Person.any_instance.stubs(:follows?).returns(true) 1001 Person.any_instance.stubs(:follows?).returns(true)
987 assert_equal 40, p1.scraps_received.not_replies.count 1002 assert_equal 40, p1.scraps_received.not_replies.count
988 get :index, :profile => p1.identifier 1003 get :index, :profile => p1.identifier
989 - assert_equal 30, assigns(:wall_items).count 1004 + assert_equal 30, assigns(:activities).count
990 end 1005 end
991 1006
992 - should 'the wall_itens be paginated in community profiles' do 1007 + should 'the activities be paginated in community profiles' do
993 p1 = Person.first 1008 p1 = Person.first
994 c = fast_create(Community) 1009 c = fast_create(Community)
995 40.times{fast_create(Scrap, :receiver_id => c.id)} 1010 40.times{fast_create(Scrap, :receiver_id => c.id)}
@@ -1002,7 +1017,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -1002,7 +1017,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
1002 Person.any_instance.stubs(:follows?).returns(true) 1017 Person.any_instance.stubs(:follows?).returns(true)
1003 assert_equal 40, c.scraps_received.not_replies.count 1018 assert_equal 40, c.scraps_received.not_replies.count
1004 get :index, :profile => c.identifier 1019 get :index, :profile => c.identifier
1005 - assert_equal 30, assigns(:wall_items).count 1020 + assert_equal 30, assigns(:activities).count
1006 end 1021 end
1007 1022
1008 should "the owner of activity could remove it" do 1023 should "the owner of activity could remove it" do
@@ -1072,17 +1087,17 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -1072,17 +1087,17 @@ class ProfileControllerTest &lt; ActionController::TestCase
1072 end 1087 end
1073 end 1088 end
1074 1089
1075 - should "not show the scrap button on network activity if the user don't follow the user" do 1090 + should "not show the network activity if the viewer don't follow the profile" do
1076 login_as(profile.identifier) 1091 login_as(profile.identifier)
1077 person = fast_create(Person) 1092 person = fast_create(Person)
1078 at = fast_create(ActionTracker::Record, :user_id => person.id) 1093 at = fast_create(ActionTracker::Record, :user_id => person.id)
1079 atn = fast_create(ActionTrackerNotification, :profile_id => profile.id, :action_tracker_id => at.id) 1094 atn = fast_create(ActionTrackerNotification, :profile_id => profile.id, :action_tracker_id => at.id)
1080 - get :index, :profile => profile.identifier  
1081 - assert_no_tag :tag => 'p', :attributes => {:class => 'profile-network-send-message'} 1095 + get :index, :profile => person.identifier
  1096 + assert_no_tag :tag => 'div', :attributes => {:id => 'profile-network'}
1082 1097
1083 person.add_friend(profile) 1098 person.add_friend(profile)
1084 - get :index, :profile => profile.identifier  
1085 - assert_tag :tag => 'p', :attributes => {:class => 'profile-network-send-message'} 1099 + get :index, :profile => person.identifier
  1100 + assert_tag :tag => 'div', :attributes => {:id => 'profile-network'}
1086 end 1101 end
1087 1102
1088 should "not show the scrap button on network activity if the user is himself" do 1103 should "not show the scrap button on network activity if the user is himself" do
@@ -1093,16 +1108,16 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -1093,16 +1108,16 @@ class ProfileControllerTest &lt; ActionController::TestCase
1093 assert_no_tag :tag => 'p', :attributes => {:class => 'profile-network-send-message'} 1108 assert_no_tag :tag => 'p', :attributes => {:class => 'profile-network-send-message'}
1094 end 1109 end
1095 1110
1096 - should "not show the scrap button on wall activity if the user don't follow the user" do 1111 + should "not show the scrap area on wall if the user don't follow the user" do
1097 login_as(profile.identifier) 1112 login_as(profile.identifier)
1098 person = fast_create(Person) 1113 person = fast_create(Person)
1099 scrap = fast_create(Scrap, :sender_id => person.id, :receiver_id => profile.id) 1114 scrap = fast_create(Scrap, :sender_id => person.id, :receiver_id => profile.id)
1100 - get :index, :profile => profile.identifier  
1101 - assert_no_tag :tag => 'p', :attributes => {:class => 'profile-wall-send-message'} 1115 + get :index, :profile => person.identifier
  1116 + assert_no_tag :tag => 'div', :attributes => {:id => 'leave_scrap'}, :descendant => { :tag => 'input', :attributes => {:value => 'Share'} }
1102 1117
1103 person.add_friend(profile) 1118 person.add_friend(profile)
1104 - get :index, :profile => profile.identifier  
1105 - assert_tag :tag => 'p', :attributes => {:class => 'profile-wall-send-message'} 1119 + get :index, :profile => person.identifier
  1120 + assert_tag :tag => 'div', :attributes => {:id => 'leave_scrap'}, :descendant => { :tag => 'input', :attributes => {:value => 'Share'} }
1106 end 1121 end
1107 1122
1108 should "not show the scrap button on wall activity if the user is himself" do 1123 should "not show the scrap button on wall activity if the user is himself" do
@@ -1158,7 +1173,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -1158,7 +1173,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
1158 assert_equal 40, profile.tracked_actions.count 1173 assert_equal 40, profile.tracked_actions.count
1159 get :view_more_activities, :profile => profile.identifier, :page => 2 1174 get :view_more_activities, :profile => profile.identifier, :page => 2
1160 assert_response :success 1175 assert_response :success
1161 - assert_template '_profile_activities' 1176 + assert_template '_profile_activities_list'
1162 assert_equal 10, assigns(:activities).count 1177 assert_equal 10, assigns(:activities).count
1163 end 1178 end
1164 1179
@@ -1247,4 +1262,70 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -1247,4 +1262,70 @@ class ProfileControllerTest &lt; ActionController::TestCase
1247 post :register_report, :profile => reported.identifier, :abuse_report => {:reason => 'some reason'} 1262 post :register_report, :profile => reported.identifier, :abuse_report => {:reason => 'some reason'}
1248 end 1263 end
1249 end 1264 end
  1265 +
  1266 + should 'display activities and scraps together' do
  1267 + another_person = fast_create(Person)
  1268 + Scrap.create!(defaults_for_scrap(:sender => another_person, :receiver => profile, :content => 'A scrap'))
  1269 +
  1270 + UserStampSweeper.any_instance.stubs(:current_user).returns(profile)
  1271 + ActionTracker::Record.destroy_all
  1272 + TinyMceArticle.create!(:profile => profile, :name => 'An article about free software')
  1273 +
  1274 + login_as(profile.identifier)
  1275 + get :index, :profile => profile.identifier
  1276 +
  1277 + assert_tag :tag => 'p', :content => 'A scrap', :attributes => { :class => 'profile-activity-text'}
  1278 + assert_tag :tag => 'div', :attributes => { :class => 'profile-activity-lead' }, :descendant => { :tag => 'a', :content => 'An article about free software' }
  1279 + end
  1280 +
  1281 + should 'have scraps and activities on activities' do
  1282 + another_person = fast_create(Person)
  1283 + scrap = Scrap.create!(defaults_for_scrap(:sender => another_person, :receiver => profile, :content => 'A scrap'))
  1284 +
  1285 + UserStampSweeper.any_instance.stubs(:current_user).returns(profile)
  1286 + ActionTracker::Record.destroy_all
  1287 + TinyMceArticle.create!(:profile => profile, :name => 'An article about free software')
  1288 + activity = ActionTracker::Record.last
  1289 +
  1290 + login_as(profile.identifier)
  1291 + get :index, :profile => profile.identifier
  1292 +
  1293 + assert_equivalent [scrap,activity], assigns(:activities).map {|a| a.klass.constantize.find(a.id)}
  1294 + end
  1295 +
  1296 + should "be logged in to leave comment on an activity" do
  1297 + article = TinyMceArticle.create!(:profile => profile, :name => 'An article about free software')
  1298 + activity = ActionTracker::Record.last
  1299 + count = activity.comments.count
  1300 +
  1301 + post :leave_comment_on_activity, :profile => profile.identifier, :comment => {:body => 'something', :source_id => activity.id}
  1302 + assert_equal count, activity.comments.count
  1303 + assert_redirected_to :controller => 'account', :action => 'login'
  1304 + end
  1305 +
  1306 + should "leave a comment in own activity" do
  1307 + login_as(profile.identifier)
  1308 + TinyMceArticle.create!(:profile => profile, :name => 'An article about free software')
  1309 + activity = ActionTracker::Record.last
  1310 + count = activity.comments.count
  1311 +
  1312 + assert_equal 0, count
  1313 + post :leave_comment_on_activity, :profile => profile.identifier, :comment => {:body => 'something'}, :source_id => activity.id
  1314 + assert_equal count + 1, ActionTracker::Record.find(activity.id).comments_count
  1315 + assert_response :success
  1316 + assert_equal "Comment successfully added.", assigns(:message)
  1317 + end
  1318 +
  1319 + should "leave a comment on another profile's activity" do
  1320 + login_as(profile.identifier)
  1321 + another_person = fast_create(Person)
  1322 + TinyMceArticle.create!(:profile => another_person, :name => 'An article about free software')
  1323 + activity = ActionTracker::Record.last
  1324 + count = activity.comments.count
  1325 + assert_equal 0, count
  1326 + post :leave_comment_on_activity, :profile => another_person.identifier, :comment => {:body => 'something'}, :source_id => activity.id
  1327 + assert_equal count + 1, ActionTracker::Record.find(activity.id).comments_count
  1328 + assert_response :success
  1329 + assert_equal "Comment successfully added.", assigns(:message)
  1330 + end
1250 end 1331 end
test/unit/action_tracker_notification_test.rb
@@ -76,4 +76,28 @@ class ActionTrackerNotificationTest &lt; ActiveSupport::TestCase @@ -76,4 +76,28 @@ class ActionTrackerNotificationTest &lt; ActiveSupport::TestCase
76 assert_equal [last_notification], at.action_tracker_notifications 76 assert_equal [last_notification], at.action_tracker_notifications
77 end 77 end
78 78
  79 + should "have comments through action_tracker" do
  80 + person = fast_create(Person)
  81 + community = fast_create(Community)
  82 + community.add_member(person)
  83 + activity = ActionTracker::Record.last
  84 + process_delayed_job_queue
  85 + notification = ActionTrackerNotification.last
  86 +
  87 + comment = create(Comment, :source => activity, :author => person)
  88 +
  89 + assert_equal activity.comments, notification.comments
  90 + end
  91 +
  92 + should "have comments through article action_tracker" do
  93 + person = fast_create(Person)
  94 + article = create(TextileArticle, :profile_id => person.id)
  95 + process_delayed_job_queue
  96 + notification = ActionTrackerNotification.last
  97 +
  98 + comment = create(Comment, :source => article, :author => person)
  99 +
  100 + assert_equal article.activity.comments, notification.comments
  101 + end
  102 +
79 end 103 end
test/unit/approve_article_test.rb
@@ -251,7 +251,7 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase @@ -251,7 +251,7 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase
251 assert_equal 1, ActionTracker::Record.count 251 assert_equal 1, ActionTracker::Record.count
252 end 252 end
253 253
254 - should 'notify with different trackers activity create with different targets' do 254 + should 'not group trackers activity of article\'s creation' do
255 ActionTracker::Record.delete_all 255 ActionTracker::Record.delete_all
256 256
257 article = fast_create(TextileArticle) 257 article = fast_create(TextileArticle)
@@ -261,28 +261,15 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase @@ -261,28 +261,15 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase
261 article = fast_create(TextileArticle) 261 article = fast_create(TextileArticle)
262 a = ApproveArticle.create!(:name => 'another bar', :article => article, :target => community, :requestor => profile) 262 a = ApproveArticle.create!(:name => 'another bar', :article => article, :target => community, :requestor => profile)
263 a.finish 263 a.finish
264 - assert_equal 1, ActionTracker::Record.count  
265 264
266 article = fast_create(TextileArticle) 265 article = fast_create(TextileArticle)
267 other_community = fast_create(Community) 266 other_community = fast_create(Community)
268 a = ApproveArticle.create!(:name => 'another bar', :article => article, :target => other_community, :requestor => profile) 267 a = ApproveArticle.create!(:name => 'another bar', :article => article, :target => other_community, :requestor => profile)
269 a.finish 268 a.finish
270 - assert_equal 2, ActionTracker::Record.count  
271 - end  
272 -  
273 - should 'notify activity on update' do  
274 - ActionTracker::Record.delete_all  
275 - a = ApproveArticle.create!(:name => 'bar', :article => article, :target => community, :requestor => profile)  
276 - a.finish  
277 - assert_equal 1, ActionTracker::Record.count  
278 -  
279 - published = article.class.last  
280 - published.name = 'foo'  
281 - published.save!  
282 - assert_equal 2, ActionTracker::Record.count 269 + assert_equal 3, ActionTracker::Record.count
283 end 270 end
284 271
285 - should 'notify with different trackers activity update with different targets' do 272 + should 'not create trackers activity when updating articles' do
286 ActionTracker::Record.delete_all 273 ActionTracker::Record.delete_all
287 article1 = fast_create(TextileArticle) 274 article1 = fast_create(TextileArticle)
288 a = ApproveArticle.create!(:name => 'bar', :article => article1, :target => community, :requestor => profile) 275 a = ApproveArticle.create!(:name => 'bar', :article => article1, :target => community, :requestor => profile)
@@ -294,16 +281,16 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase @@ -294,16 +281,16 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase
294 a.finish 281 a.finish
295 assert_equal 2, ActionTracker::Record.count 282 assert_equal 2, ActionTracker::Record.count
296 283
297 - published = article1.class.last  
298 - published.name = 'foo';published.save!  
299 - assert_equal 3, ActionTracker::Record.count  
300 -  
301 - published = article2.class.last  
302 - published.name = 'another foo';published.save!  
303 - assert_equal 4, ActionTracker::Record.count 284 + assert_no_difference ActionTracker::Record, :count do
  285 + published = article1.class.last
  286 + published.name = 'foo';published.save!
  287 +
  288 + published = article2.class.last
  289 + published.name = 'another foo';published.save!
  290 + end
304 end 291 end
305 292
306 - should "the tracker action target be defined as Community by custom_target method on articles'creation in communities" do 293 + should "the tracker action target be defined as the article on articles'creation in communities" do
307 ActionTracker::Record.delete_all 294 ActionTracker::Record.delete_all
308 person = fast_create(Person) 295 person = fast_create(Person)
309 community.add_member(person) 296 community.add_member(person)
@@ -311,17 +298,21 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase @@ -311,17 +298,21 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase
311 a = ApproveArticle.create!(:article => article, :target => community, :requestor => profile) 298 a = ApproveArticle.create!(:article => article, :target => community, :requestor => profile)
312 a.finish 299 a.finish
313 300
314 - assert_equal Community, ActionTracker::Record.last.target.class 301 + approved_article = community.articles.find_by_name(article.name)
  302 +
  303 + assert_equal approved_article, ActionTracker::Record.last.target
315 end 304 end
316 305
317 - should "the tracker action target be defined as person by custom_target method on articles'creation in profile" do 306 + should "the tracker action target be defined as the article on articles'creation in profile" do
318 ActionTracker::Record.delete_all 307 ActionTracker::Record.delete_all
319 person = fast_create(Person) 308 person = fast_create(Person)
320 309
321 a = ApproveArticle.create!(:article => article, :target => person, :requestor => profile) 310 a = ApproveArticle.create!(:article => article, :target => person, :requestor => profile)
322 a.finish 311 a.finish
323 312
324 - assert_equal Person, ActionTracker::Record.last.target.class 313 + approved_article = person.articles.find_by_name(article.name)
  314 +
  315 + assert_equal approved_article, ActionTracker::Record.last.target
325 end 316 end
326 317
327 should "have the same is_trackable method as original article" do 318 should "have the same is_trackable method as original article" do
test/unit/article_test.rb
@@ -322,15 +322,16 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -322,15 +322,16 @@ class ArticleTest &lt; ActiveSupport::TestCase
322 322
323 should 'list most commented articles' do 323 should 'list most commented articles' do
324 Article.delete_all 324 Article.delete_all
  325 + (1..4).each do |n|
  326 + create(TextileArticle, :name => "art #{n}", :profile_id => profile.id)
  327 + end
  328 + first_article = profile.articles.first
  329 + 2.times { Comment.create(:title => 'test', :body => 'asdsad', :author => profile, :source => first_article).save! }
325 330
326 - person = create_user('testuser').person  
327 - articles = (1..4).map {|n| a = person.articles.build(:name => "art #{n}"); a.save!; a }  
328 -  
329 - 2.times { articles[0].comments.build(:title => 'test', :body => 'asdsad', :author => person).save! }  
330 - 4.times { articles[1].comments.build(:title => 'test', :body => 'asdsad', :author => person).save! }  
331 - 331 + last_article = profile.articles.last
  332 + 4.times { Comment.create(:title => 'test', :body => 'asdsad', :author => profile, :source => last_article).save! }
332 # should respect the order (more commented comes first) 333 # should respect the order (more commented comes first)
333 - assert_equal [articles[1], articles[0]], person.articles.most_commented(2) 334 + assert_equal [last_article, first_article], profile.articles.most_commented(2)
334 end 335 end
335 336
336 should 'identify itself as a non-folder' do 337 should 'identify itself as a non-folder' do
@@ -365,8 +366,8 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -365,8 +366,8 @@ class ArticleTest &lt; ActiveSupport::TestCase
365 should 'index comments title together with article' do 366 should 'index comments title together with article' do
366 TestSolr.enable 367 TestSolr.enable
367 owner = create_user('testuser').person 368 owner = create_user('testuser').person
368 - art = owner.articles.build(:name => 'ytest'); art.save!  
369 - c1 = art.comments.build(:title => 'a nice comment', :body => 'anything', :author => owner); c1.save! 369 + art = fast_create(TinyMceArticle, :profile_id => owner.id, :name => 'ytest')
  370 + c1 = Comment.create(:title => 'a nice comment', :body => 'anything', :author => owner, :source => art ); c1.save!
370 371
371 assert_includes Article.find_by_contents('nice')[:results], art 372 assert_includes Article.find_by_contents('nice')[:results], art
372 end 373 end
@@ -374,8 +375,8 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -374,8 +375,8 @@ class ArticleTest &lt; ActiveSupport::TestCase
374 should 'index comments body together with article' do 375 should 'index comments body together with article' do
375 TestSolr.enable 376 TestSolr.enable
376 owner = create_user('testuser').person 377 owner = create_user('testuser').person
377 - art = owner.articles.build(:name => 'ytest'); art.save!  
378 - c1 = art.comments.build(:title => 'test comment', :body => 'anything', :author => owner); c1.save! 378 + art = fast_create(TinyMceArticle, :profile_id => owner.id, :name => 'ytest')
  379 + c1 = Comment.create(:title => 'test comment', :body => 'anything', :author => owner, :source => art); c1.save!
379 380
380 assert_includes Article.find_by_contents('anything')[:results], art 381 assert_includes Article.find_by_contents('anything')[:results], art
381 end 382 end
@@ -953,79 +954,34 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -953,79 +954,34 @@ class ArticleTest &lt; ActiveSupport::TestCase
953 end 954 end
954 955
955 should 'track action when a published article is created outside a community' do 956 should 'track action when a published article is created outside a community' do
956 - article = TinyMceArticle.create! :name => 'Tracked Article', :profile_id => profile.id  
957 - assert article.published?  
958 - assert_kind_of Person, article.profile  
959 - ta = ActionTracker::Record.last  
960 - assert_equal 'Tracked Article', ta.get_name.last  
961 - assert_equal article.url, ta.get_url.last  
962 - assert_kind_of Person, ta.user  
963 - ta.created_at = Time.now.ago(26.hours); ta.save!  
964 - article = TinyMceArticle.create! :name => 'Another Tracked Article', :profile_id => profile.id  
965 - ta = ActionTracker::Record.last  
966 - assert_equal ['Another Tracked Article'], ta.get_name  
967 - assert_equal [article.url], ta.get_url 957 + article = create(TinyMceArticle, :profile_id => profile.id)
  958 + ta = article.activity
  959 + assert_equal article.name, ta.get_name
  960 + assert_equal article.url, ta.get_url
968 end 961 end
969 962
970 should 'track action when a published article is created in a community' do 963 should 'track action when a published article is created in a community' do
971 community = fast_create(Community) 964 community = fast_create(Community)
972 - p1 = ActionTracker::Record.current_user_from_model 965 + p1 = fast_create(Person)
973 p2 = fast_create(Person) 966 p2 = fast_create(Person)
974 p3 = fast_create(Person) 967 p3 = fast_create(Person)
975 community.add_member(p1) 968 community.add_member(p1)
976 community.add_member(p2) 969 community.add_member(p2)
977 - assert p1.is_member_of?(community)  
978 - assert p2.is_member_of?(community)  
979 - assert !p3.is_member_of?(community)  
980 - Article.destroy_all  
981 - ActionTracker::Record.destroy_all  
982 - article = TinyMceArticle.create! :name => 'Tracked Article', :profile_id => community.id  
983 - assert article.published?  
984 - assert_kind_of Community, article.profile  
985 - ta = ActionTracker::Record.last  
986 - assert_equal 'Tracked Article', ta.get_name.last  
987 - assert_equal article.url, ta.get_url.last  
988 - assert_kind_of Person, ta.user 970 + UserStampSweeper.any_instance.expects(:current_user).returns(p1).at_least_once
  971 +
  972 + article = create(TinyMceArticle, :profile_id => community.id)
  973 + activity = article.activity
  974 +
989 process_delayed_job_queue 975 process_delayed_job_queue
990 - assert_equal 3, ActionTrackerNotification.count  
991 - ActionTrackerNotification.all.map{|a|a.profile}.map do |profile|  
992 - assert [p1,p2,community].include?(profile)  
993 - end 976 + assert_equal 3, ActionTrackerNotification.find_all_by_action_tracker_id(activity.id).count
  977 + assert_equivalent [p1,p2,community], ActionTrackerNotification.find_all_by_action_tracker_id(activity.id).map(&:profile)
994 end 978 end
995 979
996 - should 'track action when a published article is updated' do  
997 - a = TinyMceArticle.create! :name => 'a', :profile_id => profile.id  
998 - a.update_attributes! :name => 'b'  
999 - ta = ActionTracker::Record.last  
1000 - assert_equal ['b'], ta.get_name  
1001 - assert_equal [a.reload.url], ta.get_url  
1002 - a.update_attributes! :name => 'c'  
1003 - ta = ActionTracker::Record.last  
1004 - assert_equal ['b','c'], ta.get_name  
1005 - assert_equal [a.url,a.reload.url], ta.get_url  
1006 - a.update_attributes! :body => 'test'  
1007 - ta = ActionTracker::Record.last  
1008 - assert_equal ['b','c','c'], ta.get_name  
1009 - assert_equal [a.url,a.reload.url,a.reload.url], ta.get_url  
1010 - a.update_attributes! :hits => 50  
1011 - ta = ActionTracker::Record.last  
1012 - assert_equal ['b','c','c'], ta.get_name  
1013 - assert_equal [a.url,a.reload.url,a.reload.url], ta.get_url  
1014 - end  
1015 -  
1016 - should 'track action when a published article is removed' do  
1017 - a = TinyMceArticle.create! :name => 'a', :profile_id => profile.id  
1018 - a.destroy  
1019 - ta = ActionTracker::Record.last  
1020 - assert_equal ['a'], ta.get_name  
1021 - a = TinyMceArticle.create! :name => 'b', :profile_id => profile.id  
1022 - a.destroy  
1023 - ta = ActionTracker::Record.last  
1024 - assert_equal ['a','b'], ta.get_name  
1025 - a = TinyMceArticle.create! :name => 'c', :profile_id => profile.id, :published => false  
1026 - a.destroy  
1027 - ta = ActionTracker::Record.last  
1028 - assert_equal ['a','b'], ta.get_name 980 + should 'not track action when a published article is removed' do
  981 + a = create(TinyMceArticle, :profile_id => profile.id)
  982 + assert_no_difference ActionTracker::Record, :count do
  983 + a.destroy
  984 + end
1029 end 985 end
1030 986
1031 should 'notifiable is false by default' do 987 should 'notifiable is false by default' do
@@ -1054,6 +1010,15 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1054,6 +1010,15 @@ class ArticleTest &lt; ActiveSupport::TestCase
1054 assert_equal 0, ActionTracker::Record.count 1010 assert_equal 0, ActionTracker::Record.count
1055 end 1011 end
1056 1012
  1013 + should 'create activity' do
  1014 + a = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
  1015 + a.activity.destroy
  1016 + assert_nil a.activity
  1017 +
  1018 + a.create_activity
  1019 + assert_not_nil a.activity
  1020 + end
  1021 +
1057 should "the action_tracker_target method be defined" do 1022 should "the action_tracker_target method be defined" do
1058 assert Article.method_defined?(:action_tracker_target) 1023 assert Article.method_defined?(:action_tracker_target)
1059 end 1024 end
@@ -1090,141 +1055,64 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1090,141 +1055,64 @@ class ArticleTest &lt; ActiveSupport::TestCase
1090 assert_equal false, a.is_trackable? 1055 assert_equal false, a.is_trackable?
1091 end 1056 end
1092 1057
1093 - should 'not create more than one notification track action to community when update more than one artile' do  
1094 - community = fast_create(Community)  
1095 - p1 = Person.first || fast_create(Person)  
1096 - community.add_member(p1)  
1097 - assert p1.is_member_of?(community)  
1098 - Article.destroy_all  
1099 - ActionTracker::Record.destroy_all  
1100 - article = TinyMceArticle.create! :name => 'Tracked Article 1', :profile_id => community.id  
1101 - assert article.published?  
1102 - assert_kind_of Community, article.profile  
1103 - assert_equal 1, ActionTracker::Record.count  
1104 - ta = ActionTracker::Record.last  
1105 - assert_equal 'Tracked Article 1', ta.get_name.last  
1106 - assert_equal article.url, ta.get_url.last  
1107 - assert p1, ta.user  
1108 - assert community, ta.target  
1109 - process_delayed_job_queue  
1110 - assert_equal 2, ActionTrackerNotification.count  
1111 -  
1112 - article = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => community.id  
1113 - assert article.published?  
1114 - assert_kind_of Community, article.profile  
1115 - assert_equal 1, ActionTracker::Record.count  
1116 - ta = ActionTracker::Record.last  
1117 - assert_equal 'Tracked Article 2', ta.get_name.last  
1118 - assert_equal article.url, ta.get_url.last  
1119 - assert_equal p1, ta.user  
1120 - assert_equal community, ta.target  
1121 - process_delayed_job_queue  
1122 - assert_equal 2, ActionTrackerNotification.count 1058 + should "not be trackable if article is inside a private community" do
  1059 + private_community = fast_create(Community, :public_profile => false)
  1060 + a = fast_create(TinyMceArticle, :profile_id => private_community.id)
  1061 + assert_equal false, a.is_trackable?
1123 end 1062 end
1124 1063
1125 - should 'create the notification to the member when one member has the notification and the other no' do 1064 + should 'create the notification to organization and all organization members' do
1126 community = fast_create(Community) 1065 community = fast_create(Community)
1127 - p1 = Person.first || fast_create(Person)  
1128 - community.add_member(p1)  
1129 - assert p1.is_member_of?(community)  
1130 - Article.destroy_all  
1131 - ActionTracker::Record.destroy_all 1066 + member_1 = Person.first
  1067 + community.add_member(member_1)
  1068 +
1132 article = TinyMceArticle.create! :name => 'Tracked Article 1', :profile_id => community.id 1069 article = TinyMceArticle.create! :name => 'Tracked Article 1', :profile_id => community.id
1133 - assert article.published?  
1134 - assert_kind_of Community, article.profile  
1135 - assert_equal 1, ActionTracker::Record.count  
1136 - ta = ActionTracker::Record.first  
1137 - assert_equal 'Tracked Article 1', ta.get_name.last  
1138 - assert_equal article.url, ta.get_url.last  
1139 - assert p1, ta.user  
1140 - assert community, ta.target  
1141 - process_delayed_job_queue  
1142 - assert_equal 2, ActionTrackerNotification.count 1070 + first_activity = article.activity
  1071 + assert_equal [first_activity], ActionTracker::Record.find_all_by_verb('create_article')
1143 1072
1144 - p2 = fast_create(Person)  
1145 - community.add_member(p2)  
1146 process_delayed_job_queue 1073 process_delayed_job_queue
1147 - assert_equal 5, ActionTrackerNotification.count  
1148 -  
1149 - article = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => community.id  
1150 - assert article.published?  
1151 - assert_kind_of Community, article.profile  
1152 - assert_equal 3, ActionTracker::Record.count  
1153 - ta = ActionTracker::Record.first  
1154 - assert_equal 'Tracked Article 2', ta.get_name.last  
1155 - assert_equal article.url, ta.get_url.last  
1156 - assert_equal p1, ta.user  
1157 - assert_equal community, ta.target 1074 + assert_equal 2, ActionTrackerNotification.find_all_by_action_tracker_id(first_activity.id).count
  1075 +
  1076 + member_2 = fast_create(Person)
  1077 + community.add_member(member_2)
  1078 +
  1079 + article2 = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => community.id
  1080 + second_activity = article2.activity
  1081 + assert_equivalent [first_activity, second_activity], ActionTracker::Record.find_all_by_verb('create_article')
  1082 +
1158 process_delayed_job_queue 1083 process_delayed_job_queue
1159 - assert_equal 6, ActionTrackerNotification.count 1084 + assert_equal 3, ActionTrackerNotification.find_all_by_action_tracker_id(second_activity.id).count
1160 end 1085 end
1161 1086
1162 - should 'not create more than one notification track action to friends when update more than one artile' do  
1163 - p1 = Person.first || fast_create(Person) 1087 + should 'create notifications to friends when creating an article' do
1164 friend = fast_create(Person) 1088 friend = fast_create(Person)
1165 - p1.add_friend(friend) 1089 + profile.add_friend(friend)
1166 Article.destroy_all 1090 Article.destroy_all
1167 ActionTracker::Record.destroy_all 1091 ActionTracker::Record.destroy_all
1168 ActionTrackerNotification.destroy_all 1092 ActionTrackerNotification.destroy_all
1169 - article = TinyMceArticle.create! :name => 'Tracked Article 1', :profile_id => p1.id  
1170 - assert article.published?  
1171 - assert_kind_of Person, article.profile  
1172 - assert_equal 1, ActionTracker::Record.count  
1173 - ta = ActionTracker::Record.last  
1174 - assert_equal 'Tracked Article 1', ta.get_name.last  
1175 - assert_equal article.url, ta.get_url.last  
1176 - assert p1, ta.user  
1177 - assert p1, ta.target  
1178 - process_delayed_job_queue  
1179 - assert_equal 2, ActionTrackerNotification.count  
1180 -  
1181 - article = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => p1.id  
1182 - assert article.published?  
1183 - assert_kind_of Person, article.profile  
1184 - assert_equal 1, ActionTracker::Record.count  
1185 - ta = ActionTracker::Record.last  
1186 - assert_equal 'Tracked Article 2', ta.get_name.last  
1187 - assert_equal article.url, ta.get_url.last  
1188 - assert_equal p1, ta.user  
1189 - assert_equal p1, ta.target 1093 + UserStampSweeper.any_instance.expects(:current_user).returns(profile).at_least_once
  1094 + article = create(TinyMceArticle, :profile_id => profile.id)
  1095 +
1190 process_delayed_job_queue 1096 process_delayed_job_queue
1191 - assert_equal 2, ActionTrackerNotification.count 1097 + assert_equal friend, ActionTrackerNotification.last.profile
1192 end 1098 end
1193 1099
1194 should 'create the notification to the friend when one friend has the notification and the other no' do 1100 should 'create the notification to the friend when one friend has the notification and the other no' do
1195 - p1 = Person.first || fast_create(Person)  
1196 f1 = fast_create(Person) 1101 f1 = fast_create(Person)
1197 - p1.add_friend(f1)  
1198 - Article.destroy_all  
1199 - ActionTracker::Record.destroy_all  
1200 - ActionTrackerNotification.destroy_all  
1201 - article = TinyMceArticle.create! :name => 'Tracked Article 1', :profile_id => p1.id  
1202 - assert article.published?  
1203 - assert_kind_of Person, article.profile  
1204 - assert_equal 1, ActionTracker::Record.count  
1205 - ta = ActionTracker::Record.first  
1206 - assert_equal 'Tracked Article 1', ta.get_name.last  
1207 - assert_equal article.url, ta.get_url.last  
1208 - assert p1, ta.user  
1209 - assert p1, ta.target 1102 + profile.add_friend(f1)
  1103 +
  1104 + UserStampSweeper.any_instance.expects(:current_user).returns(profile).at_least_once
  1105 + article = TinyMceArticle.create! :name => 'Tracked Article 1', :profile_id => profile.id
  1106 + assert_equal 1, ActionTracker::Record.find_all_by_verb('create_article').count
1210 process_delayed_job_queue 1107 process_delayed_job_queue
1211 - assert_equal 2, ActionTrackerNotification.count 1108 + assert_equal 2, ActionTrackerNotification.find_all_by_action_tracker_id(article.activity.id).count
1212 1109
1213 f2 = fast_create(Person) 1110 f2 = fast_create(Person)
1214 - p1.add_friend(f2)  
1215 - process_delayed_job_queue  
1216 - assert_equal 5, ActionTrackerNotification.count  
1217 - article = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => p1.id  
1218 - assert article.published?  
1219 - assert_kind_of Person, article.profile  
1220 - assert_equal 2, ActionTracker::Record.count  
1221 - ta = ActionTracker::Record.first  
1222 - assert_equal 'Tracked Article 2', ta.get_name.last  
1223 - assert_equal article.url, ta.get_url.last  
1224 - assert_equal p1, ta.user  
1225 - assert_equal p1, ta.target 1111 + profile.add_friend(f2)
  1112 + article2 = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => profile.id
  1113 + assert_equal 2, ActionTracker::Record.find_all_by_verb('create_article').count
1226 process_delayed_job_queue 1114 process_delayed_job_queue
1227 - assert_equal 6, ActionTrackerNotification.count 1115 + assert_equal 3, ActionTrackerNotification.find_all_by_action_tracker_id(article2.activity.id).count
1228 end 1116 end
1229 1117
1230 should 'found articles with published date between a range' do 1118 should 'found articles with published date between a range' do
@@ -1582,7 +1470,7 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1582,7 +1470,7 @@ class ArticleTest &lt; ActiveSupport::TestCase
1582 domain = Environment.default.domains.first || Domain.new(:name => 'localhost') 1470 domain = Environment.default.domains.first || Domain.new(:name => 'localhost')
1583 article = Article.new(:body => "An article with invalid src in img tag <img src='path with spaces.png' />", :profile => @profile) 1471 article = Article.new(:body => "An article with invalid src in img tag <img src='path with spaces.png' />", :profile => @profile)
1584 assert_nothing_raised URI::InvalidURIError do 1472 assert_nothing_raised URI::InvalidURIError do
1585 - assert_equal ["http://#{domain.name}/path%20with%20spaces.png"], article.body_images_paths 1473 + assert_equal ["http://#{profile.environment.default_hostname}/path%20with%20spaces.png"], article.body_images_paths
1586 end 1474 end
1587 end 1475 end
1588 1476
@@ -1814,4 +1702,24 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1814,4 +1702,24 @@ class ArticleTest &lt; ActiveSupport::TestCase
1814 assert !a.allow_edit?(nil) 1702 assert !a.allow_edit?(nil)
1815 end 1703 end
1816 1704
  1705 + should 'get first image from lead' do
  1706 + a = fast_create(Article, :body => '<p>Foo</p><p><img src="bar.png" />Bar<img src="foo.png" /></p>',
  1707 + :abstract => '<p>Lead</p><p><img src="leadbar.png" />Bar<img src="leadfoo.png" /></p>')
  1708 + assert_equal 'leadbar.png', a.first_image
  1709 + end
  1710 +
  1711 + should 'get first image from body' do
  1712 + a = fast_create(Article, :body => '<p>Foo</p><p><img src="bar.png" />Bar<img src="foo.png" /></p>')
  1713 + assert_equal 'bar.png', a.first_image
  1714 + end
  1715 +
  1716 + should 'not get first image from anywhere' do
  1717 + a = fast_create(Article, :body => '<p>Foo</p><p>Bar</p>')
  1718 + assert_equal '', a.first_image
  1719 + end
  1720 +
  1721 + should 'store first image in tracked action' do
  1722 + a = TinyMceArticle.create! :name => 'Tracked Article', :body => '<p>Foo<img src="foo.png" />Bar</p>', :profile_id => profile.id
  1723 + assert_equal 'foo.png', ActionTracker::Record.last.get_first_image
  1724 + end
1817 end 1725 end
test/unit/category_test.rb
@@ -311,10 +311,10 @@ class CategoryTest &lt; ActiveSupport::TestCase @@ -311,10 +311,10 @@ class CategoryTest &lt; ActiveSupport::TestCase
311 a2 = person.articles.build(:name => 'art2', :category_ids => [c.id]); a2.save! 311 a2 = person.articles.build(:name => 'art2', :category_ids => [c.id]); a2.save!
312 a3 = person.articles.build(:name => 'art3', :category_ids => [c.id]); a3.save! 312 a3 = person.articles.build(:name => 'art3', :category_ids => [c.id]); a3.save!
313 313
314 - a1.comments.build(:title => 'test', :body => 'asdsa', :author => person).save!  
315 - 5.times { a2.comments.build(:title => 'test', :body => 'asdsa', :author => person).save! } 314 + Comment.create(:title => 'test', :body => 'asdsa', :author => person, :source => a1)
  315 + 5.times { Comment.create(:title => 'test', :body => 'asdsa', :author => person, :source => a2) }
316 316
317 - 10.times { a3.comments.build(:title => 'test', :body => 'kajsdsa', :author => person).save! } 317 + 10.times { Comment.create(:title => 'test', :body => 'kajsdsa', :author => person, :source => a3) }
318 318
319 assert_equal [a3, a2], c.most_commented_articles(2) 319 assert_equal [a3, a2], c.most_commented_articles(2)
320 end 320 end
test/unit/comment_notifier_test.rb
@@ -12,26 +12,26 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase @@ -12,26 +12,26 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase
12 @article = fast_create(Article, :name => 'Article test', :profile_id => @profile.id, :notify_comments => true) 12 @article = fast_create(Article, :name => 'Article test', :profile_id => @profile.id, :notify_comments => true)
13 end 13 end
14 14
15 - should 'deliver mail after make aarticle commment' do 15 + should 'deliver mail after make an article comment' do
16 assert_difference ActionMailer::Base.deliveries, :size do 16 assert_difference ActionMailer::Base.deliveries, :size do
17 - @article.comments << Comment.new(:author => @profile, :title => 'test comment', :body => 'you suck!') 17 + Comment.create(:author => @profile, :title => 'test comment', :body => 'you suck!', :source => @article )
18 end 18 end
19 end 19 end
20 20
21 should 'deliver mail to owner of article' do 21 should 'deliver mail to owner of article' do
22 - @article.comments << Comment.new(:author => @profile, :title => 'test comment', :body => 'you suck!') 22 + Comment.create(:author => @profile, :title => 'test comment', :body => 'you suck!', :source => @article )
23 sent = ActionMailer::Base.deliveries.first 23 sent = ActionMailer::Base.deliveries.first
24 assert_equal [@profile.email], sent.to 24 assert_equal [@profile.email], sent.to
25 end 25 end
26 26
27 should 'display author name in delivered mail' do 27 should 'display author name in delivered mail' do
28 - @article.comments << Comment.new(:author => @profile, :title => 'test comment', :body => 'you suck!') 28 + Comment.create(:author => @profile, :title => 'test comment', :body => 'you suck!', :source => @article)
29 sent = ActionMailer::Base.deliveries.first 29 sent = ActionMailer::Base.deliveries.first
30 assert_match /user_comment_test/, sent.body 30 assert_match /user_comment_test/, sent.body
31 end 31 end
32 32
33 should 'display unauthenticated author name and email in delivered mail' do 33 should 'display unauthenticated author name and email in delivered mail' do
34 - @article.comments << Comment.new(:name => 'flatline', :email => 'flatline@invalid.com', :title => 'test comment', :body => 'you suck!') 34 + Comment.create(:name => 'flatline', :email => 'flatline@invalid.com', :title => 'test comment', :body => 'you suck!', :source => @article )
35 sent = ActionMailer::Base.deliveries.first 35 sent = ActionMailer::Base.deliveries.first
36 assert_match /flatline/, sent.body 36 assert_match /flatline/, sent.body
37 assert_match /flatline@invalid.com/, sent.body 37 assert_match /flatline@invalid.com/, sent.body
@@ -45,13 +45,13 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase @@ -45,13 +45,13 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase
45 end 45 end
46 46
47 should 'include comment title in the e-mail' do 47 should 'include comment title in the e-mail' do
48 - @article.comments << Comment.new(:author => @profile, :title => 'comment title', :body => 'comment title') 48 + Comment.create(:author => @profile, :title => 'comment title', :body => 'comment body', :source => @article)
49 sent = ActionMailer::Base.deliveries.first 49 sent = ActionMailer::Base.deliveries.first
50 assert_match /comment title/, sent.body 50 assert_match /comment title/, sent.body
51 end 51 end
52 52
53 should 'include comment text in the e-mail' do 53 should 'include comment text in the e-mail' do
54 - @article.comments << Comment.new(:author => @profile, :title => 'comment title', :body => 'comment body') 54 + Comment.create(:author => @profile, :title => 'comment title', :body => 'comment body', :source => @article)
55 sent = ActionMailer::Base.deliveries.first 55 sent = ActionMailer::Base.deliveries.first
56 assert_match /comment body/, sent.body 56 assert_match /comment body/, sent.body
57 end 57 end
test/unit/comment_test.rb
@@ -13,13 +13,13 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -13,13 +13,13 @@ class CommentTest &lt; ActiveSupport::TestCase
13 assert_mandatory(Comment.new, :body) 13 assert_mandatory(Comment.new, :body)
14 end 14 end
15 15
16 - should 'belong to an article' do 16 + should 'have a polymorphic relationship with source' do
17 c = Comment.new 17 c = Comment.new
18 - assert_raise ActiveRecord::AssociationTypeMismatch do  
19 - c.article = 1 18 + assert_nothing_raised do
  19 + c.source = Article.new
20 end 20 end
21 assert_nothing_raised do 21 assert_nothing_raised do
22 - c.article = Article.new 22 + c.source = ActionTracker::Record.new
23 end 23 end
24 end 24 end
25 25
@@ -65,12 +65,33 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -65,12 +65,33 @@ class CommentTest &lt; ActiveSupport::TestCase
65 65
66 should 'update counter cache in article' do 66 should 'update counter cache in article' do
67 owner = create_user('testuser').person 67 owner = create_user('testuser').person
68 - art = owner.articles.build(:name => 'ytest'); art.save!  
69 - 68 + art = create(TextileArticle, :profile_id => owner.id)
70 cc = art.comments_count 69 cc = art.comments_count
71 - art.comments.build(:title => 'test comment', :body => 'anything', :author => owner).save!  
72 - art.reload  
73 - assert_equal cc + 1, art.comments_count 70 +
  71 + comment = create(Comment, :source => art, :author_id => owner.id)
  72 + assert_equal cc + 1, Article.find(art.id).comments_count
  73 + end
  74 +
  75 + should 'update counter cache in article activity' do
  76 + owner = create_user('testuser').person
  77 + article = create(TextileArticle, :profile_id => owner.id)
  78 +
  79 + action = article.activity
  80 + cc = action.comments_count
  81 + comment = create(Comment, :source => action, :author_id => owner.id)
  82 + assert_equal cc + 1, ActionTracker::Record.find(action.id).comments_count
  83 + end
  84 +
  85 + should 'update counter cache in general activity when add a comment' do
  86 + person = fast_create(Person)
  87 + community = fast_create(Community)
  88 +
  89 + activity = ActionTracker::Record.create :user => person, :target => community, :verb => 'add_member_in_community'
  90 +
  91 + cc = activity.comments_count
  92 +
  93 + comment = create(Comment, :source => activity, :author_id => person.id)
  94 + assert_equal cc + 1, ActionTracker::Record.find(activity.id).comments_count
74 end 95 end
75 96
76 should 'provide author name for authenticated authors' do 97 should 'provide author name for authenticated authors' do
@@ -217,30 +238,10 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -217,30 +238,10 @@ class CommentTest &lt; ActiveSupport::TestCase
217 assert File.exists?(File.join(Rails.root, 'public', image)), "#{image} does not exist." 238 assert File.exists?(File.join(Rails.root, 'public', image)), "#{image} does not exist."
218 end 239 end
219 240
220 - should 'track action when comment is created' do  
221 - owner = create_user('testuser').person  
222 - article = owner.articles.create!(:name => 'test', :body => '...')  
223 - comment = article.comments.create!(:article => article, :name => 'foo', :title => 'bar', :body => 'my comment', :email => 'cracker@test.org')  
224 - ta = ActionTracker::Record.last  
225 - assert_equal 'bar', ta.get_title  
226 - assert_equal 'my comment', ta.get_body  
227 - assert_equal 'test', ta.get_article_title  
228 - assert_equal article.url, ta.get_article_url  
229 - assert_equal comment.url, ta.get_url  
230 - end  
231 -  
232 should 'have the action_tracker_target defined' do 241 should 'have the action_tracker_target defined' do
233 assert Comment.method_defined?(:action_tracker_target) 242 assert Comment.method_defined?(:action_tracker_target)
234 end 243 end
235 244
236 - should "have the action_tracker_target be the articles's profile" do  
237 - owner = create_user('testuser').person  
238 - article = owner.articles.create!(:name => 'test', :body => '...')  
239 - comment = article.comments.create!(:article => article, :name => 'foo', :title => 'bar', :body => 'my comment', :email => 'cracker@test.org')  
240 - ta = ActionTracker::Record.last  
241 - assert_equal owner, ta.target  
242 - end  
243 -  
244 should "get children of a comment" do 245 should "get children of a comment" do
245 c = fast_create(Comment) 246 c = fast_create(Comment)
246 c1 = fast_create(Comment, :reply_of_id => c.id) 247 c1 = fast_create(Comment, :reply_of_id => c.id)
@@ -307,11 +308,11 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -307,11 +308,11 @@ class CommentTest &lt; ActiveSupport::TestCase
307 308
308 should "return comments as a thread" do 309 should "return comments as a thread" do
309 a = fast_create(Article) 310 a = fast_create(Article)
310 - c0 = fast_create(Comment, :article_id => a.id)  
311 - c1 = fast_create(Comment, :reply_of_id => c0.id, :article_id => a.id)  
312 - c2 = fast_create(Comment, :reply_of_id => c1.id, :article_id => a.id)  
313 - c3 = fast_create(Comment, :reply_of_id => c0.id, :article_id => a.id)  
314 - c4 = fast_create(Comment, :article_id => a.id) 311 + c0 = fast_create(Comment, :source_id => a.id)
  312 + c1 = fast_create(Comment, :reply_of_id => c0.id, :source_id => a.id)
  313 + c2 = fast_create(Comment, :reply_of_id => c1.id, :source_id => a.id)
  314 + c3 = fast_create(Comment, :reply_of_id => c0.id, :source_id => a.id)
  315 + c4 = fast_create(Comment, :source_id => a.id)
315 result = a.comments.as_thread 316 result = a.comments.as_thread
316 assert_equal c0.id, result[0].id 317 assert_equal c0.id, result[0].id
317 assert_equal [c1.id, c3.id], result[0].replies.map(&:id) 318 assert_equal [c1.id, c3.id], result[0].replies.map(&:id)
@@ -320,6 +321,22 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -320,6 +321,22 @@ class CommentTest &lt; ActiveSupport::TestCase
320 assert result[1].replies.empty? 321 assert result[1].replies.empty?
321 end 322 end
322 323
  324 + should "return activities comments as a thread" do
  325 + person = fast_create(Person)
  326 + a = TextileArticle.create!(:profile => person, :name => 'My article', :body => 'Article body')
  327 + c0 = Comment.create!(:source => a, :body => 'My comment', :author => person)
  328 + c1 = Comment.create!(:reply_of_id => c0.id, :source => a, :body => 'bla', :author => person)
  329 + c2 = Comment.create!(:reply_of_id => c1.id, :source => a, :body => 'bla', :author => person)
  330 + c3 = Comment.create!(:reply_of_id => c0.id, :source => a, :body => 'bla', :author => person)
  331 + c4 = Comment.create!(:source => a, :body => 'My comment', :author => person)
  332 + result = a.activity.comments_as_thread
  333 + assert_equal c0, result[0]
  334 + assert_equal [c1, c3], result[0].replies
  335 + assert_equal [c2], result[0].replies[0].replies
  336 + assert_equal c4, result[1]
  337 + assert result[1].replies.empty?
  338 + end
  339 +
323 should 'provide author url for authenticated user' do 340 should 'provide author url for authenticated user' do
324 author = Person.new 341 author = Person.new
325 author.expects(:url).returns('http://blabla.net/author') 342 author.expects(:url).returns('http://blabla.net/author')
@@ -338,4 +355,27 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -338,4 +355,27 @@ class CommentTest &lt; ActiveSupport::TestCase
338 assert c.rejected? 355 assert c.rejected?
339 end 356 end
340 357
  358 + should 'update article activity when add a comment' do
  359 + profile = create_user('testuser').person
  360 + article = create(TinyMceArticle, :profile => profile)
  361 + action = article.activity
  362 + time = action.updated_at
  363 +
  364 + Time.stubs(:now).returns(time + 1.day)
  365 +
  366 + comment = create(Comment, :source => article, :author => profile)
  367 + assert_equal time + 1.day, article.activity.updated_at
  368 + end
  369 +
  370 + should 'create a new activity when add a comment and the activity was removed' do
  371 + profile = create_user('testuser').person
  372 + article = create(TinyMceArticle, :profile => profile)
  373 + article.activity.destroy
  374 +
  375 + assert_nil article.activity
  376 +
  377 + comment = create(Comment, :source => article, :author => profile)
  378 + assert_not_nil article.activity
  379 + end
  380 +
341 end 381 end
test/unit/community_test.rb
@@ -274,22 +274,19 @@ class CommunityTest &lt; ActiveSupport::TestCase @@ -274,22 +274,19 @@ class CommunityTest &lt; ActiveSupport::TestCase
274 end 274 end
275 end 275 end
276 276
277 - should "be created an tracked action to the community when an community's article is commented" do 277 + should "update the action of article creation when an community's article is commented" do
278 ActionTrackerNotification.delete_all 278 ActionTrackerNotification.delete_all
279 p1 = Person.first 279 p1 = Person.first
280 community = fast_create(Community) 280 community = fast_create(Community)
281 p2 = fast_create(Person) 281 p2 = fast_create(Person)
282 p3 = fast_create(Person) 282 p3 = fast_create(Person)
283 community.add_member(p3) 283 community.add_member(p3)
284 - article = fast_create(Article, :profile_id => community.id)  
285 - ActionTracker::Record.destroy_all  
286 - assert_difference(ActionTrackerNotification, :count, 3) do  
287 - Comment.create!(:article_id => article.id, :title => 'some', :body => 'some', :author_id => p2.id)  
288 - process_delayed_job_queue  
289 - end  
290 - ActionTrackerNotification.all.map{|a|a.profile}.map do |profile|  
291 - assert [community,p1,p3].include?(profile)  
292 - end 284 + article = create(TextileArticle, :profile_id => community.id)
  285 + time = article.activity.updated_at
  286 + Time.stubs(:now).returns(time + 1.day)
  287 + Comment.create!(:source_id => article.id, :title => 'some', :body => 'some', :author_id => p2.id)
  288 + process_delayed_job_queue
  289 + assert_equal time, article.activity.updated_at
293 end 290 end
294 291
295 should "see get all received scraps" do 292 should "see get all received scraps" do
@@ -341,4 +338,35 @@ class CommunityTest &lt; ActiveSupport::TestCase @@ -341,4 +338,35 @@ class CommunityTest &lt; ActiveSupport::TestCase
341 assert_equal false, community.receives_scrap_notification? 338 assert_equal false, community.receives_scrap_notification?
342 end 339 end
343 340
  341 + should 'return scraps as activities' do
  342 + person = fast_create(Person)
  343 + community = fast_create(Community)
  344 +
  345 + scrap = Scrap.create!(defaults_for_scrap(:sender => person, :receiver => community, :content => 'A scrap'))
  346 + activity = ActionTracker::Record.last
  347 +
  348 + assert_equal [activity,scrap], community.activities.map { |a| a.klass.constantize.find(a.id) }
  349 + end
  350 +
  351 + should 'return tracked_actions of community as activities' do
  352 + person = fast_create(Person)
  353 + community = fast_create(Community)
  354 +
  355 + UserStampSweeper.any_instance.expects(:current_user).returns(person).at_least_once
  356 + article = create(TinyMceArticle, :profile => community, :name => 'An article about free software')
  357 +
  358 + assert_equal [article.activity], community.activities.map { |a| a.klass.constantize.find(a.id) }
  359 + end
  360 +
  361 + should 'not return tracked_actions of other community as activities' do
  362 + person = fast_create(Person)
  363 + community = fast_create(Community)
  364 + community2 = fast_create(Community)
  365 +
  366 + UserStampSweeper.any_instance.expects(:current_user).returns(person).at_least_once
  367 + article = create(TinyMceArticle, :profile => community2, :name => 'Another article about free software')
  368 +
  369 + assert_not_includes community.activities.map { |a| a.klass.constantize.find(a.id) }, article.activity
  370 + end
  371 +
344 end 372 end
test/unit/enterprise_test.rb
@@ -470,4 +470,36 @@ class EnterpriseTest &lt; ActiveSupport::TestCase @@ -470,4 +470,36 @@ class EnterpriseTest &lt; ActiveSupport::TestCase
470 ent.save! 470 ent.save!
471 end 471 end
472 472
  473 + should 'return scraps as activities' do
  474 + person = fast_create(Person)
  475 + enterprise = fast_create(Enterprise)
  476 +
  477 +
  478 + activity = ActionTracker::Record.last
  479 + scrap = Scrap.create!(defaults_for_scrap(:sender => person, :receiver => enterprise, :content => 'A scrap'))
  480 +
  481 + assert_equal [scrap], enterprise.activities.map { |a| a.klass.constantize.find(a.id) }
  482 + end
  483 +
  484 + should 'return tracked_actions of community as activities' do
  485 + person = fast_create(Person)
  486 + enterprise = fast_create(Enterprise)
  487 +
  488 + UserStampSweeper.any_instance.expects(:current_user).returns(person).at_least_once
  489 + article = create(TinyMceArticle, :profile => enterprise, :name => 'An article about free software')
  490 +
  491 + assert_equal [article.activity], enterprise.activities.map { |a| a.klass.constantize.find(a.id) }
  492 + end
  493 +
  494 + should 'not return tracked_actions of other community as activities' do
  495 + person = fast_create(Person)
  496 + enterprise = fast_create(Enterprise)
  497 + enterprise2 = fast_create(Enterprise)
  498 +
  499 + UserStampSweeper.any_instance.expects(:current_user).returns(person).at_least_once
  500 + article = create(TinyMceArticle, :profile => enterprise2, :name => 'Another article about free software')
  501 +
  502 + assert_not_includes enterprise.activities.map { |a| a.klass.constantize.find(a.id) }, article.activity
  503 + end
  504 +
473 end 505 end
test/unit/event_test.rb
@@ -276,4 +276,7 @@ class EventTest &lt; ActiveSupport::TestCase @@ -276,4 +276,7 @@ class EventTest &lt; ActiveSupport::TestCase
276 assert Event.new.tiny_mce? 276 assert Event.new.tiny_mce?
277 end 277 end
278 278
  279 + should 'be notifiable' do
  280 + assert Event.new.notifiable?
  281 + end
279 end 282 end
test/unit/forum_helper_test.rb
@@ -65,7 +65,7 @@ class ForumHelperTest &lt; ActiveSupport::TestCase @@ -65,7 +65,7 @@ class ForumHelperTest &lt; ActiveSupport::TestCase
65 some_post.comments << Comment.new(:name => 'John', :email => 'lenon@example.com', :title => 'test', :body => 'test') 65 some_post.comments << Comment.new(:name => 'John', :email => 'lenon@example.com', :title => 'test', :body => 'test')
66 c = Comment.last 66 c = Comment.last
67 out = last_topic_update(some_post) 67 out = last_topic_update(some_post)
68 - assert_match "#{c.created_at.to_s} ago by John", out 68 + assert_match "#{c.created_at.to_s} by John", out
69 assert_match 'John', out 69 assert_match 'John', out
70 70
71 assert_match(/#{Regexp.escape(c.created_at.to_s)} ago by John/m, last_topic_update(some_post)) 71 assert_match(/#{Regexp.escape(c.created_at.to_s)} ago by John/m, last_topic_update(some_post))
test/unit/forum_test.rb
@@ -28,21 +28,21 @@ class ForumTest &lt; ActiveSupport::TestCase @@ -28,21 +28,21 @@ class ForumTest &lt; ActiveSupport::TestCase
28 28
29 should 'create rss feed automatically' do 29 should 'create rss feed automatically' do
30 p = create_user('testuser').person 30 p = create_user('testuser').person
31 - b = create(Forum, :profile_id => p.id, :name => 'forum_feed_test') 31 + b = create(Forum, :profile_id => p.id, :name => 'forum_feed_test', :body => 'Forum')
32 assert_kind_of RssFeed, b.feed 32 assert_kind_of RssFeed, b.feed
33 end 33 end
34 34
35 should 'save feed options' do 35 should 'save feed options' do
36 p = create_user('testuser').person 36 p = create_user('testuser').person
37 - p.articles << Forum.new(:profile => p, :name => 'forum_feed_test') 37 + p.articles << forum = Forum.new(:profile => p, :name => 'forum_feed_test', :body => 'Forum test')
38 p.forum.feed = { :limit => 7 } 38 p.forum.feed = { :limit => 7 }
39 - assert_equal 7, p.forum.feed.limit 39 + assert_equal 7, Forum.find(forum.id).feed.limit
40 end 40 end
41 41
42 should 'save feed options after create forum' do 42 should 'save feed options after create forum' do
43 p = create_user('testuser').person 43 p = create_user('testuser').person
44 - p.articles << Forum.new(:profile => p, :name => 'forum_feed_test', :feed => { :limit => 7 })  
45 - assert_equal 7, p.forum.feed.limit 44 + p.articles << forum = Forum.new(:profile => p, :name => 'forum_feed_test', :body => 'Forum test', :feed => { :limit => 7 })
  45 + assert_equal 7, Forum.find(forum.id).feed.limit
46 end 46 end
47 47
48 should 'list 5 posts per page by default' do 48 should 'list 5 posts per page by default' do
@@ -52,16 +52,15 @@ class ForumTest &lt; ActiveSupport::TestCase @@ -52,16 +52,15 @@ class ForumTest &lt; ActiveSupport::TestCase
52 52
53 should 'update posts per page setting' do 53 should 'update posts per page setting' do
54 p = create_user('testuser').person 54 p = create_user('testuser').person
55 - p.articles << Forum.new(:profile => p, :name => 'Forum test')  
56 - forum = p.forum 55 + p.articles << forum = Forum.new(:profile => p, :name => 'Forum test', :body => 'Forum test')
57 forum.posts_per_page = 7 56 forum.posts_per_page = 7
58 assert forum.save! 57 assert forum.save!
59 - assert_equal 7, p.forum.posts_per_page 58 + assert_equal 7, Forum.find(forum.id).posts_per_page
60 end 59 end
61 60
62 should 'has posts' do 61 should 'has posts' do
63 p = create_user('testuser').person 62 p = create_user('testuser').person
64 - forum = fast_create(Forum, :profile_id => p.id, :name => 'Forum test') 63 + p.articles << forum = Forum.new(:profile => p, :name => 'Forum test', :body => 'Forum test')
65 post = fast_create(TextileArticle, :name => 'First post', :profile_id => p.id, :parent_id => forum.id) 64 post = fast_create(TextileArticle, :name => 'First post', :profile_id => p.id, :parent_id => forum.id)
66 forum.children << post 65 forum.children << post
67 assert_includes forum.posts, post 66 assert_includes forum.posts, post
@@ -69,7 +68,7 @@ class ForumTest &lt; ActiveSupport::TestCase @@ -69,7 +68,7 @@ class ForumTest &lt; ActiveSupport::TestCase
69 68
70 should 'not includes rss feed in posts' do 69 should 'not includes rss feed in posts' do
71 p = create_user('testuser').person 70 p = create_user('testuser').person
72 - forum = create(Forum, :profile_id => p.id, :name => 'Forum test') 71 + forum = create(Forum, :profile_id => p.id, :name => 'Forum test', :body => 'Forum')
73 assert_includes forum.children, forum.feed 72 assert_includes forum.children, forum.feed
74 assert_not_includes forum.posts, forum.feed 73 assert_not_includes forum.posts, forum.feed
75 end 74 end
@@ -89,13 +88,13 @@ class ForumTest &lt; ActiveSupport::TestCase @@ -89,13 +88,13 @@ class ForumTest &lt; ActiveSupport::TestCase
89 p = create_user('testuser').person 88 p = create_user('testuser').person
90 fast_create(Forum, :name => 'Forum test', :profile_id => p.id) 89 fast_create(Forum, :name => 'Forum test', :profile_id => p.id)
91 assert_nothing_raised ActiveRecord::RecordInvalid do 90 assert_nothing_raised ActiveRecord::RecordInvalid do
92 - Forum.create!(:name => 'Another Forum', :profile => p) 91 + Forum.create!(:name => 'Another Forum', :profile => p, :body => 'Forum test')
93 end 92 end
94 end 93 end
95 94
96 should 'not update slug from name for existing forum' do 95 should 'not update slug from name for existing forum' do
97 p = create_user('testuser').person 96 p = create_user('testuser').person
98 - forum = Forum.create!(:name => 'Forum test', :profile => p) 97 + forum = Forum.create(:name => 'Forum test', :profile_id => p.id, :body => 'Forum')
99 assert_equal 'forum-test', forum.slug 98 assert_equal 'forum-test', forum.slug
100 forum.name = 'Changed name' 99 forum.name = 'Changed name'
101 assert_not_equal 'changed-name', forum.slug 100 assert_not_equal 'changed-name', forum.slug
@@ -110,4 +109,28 @@ class ForumTest &lt; ActiveSupport::TestCase @@ -110,4 +109,28 @@ class ForumTest &lt; ActiveSupport::TestCase
110 assert !folder.accept_uploads? 109 assert !folder.accept_uploads?
111 end 110 end
112 111
  112 + should 'be notifiable' do
  113 + assert Forum.new.notifiable?
  114 + end
  115 +
  116 + should 'get first paragraph' do
  117 + f = fast_create(Forum, :body => '<p>First</p><p>Second</p>')
  118 + assert_equal '<p>First</p>', f.first_paragraph
  119 + end
  120 +
  121 + should 'not get first paragraph' do
  122 + f = fast_create(Forum, :body => 'Nothing to do here')
  123 + assert_equal '', f.first_paragraph
  124 + end
  125 +
  126 + should 'provide first_paragraph even if body was not given' do
  127 + f = fast_create(Forum)
  128 + assert_equal '', f.first_paragraph
  129 + end
  130 +
  131 + should 'provide first_paragraph even if body is nil' do
  132 + f = fast_create(Forum, :body => nil)
  133 + assert_equal '', f.first_paragraph
  134 + end
  135 +
113 end 136 end
test/unit/notify_activity_to_profiles_job_test.rb
@@ -24,28 +24,6 @@ class NotifyActivityToProfilesJobTest &lt; ActiveSupport::TestCase @@ -24,28 +24,6 @@ class NotifyActivityToProfilesJobTest &lt; ActiveSupport::TestCase
24 end 24 end
25 end 25 end
26 26
27 - should 'notify just the community in tracker with remove_member_in_community verb' do  
28 - person = fast_create(Person)  
29 - community = fast_create(Community)  
30 - action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'remove_member_in_community')  
31 - assert NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)  
32 - p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)  
33 - fast_create(Friendship, :person_id => person.id, :friend_id => p1.id)  
34 - fast_create(Friendship, :person_id => person.id, :friend_id => p2.id)  
35 - fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id)  
36 - fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)  
37 - ActionTrackerNotification.delete_all  
38 - job = NotifyActivityToProfilesJob.new(action_tracker.id)  
39 - job.perform  
40 - process_delayed_job_queue  
41 -  
42 - assert_equal 1, ActionTrackerNotification.count  
43 - [community].each do |profile|  
44 - notification = ActionTrackerNotification.find_by_profile_id profile.id  
45 - assert_equal action_tracker, notification.action_tracker  
46 - end  
47 - end  
48 -  
49 should 'notify just the users and his friends tracking user actions' do 27 should 'notify just the users and his friends tracking user actions' do
50 person = fast_create(Person) 28 person = fast_create(Person)
51 community = fast_create(Community) 29 community = fast_create(Community)
@@ -132,36 +110,14 @@ class NotifyActivityToProfilesJobTest &lt; ActiveSupport::TestCase @@ -132,36 +110,14 @@ class NotifyActivityToProfilesJobTest &lt; ActiveSupport::TestCase
132 end 110 end
133 end 111 end
134 112
135 - should 'not notify the community tracking leave_community verb' do  
136 - person = fast_create(Person)  
137 - community = fast_create(Community)  
138 - action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'leave_community')  
139 - assert !NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)  
140 - p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)  
141 - fast_create(Friendship, :person_id => person.id, :friend_id => p1.id)  
142 - fast_create(Friendship, :person_id => person.id, :friend_id => p2.id)  
143 - fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id)  
144 - fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)  
145 - ActionTrackerNotification.delete_all  
146 - job = NotifyActivityToProfilesJob.new(action_tracker.id)  
147 - job.perform  
148 - process_delayed_job_queue  
149 -  
150 - assert_equal 5, ActionTrackerNotification.count  
151 - [person, p1, p2, m1, m2].each do |profile|  
152 - notification = ActionTrackerNotification.find_by_profile_id profile.id  
153 - assert_equal action_tracker, notification.action_tracker  
154 - end  
155 - end  
156 -  
157 should "the NOTIFY_ONLY_COMMUNITY constant has all the verbs tested" do 113 should "the NOTIFY_ONLY_COMMUNITY constant has all the verbs tested" do
158 - notify_community_verbs = ['add_member_in_community', 'remove_member_in_community'] 114 + notify_community_verbs = ['add_member_in_community']
159 assert_equal [], notify_community_verbs - NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY 115 assert_equal [], notify_community_verbs - NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY
160 assert_equal [], NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY - notify_community_verbs 116 assert_equal [], NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY - notify_community_verbs
161 end 117 end
162 118
163 should "the NOT_NOTIFY_COMMUNITY constant has all the verbs tested" do 119 should "the NOT_NOTIFY_COMMUNITY constant has all the verbs tested" do
164 - not_notify_community_verbs = ['join_community', 'leave_community'] 120 + not_notify_community_verbs = ['join_community']
165 assert_equal [], not_notify_community_verbs - NotifyActivityToProfilesJob::NOT_NOTIFY_COMMUNITY 121 assert_equal [], not_notify_community_verbs - NotifyActivityToProfilesJob::NOT_NOTIFY_COMMUNITY
166 assert_equal [], NotifyActivityToProfilesJob::NOT_NOTIFY_COMMUNITY - not_notify_community_verbs 122 assert_equal [], NotifyActivityToProfilesJob::NOT_NOTIFY_COMMUNITY - not_notify_community_verbs
167 end 123 end
test/unit/person_test.rb
@@ -1013,65 +1013,14 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -1013,65 +1013,14 @@ class PersonTest &lt; ActiveSupport::TestCase
1013 assert has_add_member_notification 1013 assert has_add_member_notification
1014 end 1014 end
1015 1015
1016 - should 'track only one action when a person leaves a community' do 1016 + should 'not track when a person leaves a community' do
1017 p = create_user('test_user').person 1017 p = create_user('test_user').person
1018 c = fast_create(Community, :name => "Foo") 1018 c = fast_create(Community, :name => "Foo")
1019 c.add_member(p) 1019 c.add_member(p)
1020 c.add_moderator(p) 1020 c.add_moderator(p)
1021 ActionTracker::Record.delete_all 1021 ActionTracker::Record.delete_all
1022 c.remove_member(p) 1022 c.remove_member(p)
1023 - assert_equal ["Foo"], ActionTracker::Record.last(:conditions => {:verb => 'leave_community'}).get_resource_name  
1024 - end  
1025 -  
1026 - should 'the tracker target be Community when a person leaves a community' do  
1027 - ActionTracker::Record.delete_all  
1028 - p = create_user('test_user').person  
1029 - c = fast_create(Community, :name => "Foo")  
1030 - c.add_member(p)  
1031 - c.add_moderator(p)  
1032 - ActionTracker::Record.delete_all  
1033 - c.remove_member(p)  
1034 - assert_kind_of Community, ActionTracker::Record.last(:conditions => {:verb => 'leave_community'}).target  
1035 - end  
1036 -  
1037 - should 'the community be notified specifically when a person leaves a community' do  
1038 - ActionTracker::Record.delete_all  
1039 - p = create_user('test_user').person  
1040 - c = fast_create(Community, :name => "Foo")  
1041 - c.add_member(p)  
1042 - c.add_moderator(p)  
1043 - ActionTracker::Record.delete_all  
1044 - c.remove_member(p)  
1045 - assert_not_nil ActionTracker::Record.last(:conditions => {:verb => 'remove_member_in_community'})  
1046 - end  
1047 -  
1048 - should 'the community specific notification created when a member leaves community could not be propagated to members' do  
1049 - ActionTracker::Record.delete_all  
1050 - p1 = Person.first  
1051 - p2 = create_user('test_user').person  
1052 - p3 = create_user('test_user').person  
1053 - c = fast_create(Community, :name => "Foo")  
1054 - process_delayed_job_queue  
1055 - Delayed::Job.delete_all  
1056 - c.add_member(p1)  
1057 - c.add_member(p3)  
1058 - c.add_moderator(p1)  
1059 - c.add_moderator(p3)  
1060 - ActionTracker::Record.delete_all  
1061 - c.remove_member(p1)  
1062 - process_delayed_job_queue  
1063 - c.remove_member(p3)  
1064 - process_delayed_job_queue  
1065 - assert_equal 4, ActionTracker::Record.count  
1066 - assert_equal 5, ActionTrackerNotification.count  
1067 - has_remove_member_notification = false  
1068 - ActionTrackerNotification.all.map do |notification|  
1069 - if notification.action_tracker.verb == 'remove_member_in_community'  
1070 - has_remove_member_notification = true  
1071 - assert_equal c, notification.profile  
1072 - end  
1073 - end  
1074 - assert has_remove_member_notification 1023 + assert_equal [], ActionTracker::Record.all
1075 end 1024 end
1076 1025
1077 should 'get all friends online' do 1026 should 'get all friends online' do
@@ -1243,4 +1192,32 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -1243,4 +1192,32 @@ class PersonTest &lt; ActiveSupport::TestCase
1243 assert !person.visible 1192 assert !person.visible
1244 assert_not_equal password, person.user.password 1193 assert_not_equal password, person.user.password
1245 end 1194 end
  1195 +
  1196 + should 'return tracked_actions and scraps as activities' do
  1197 + person = fast_create(Person)
  1198 + another_person = fast_create(Person)
  1199 +
  1200 + scrap = Scrap.create!(defaults_for_scrap(:sender => another_person, :receiver => person, :content => 'A scrap'))
  1201 + UserStampSweeper.any_instance.expects(:current_user).returns(person).at_least_once
  1202 + article = TinyMceArticle.create!(:profile => person, :name => 'An article about free software')
  1203 +
  1204 + assert_equivalent [scrap,article.activity], person.activities.map { |a| a.klass.constantize.find(a.id) }
  1205 + end
  1206 +
  1207 + should 'not return tracked_actions and scraps from others as activities' do
  1208 + person = fast_create(Person)
  1209 + another_person = fast_create(Person)
  1210 +
  1211 + person_scrap = Scrap.create!(defaults_for_scrap(:sender => person, :receiver => person, :content => 'A scrap from person'))
  1212 + another_person_scrap = Scrap.create!(defaults_for_scrap(:sender => another_person, :receiver => another_person, :content => 'A scrap from another person'))
  1213 +
  1214 + TinyMceArticle.create!(:profile => another_person, :name => 'An article about free software from another person')
  1215 + another_person_activity = ActionTracker::Record.last
  1216 +
  1217 + UserStampSweeper.any_instance.stubs(:current_user).returns(person)
  1218 + TinyMceArticle.create!(:profile => person, :name => 'An article about free software')
  1219 + person_activity = ActionTracker::Record.last
  1220 +
  1221 + assert_equivalent [person_scrap,person_activity], person.activities.map { |a| a.klass.constantize.find(a.id) }
  1222 + end
1246 end 1223 end
test/unit/profile_test.rb
@@ -1648,7 +1648,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1648,7 +1648,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1648 1648
1649 should 'have forum' do 1649 should 'have forum' do
1650 p = fast_create(Profile) 1650 p = fast_create(Profile)
1651 - p.articles << Forum.new(:profile => p, :name => 'forum_feed_test') 1651 + p.articles << Forum.new(:profile => p, :name => 'forum_feed_test', :body => 'Forum test')
1652 assert p.has_forum? 1652 assert p.has_forum?
1653 end 1653 end
1654 1654
@@ -1664,9 +1664,9 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1664,9 +1664,9 @@ class ProfileTest &lt; ActiveSupport::TestCase
1664 1664
1665 should 'get first forum when has multiple forums' do 1665 should 'get first forum when has multiple forums' do
1666 p = fast_create(Profile) 1666 p = fast_create(Profile)
1667 - p.forums << Forum.new(:profile => p, :name => 'Forum one')  
1668 - p.forums << Forum.new(:profile => p, :name => 'Forum two')  
1669 - p.forums << Forum.new(:profile => p, :name => 'Forum three') 1667 + p.forums << Forum.new(:profile => p, :name => 'Forum one', :body => 'Forum test')
  1668 + p.forums << Forum.new(:profile => p, :name => 'Forum two', :body => 'Forum test')
  1669 + p.forums << Forum.new(:profile => p, :name => 'Forum three', :body => 'Forum test')
1670 assert_equal 'Forum one', p.forum.name 1670 assert_equal 'Forum one', p.forum.name
1671 assert_equal 3, p.forums.count 1671 assert_equal 3, p.forums.count
1672 end 1672 end
@@ -1731,6 +1731,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1731,6 +1731,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1731 assert profile.is_on_homepage?("/#{profile.identifier}/#{homepage.slug}", homepage) 1731 assert profile.is_on_homepage?("/#{profile.identifier}/#{homepage.slug}", homepage)
1732 end 1732 end
1733 1733
  1734 +
1734 should 'find profiles with image' do 1735 should 'find profiles with image' do
1735 env = fast_create(Environment) 1736 env = fast_create(Environment)
1736 2.times do |n| 1737 2.times do |n|
@@ -1791,6 +1792,11 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1791,6 +1792,11 @@ class ProfileTest &lt; ActiveSupport::TestCase
1791 end 1792 end
1792 end 1793 end
1793 1794
  1795 + should 'return empty array as activities' do
  1796 + profile = Profile.new
  1797 + assert_equal [], profile.activities
  1798 + end
  1799 +
1794 private 1800 private
1795 1801
1796 def assert_invalid_identifier(id) 1802 def assert_invalid_identifier(id)
test/unit/textile_article_test.rb
@@ -38,80 +38,72 @@ class TextileArticleTest &lt; ActiveSupport::TestCase @@ -38,80 +38,72 @@ class TextileArticleTest &lt; ActiveSupport::TestCase
38 assert_equal 1, ActionTracker::Record.count 38 assert_equal 1, ActionTracker::Record.count
39 end 39 end
40 40
41 - should 'notify with different trackers activity create with different targets' do 41 + should 'not group trackers activity of article\'s creation' do
42 ActionTracker::Record.delete_all 42 ActionTracker::Record.delete_all
43 profile = fast_create(Profile) 43 profile = fast_create(Profile)
44 TextileArticle.create! :name => 'bar', :profile_id => profile.id, :published => true 44 TextileArticle.create! :name => 'bar', :profile_id => profile.id, :published => true
45 TextileArticle.create! :name => 'another bar', :profile_id => profile.id, :published => true 45 TextileArticle.create! :name => 'another bar', :profile_id => profile.id, :published => true
46 - assert_equal 1, ActionTracker::Record.count  
47 TextileArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true 46 TextileArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
48 - assert_equal 2, ActionTracker::Record.count 47 + assert_equal 3, ActionTracker::Record.count
49 end 48 end
50 49
51 - should 'notify activity on update' do 50 + should 'not update activity on update of an article' do
52 ActionTracker::Record.delete_all 51 ActionTracker::Record.delete_all
53 - a = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true  
54 - assert_equal 1, ActionTracker::Record.count  
55 - a.name = 'foo'  
56 - a.save!  
57 - assert_equal 2, ActionTracker::Record.count 52 + profile = fast_create(Profile)
  53 + article = create(TextileArticle, :profile_id => profile.id)
  54 + time = article.activity.updated_at
  55 + Time.stubs(:now).returns(time + 1.day)
  56 + assert_no_difference ActionTracker::Record, :count do
  57 + article.name = 'foo'
  58 + article.save!
  59 + end
  60 + assert_equal time, article.activity.updated_at
58 end 61 end
59 62
60 - should 'notify with different trackers activity update with different targets' do 63 + should 'not create trackers activity when updating articles' do
61 ActionTracker::Record.delete_all 64 ActionTracker::Record.delete_all
62 a1 = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true 65 a1 = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
63 a2 = TextileArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true 66 a2 = TextileArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
64 - assert_equal 2, ActionTracker::Record.count  
65 - a1.name = 'foo'  
66 - a1.save!  
67 - assert_equal 3, ActionTracker::Record.count  
68 - a2.name = 'another foo'  
69 - a2.save!  
70 - assert_equal 4, ActionTracker::Record.count 67 + assert_no_difference ActionTracker::Record, :count do
  68 + a1.name = 'foo';a1.save!
  69 + a2.name = 'another foo';a2.save!
  70 + end
71 end 71 end
72 72
73 - should 'notify activity on destroy' do 73 + should 'not notify activity on destroy' do
74 ActionTracker::Record.delete_all 74 ActionTracker::Record.delete_all
75 a = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true 75 a = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
76 - assert_equal 1, ActionTracker::Record.count  
77 - a.destroy  
78 - assert_equal 2, ActionTracker::Record.count 76 + assert_no_difference ActionTracker::Record, :count do
  77 + a.destroy
  78 + end
79 end 79 end
80 80
81 - should 'notify different activities when destroy articles with diferrents targets' do 81 + should 'not notify when an article is destroyed' do
82 ActionTracker::Record.delete_all 82 ActionTracker::Record.delete_all
83 a1 = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true 83 a1 = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
84 a2 = TextileArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true 84 a2 = TextileArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
85 assert_equal 2, ActionTracker::Record.count 85 assert_equal 2, ActionTracker::Record.count
86 - a1.destroy  
87 - assert_equal 3, ActionTracker::Record.count  
88 - a2.destroy  
89 - assert_equal 4, ActionTracker::Record.count 86 + assert_no_difference ActionTracker::Record, :count do
  87 + a1.destroy
  88 + a2.destroy
  89 + end
90 end 90 end
91 91
92 - should "the tracker action target be defined as Community by custom_target method on articles'creation in communities" do 92 + should "the tracker action target be defined as the article on articles'creation in communities" do
93 ActionTracker::Record.delete_all 93 ActionTracker::Record.delete_all
94 community = fast_create(Community) 94 community = fast_create(Community)
95 p1 = Person.first 95 p1 = Person.first
96 community.add_member(p1) 96 community.add_member(p1)
97 assert p1.is_member_of?(community) 97 assert p1.is_member_of?(community)
98 article = TextileArticle.create! :name => 'test', :profile_id => community.id 98 article = TextileArticle.create! :name => 'test', :profile_id => community.id
99 - assert_equal true, article.published?  
100 - assert_equal true, article.notifiable?  
101 - assert_equal false, article.image?  
102 - assert_equal Community, article.profile.class  
103 - assert_equal Community, ActionTracker::Record.last.target.class 99 + assert_equal article, ActionTracker::Record.last.target
104 end 100 end
105 101
106 - should "the tracker action target be defined as person by custom_target method on articles'creation in profile" do 102 + should "the tracker action target be defined as the article on articles'creation in profile" do
107 ActionTracker::Record.delete_all 103 ActionTracker::Record.delete_all
108 person = Person.first 104 person = Person.first
109 article = TextileArticle.create! :name => 'test', :profile_id => person.id 105 article = TextileArticle.create! :name => 'test', :profile_id => person.id
110 - assert_equal true, article.published?  
111 - assert_equal true, article.notifiable?  
112 - assert_equal false, article.image?  
113 - assert_equal Person, article.profile.class  
114 - assert_equal person, ActionTracker::Record.last.target 106 + assert_equal article, ActionTracker::Record.last.target
115 end 107 end
116 108
117 should 'not notify activity if the article is not advertise' do 109 should 'not notify activity if the article is not advertise' do
@@ -129,7 +121,7 @@ class TextileArticleTest &lt; ActiveSupport::TestCase @@ -129,7 +121,7 @@ class TextileArticleTest &lt; ActiveSupport::TestCase
129 end 121 end
130 122
131 should "the common trackable conditions return the correct value" do 123 should "the common trackable conditions return the correct value" do
132 - a = TextileArticle.new 124 + a = TextileArticle.new(:profile => profile)
133 a.published = a.advertise = true 125 a.published = a.advertise = true
134 assert_equal true, a.published? 126 assert_equal true, a.published?
135 assert_equal true, a.notifiable? 127 assert_equal true, a.notifiable?
test/unit/tiny_mce_article_test.rb
@@ -135,80 +135,64 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase @@ -135,80 +135,64 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase
135 assert_equal 1, ActionTracker::Record.count 135 assert_equal 1, ActionTracker::Record.count
136 end 136 end
137 137
138 - should 'notify with different trackers activity create with different targets' do 138 + should 'not group trackers activity of article\'s creation' do
139 ActionTracker::Record.delete_all 139 ActionTracker::Record.delete_all
140 profile = fast_create(Profile) 140 profile = fast_create(Profile)
141 TinyMceArticle.create! :name => 'bar', :profile_id => profile.id, :published => true 141 TinyMceArticle.create! :name => 'bar', :profile_id => profile.id, :published => true
142 TinyMceArticle.create! :name => 'another bar', :profile_id => profile.id, :published => true 142 TinyMceArticle.create! :name => 'another bar', :profile_id => profile.id, :published => true
143 - assert_equal 1, ActionTracker::Record.count  
144 - TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true  
145 assert_equal 2, ActionTracker::Record.count 143 assert_equal 2, ActionTracker::Record.count
  144 + TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
  145 + assert_equal 3, ActionTracker::Record.count
146 end 146 end
147 147
148 - should 'notify activity on update' do 148 + should 'not update activity on update of an article' do
149 ActionTracker::Record.delete_all 149 ActionTracker::Record.delete_all
150 - a = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true  
151 - assert_equal 1, ActionTracker::Record.count  
152 - a.name = 'foo'  
153 - a.save!  
154 - assert_equal 2, ActionTracker::Record.count 150 + profile = fast_create(Profile)
  151 + article = create(TinyMceArticle, :profile_id => profile.id)
  152 + time = article.activity.updated_at
  153 + Time.stubs(:now).returns(time + 1.day)
  154 + assert_no_difference ActionTracker::Record, :count do
  155 + article.name = 'foo'
  156 + article.save!
  157 + end
  158 + assert_equal time, article.activity.updated_at
155 end 159 end
156 160
157 - should 'notify with different trackers activity update with different targets' do 161 + should 'not create trackers activity when updating articles' do
158 ActionTracker::Record.delete_all 162 ActionTracker::Record.delete_all
159 a1 = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true 163 a1 = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
160 a2 = TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true 164 a2 = TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
161 - assert_equal 2, ActionTracker::Record.count  
162 - a1.name = 'foo'  
163 - a1.save!  
164 - assert_equal 3, ActionTracker::Record.count  
165 - a2.name = 'another foo'  
166 - a2.save!  
167 - assert_equal 4, ActionTracker::Record.count 165 + assert_no_difference ActionTracker::Record, :count do
  166 + a1.name = 'foo';a1.save!
  167 + a2.name = 'another foo';a2.save!
  168 + end
168 end 169 end
169 170
170 - should 'notify activity on destroy' do  
171 - ActionTracker::Record.delete_all  
172 - a = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true  
173 - assert_equal 1, ActionTracker::Record.count  
174 - a.destroy  
175 - assert_equal 2, ActionTracker::Record.count  
176 - end  
177 -  
178 - should 'notify different activities when destroy articles with diferrents targets' do 171 + should 'not notify when an article is destroyed' do
179 ActionTracker::Record.delete_all 172 ActionTracker::Record.delete_all
180 a1 = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true 173 a1 = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
181 a2 = TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true 174 a2 = TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
182 - assert_equal 2, ActionTracker::Record.count  
183 - a1.destroy  
184 - assert_equal 3, ActionTracker::Record.count  
185 - a2.destroy  
186 - assert_equal 4, ActionTracker::Record.count 175 + assert_no_difference ActionTracker::Record, :count do
  176 + a1.destroy
  177 + a2.destroy
  178 +end
187 end 179 end
188 180
189 - should "the tracker action target be defined as Community by custom_target method on articles'creation in communities" do 181 + should "the tracker action target be defined as the article on articles'creation in communities" do
190 ActionTracker::Record.delete_all 182 ActionTracker::Record.delete_all
191 community = fast_create(Community) 183 community = fast_create(Community)
192 p1 = Person.first 184 p1 = Person.first
193 community.add_member(p1) 185 community.add_member(p1)
194 assert p1.is_member_of?(community) 186 assert p1.is_member_of?(community)
195 article = TinyMceArticle.create! :name => 'test', :profile_id => community.id 187 article = TinyMceArticle.create! :name => 'test', :profile_id => community.id
196 - assert_equal true, article.published?  
197 - assert_equal true, article.notifiable?  
198 - assert_equal false, article.image?  
199 - assert_equal Community, article.profile.class  
200 - assert_equal Community, ActionTracker::Record.last.target.class 188 + assert_equal article, ActionTracker::Record.last.target
201 end 189 end
202 190
203 - should "the tracker action target be defined as person by custom_target method on articles'creation in profile" do 191 + should "the tracker action target be defined as the article on articles'creation in profile" do
204 ActionTracker::Record.delete_all 192 ActionTracker::Record.delete_all
205 person = Person.first 193 person = Person.first
206 article = TinyMceArticle.create! :name => 'test', :profile_id => person.id 194 article = TinyMceArticle.create! :name => 'test', :profile_id => person.id
207 - assert_equal true, article.published?  
208 - assert_equal true, article.notifiable?  
209 - assert_equal false, article.image?  
210 - assert_equal Person, article.profile.class  
211 - assert_equal person, ActionTracker::Record.last.target 195 + assert_equal article, ActionTracker::Record.last.target
212 end 196 end
213 197
214 should 'not notify activity if the article is not advertise' do 198 should 'not notify activity if the article is not advertise' do
@@ -226,7 +210,7 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase @@ -226,7 +210,7 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase
226 end 210 end
227 211
228 should "the common trackable conditions return the correct value" do 212 should "the common trackable conditions return the correct value" do
229 - a = TinyMceArticle.new 213 + a = TinyMceArticle.new(:profile => profile)
230 a.published = a.advertise = true 214 a.published = a.advertise = true
231 assert_equal true, a.published? 215 assert_equal true, a.published?
232 assert_equal true, a.notifiable? 216 assert_equal true, a.notifiable?
test/unit/uploaded_file_test.rb
@@ -231,10 +231,10 @@ class UploadedFileTest &lt; ActiveSupport::TestCase @@ -231,10 +231,10 @@ class UploadedFileTest &lt; ActiveSupport::TestCase
231 should 'return a thumbnail for images' do 231 should 'return a thumbnail for images' do
232 f = UploadedFile.new 232 f = UploadedFile.new
233 f.expects(:image?).returns(true) 233 f.expects(:image?).returns(true)
234 - f.expects(:full_filename).with(:thumb).returns(File.join(RAILS_ROOT, 'public', 'images', '0000', '0005', 'x.png')) 234 + f.expects(:full_filename).with(:display).returns(File.join(RAILS_ROOT, 'public', 'images', '0000', '0005', 'x.png'))
235 assert_equal '/images/0000/0005/x.png', f.thumbnail_path 235 assert_equal '/images/0000/0005/x.png', f.thumbnail_path
236 f = UploadedFile.new 236 f = UploadedFile.new
237 - f.stubs(:full_filename).with(:thumb).returns(File.join(RAILS_ROOT, 'public', 'images', '0000', '0005', 'x.png')) 237 + f.stubs(:full_filename).with(:display).returns(File.join(RAILS_ROOT, 'public', 'images', '0000', '0005', 'x.png'))
238 f.expects(:image?).returns(false) 238 f.expects(:image?).returns(false)
239 assert_nil f.thumbnail_path 239 assert_nil f.thumbnail_path
240 end 240 end
@@ -330,4 +330,11 @@ class UploadedFileTest &lt; ActiveSupport::TestCase @@ -330,4 +330,11 @@ class UploadedFileTest &lt; ActiveSupport::TestCase
330 assert_equal 'hello_world.php.txt', file.filename 330 assert_equal 'hello_world.php.txt', file.filename
331 end 331 end
332 332
  333 + should 'use itself as target for action tracker' do
  334 + p = fast_create(Gallery, :profile_id => @profile.id)
  335 + f = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent => p, :profile => @profile)
  336 + ta = f.activity
  337 + assert_equal f, ta.target
  338 + end
  339 +
333 end 340 end
vendor/plugins/access_control/lib/role_assignment.rb
@@ -9,10 +9,6 @@ class RoleAssignment &lt; ActiveRecord::Base @@ -9,10 +9,6 @@ class RoleAssignment &lt; ActiveRecord::Base
9 9
10 track_actions :add_member_in_community, :after_create, :if => Proc.new { |x| x.resource.is_a?(Community) && x.accessor.role_assignments.count(:conditions => { :resource_id => x.resource.id, :resource_type => 'Profile' }) == 1 }, :custom_user => :accessor, :custom_target => :resource 10 track_actions :add_member_in_community, :after_create, :if => Proc.new { |x| x.resource.is_a?(Community) && x.accessor.role_assignments.count(:conditions => { :resource_id => x.resource.id, :resource_type => 'Profile' }) == 1 }, :custom_user => :accessor, :custom_target => :resource
11 11
12 - track_actions :leave_community, :before_destroy, :keep_params => ["resource.name", "resource.url", "resource.profile_custom_icon"], :if => Proc.new { |x| x.resource.is_a?(Community) && x.accessor.role_assignments.count(:conditions => { :resource_id => x.resource.id, :resource_type => 'Profile' }) == 1 }, :custom_user => :accessor, :custom_target => :resource  
13 -  
14 - track_actions :remove_member_in_community, :before_destroy, :if => Proc.new { |x| x.resource.is_a?(Community) && x.accessor.role_assignments.count(:conditions => { :resource_id => x.resource.id, :resource_type => 'Profile' }) == 1 }, :custom_target => :resource, :custom_user => :accessor  
15 -  
16 def has_permission?(perm, res) 12 def has_permission?(perm, res)
17 return false unless role.has_permission?(perm.to_s) && (resource || is_global) 13 return false unless role.has_permission?(perm.to_s) && (resource || is_global)
18 return true if is_global 14 return true if is_global
vendor/plugins/action_tracker/lib/action_tracker_model.rb
@@ -24,6 +24,7 @@ module ActionTracker @@ -24,6 +24,7 @@ module ActionTracker
24 RECENT_DELAY = 30 24 RECENT_DELAY = 30
25 25
26 named_scope :recent, :conditions => ['created_at >= ?', RECENT_DELAY.days.ago] 26 named_scope :recent, :conditions => ['created_at >= ?', RECENT_DELAY.days.ago]
  27 + named_scope :visible, :conditions => { :visible => true }
27 28
28 def self.current_user_from_model 29 def self.current_user_from_model
29 u = new 30 u = new
vendor/plugins/action_tracker_has_comments/init.rb 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +# monkey patch to add comments on action_tracker
  2 +
  3 +ActionTracker::Record.module_eval do
  4 +
  5 + 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 +
  7 + def conditions_for_comments
  8 + type, id = (self.target_type == 'Article' ? ['Article', self.target_id] : [self.class.to_s, self.id])
  9 + "source_type = '#{type}' AND source_id = '#{id}'"
  10 + end
  11 +
  12 + def comments_as_thread
  13 + result = {}
  14 + root = []
  15 + self.comments.each do |c|
  16 + c.replies = []
  17 + result[c.id] ||= c
  18 + c.reply_of_id.nil? ? root << c : result[c.reply_of_id].replies << c
  19 + end
  20 + root
  21 + end
  22 +
  23 +end
vendor/plugins/active_record_counter_cache_on_polymorphic_association/init.rb 0 → 100644
@@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
  1 +# monkey patch to fix ActiveRecord bug
  2 +#
  3 +# https://rails.lighthouseapp.com/projects/8994/tickets/2452-counter_cache-not-updated-when-an-item-updates-its-polymorphic-owner
  4 +
  5 +#ActiveRecord::Associations.module_eval do
  6 +#
  7 +# def replace(record)
  8 +#
  9 +# counter_cache_name = @reflection.counter_cache_column
  10 +#
  11 +# if record.nil?
  12 +# if counter_cache_name && !@owner.new_record?
  13 +# record.class.base_class.decrement_counter(counter_cache_name, @owner[@reflection.primary_key_name]) if @owner[@reflection.primary_key_name]
  14 +# end
  15 +#
  16 +# @target = @owner[@reflection.primary_key_name] = @owner[@reflection.options[:foreign_type]] = nil
  17 +# else
  18 +# @target = (AssociationProxy === record ? record.target : record)
  19 +#
  20 +# if counter_cache_name && !@owner.new_record?
  21 +# record.class.base_class.increment_counter(counter_cache_name, record.id)
  22 +# record.class.base_class.decrement_counter(counter_cache_name, @owner[@reflection.primary_key_name]) if @owner[@reflection.primary_key_name]
  23 +# end
  24 +#
  25 +# @owner[@reflection.primary_key_name] = record.id
  26 +# @owner[@reflection.options[:foreign_type]] = record.class.base_class.name.to_s
  27 +#
  28 +#
  29 +# @updated = true
  30 +# end
  31 +#
  32 +# loaded
  33 +# record
  34 +# end
  35 +#
  36 +#end