Commit cb35a9eb295f8c940328c7b666cd10f0ae86cda6

Authored by Daniela Feitosa
2 parents 93103d85 c40d3969

Merge branch '0.37-rc2' into AI1826

Conflicts:
	test/unit/article_test.rb
Showing 86 changed files with 1631 additions and 771 deletions   Show diff stats
app/controllers/public/profile_controller.rb
... ... @@ -3,17 +3,15 @@ class ProfileController < PublicController
3 3 needs_profile
4 4 before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add]
5 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 8 helper TagsHelper
9 9  
10 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 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 15 end
18 16 @tags = profile.article_tags
19 17 unless profile.display_info_to?(user)
... ... @@ -180,22 +178,33 @@ class ProfileController < PublicController
180 178 @scrap.receiver= receiver
181 179 @tab_action = params[:tab_action]
182 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 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 199 end
191 200  
192 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 204 end
196 205  
197 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 208 render :partial => 'profile_network_activities', :locals => {:network_activities => @activities}
200 209 end
201 210  
... ... @@ -213,7 +222,11 @@ class ProfileController < PublicController
213 222 begin
214 223 raise if !can_edit_profile
215 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 230 render :text => _('Activity successfully removed.')
218 231 rescue
219 232 render :text => _('You could not remove this activity')
... ... @@ -285,6 +298,16 @@ class ProfileController < PublicController
285 298 end
286 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 311 protected
289 312  
290 313 def check_access_to_profile
... ...
app/helpers/application_helper.rb
... ... @@ -1217,15 +1217,12 @@ module ApplicationHelper
1217 1217 else _('1 minute')
1218 1218 end
1219 1219  
1220   - when 2..44 then _('%{distance} minutes') % { :distance => distance_in_minutes }
1221   - when 45..89 then _('about 1 hour')
1222   - when 90..1439 then _('about %{distance} hours') % { :distance => (distance_in_minutes.to_f / 60.0).round }
1223   - when 1440..2879 then _('1 day')
1224   - when 2880..43199 then _('%{distance} days') % { :distance => (distance_in_minutes / 1440).round }
1225   - when 43200..86399 then _('about 1 month')
1226   - when 86400..525599 then _('%{distance} months') % { :distance => (distance_in_minutes / 43200).round }
1227   - when 525600..1051199 then _('about 1 year')
1228   - else _('over %{distance} years') % { :distance => (distance_in_minutes / 525600).round }
  1220 + when 2..44 then _('%{distance} minutes ago') % { :distance => distance_in_minutes }
  1221 + when 45..89 then _('about 1 hour ago')
  1222 + when 90..1439 then _('about %{distance} hours ago') % { :distance => (distance_in_minutes.to_f / 60.0).round }
  1223 + when 1440..2879 then _('1 day ago')
  1224 + when 2880..10079 then _('%{distance} days ago') % { :distance => (distance_in_minutes / 1440).round }
  1225 + else show_time(from_time)
1229 1226 end
1230 1227 end
1231 1228  
... ...
app/helpers/forum_helper.rb
... ... @@ -42,9 +42,9 @@ module ForumHelper
42 42 def last_topic_update(article)
43 43 info = article.info_from_last_update
44 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 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 48 end
49 49 end
50 50  
... ...
app/models/action_tracker_notification.rb
... ... @@ -3,6 +3,8 @@ class ActionTrackerNotification < ActiveRecord::Base
3 3 belongs_to :profile
4 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 8 validates_presence_of :profile_id, :action_tracker_id
7 9 validates_uniqueness_of :action_tracker_id, :scope => :profile_id
8 10  
... ...
app/models/article.rb
... ... @@ -2,9 +2,7 @@ require 'hpricot'
2 2  
3 3 class Article < ActiveRecord::Base
4 4  
5   - track_actions :create_article, :after_create, :keep_params => [:name, :url], :if => Proc.new { |a| a.is_trackable? && !a.image? }, :custom_target => :action_tracker_target
6   - 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
7   - track_actions :remove_article, :before_destroy, :keep_params => [:name], :if => Proc.new { |a| a.is_trackable? }, :custom_target => :action_tracker_target
  5 + track_actions :create_article, :after_create, :keep_params => [:name, :url, :lead, :first_image], :if => Proc.new { |a| a.is_trackable? && !a.image? }
8 6  
9 7 # xss_terminate plugin can't sanitize array fields
10 8 before_save :sanitize_tag_list
... ... @@ -17,7 +15,7 @@ class Article &lt; ActiveRecord::Base
17 15  
18 16 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id'
19 17  
20   - has_many :comments, :dependent => :destroy, :order => 'created_at asc'
  18 + has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc'
21 19  
22 20 has_many :article_categorizations, :conditions => [ 'articles_categories.virtual = ?', false ]
23 21 has_many :categories, :through => :article_categorizations
... ... @@ -65,7 +63,7 @@ class Article &lt; ActiveRecord::Base
65 63 validate :translation_must_have_language
66 64  
67 65 def is_trackable?
68   - self.published? && self.notifiable? && self.advertise?
  66 + self.published? && self.notifiable? && self.advertise? && self.profile.public_profile
69 67 end
70 68  
71 69 def external_link=(link)
... ... @@ -135,7 +133,7 @@ class Article &lt; ActiveRecord::Base
135 133 before_update do |article|
136 134 article.advertise = true
137 135 end
138   -
  136 +
139 137 # retrieves all articles belonging to the given +profile+ that are not
140 138 # sub-articles of any other article.
141 139 named_scope :top_level_for, lambda { |profile|
... ... @@ -571,6 +569,21 @@ class Article &lt; ActiveRecord::Base
571 569 _('Created at: ')
572 570 end
573 571  
  572 + def activity
  573 + ActionTracker::Record.find_by_target_type_and_target_id 'Article', self.id
  574 + end
  575 +
  576 + def create_activity
  577 + if is_trackable? && !image?
  578 + save_action_for_verb 'create_article', [:name, :url, :lead, :first_image], Proc.new{}, :author
  579 + end
  580 + end
  581 +
  582 + def first_image
  583 + img = Hpricot(self.lead.to_s).search('img[@src]').first || Hpricot(self.body.to_s).search('img').first
  584 + img.nil? ? '' : img.attributes['src']
  585 + end
  586 +
574 587 private
575 588  
576 589 def sanitize_tag_list
... ...
app/models/comment.rb
1 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 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 9 belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id'
8 10 has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy
9 11 belongs_to :reply_of, :class_name => 'Comment', :foreign_key => 'reply_of_id'
... ... @@ -70,13 +72,25 @@ class Comment &lt; ActiveRecord::Base
70 72 after_save :notify_article
71 73 after_destroy :notify_article
72 74 def notify_article
73   - article.comments_updated
  75 + article.comments_updated if article.kind_of?(Article)
74 76 end
75 77  
76 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 80 Comment::Notifier.deliver_mail(comment)
79 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 94 end
81 95  
82 96 def replies
... ...
app/models/community.rb
... ... @@ -79,4 +79,8 @@ class Community &lt; Organization
79 79 {:title => __('Community Info and settings'), :icon => 'edit-profile-group'}
80 80 end
81 81  
  82 + def activities
  83 + 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")
  84 + end
  85 +
82 86 end
... ...
app/models/enterprise.rb
... ... @@ -181,4 +181,8 @@ class Enterprise &lt; Organization
181 181 true
182 182 end
183 183  
  184 + def activities
  185 + 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")
  186 + end
  187 +
184 188 end
... ...
app/models/event.rb
... ... @@ -120,6 +120,10 @@ class Event &lt; Article
120 120 true
121 121 end
122 122  
  123 + def notifiable?
  124 + true
  125 + end
  126 +
123 127 include Noosfero::TranslatableContent
124 128 include MaybeAddHttp
125 129  
... ...
app/models/external_feed.rb
... ... @@ -14,6 +14,7 @@ class ExternalFeed &lt; ActiveRecord::Base
14 14 article = TinyMceArticle.new(:name => title, :profile => blog.profile, :body => content, :published_at => date, :source => link, :profile => blog.profile, :parent => blog)
15 15 unless blog.children.exists?(:slug => article.slug)
16 16 article.save!
  17 + article.delay.create_activity
17 18 end
18 19 end
19 20  
... ...
app/models/forum.rb
... ... @@ -24,4 +24,14 @@ class Forum &lt; Folder
24 24 def self.icon_name(article = nil)
25 25 'forum'
26 26 end
  27 +
  28 + def notifiable?
  29 + true
  30 + end
  31 +
  32 + def first_paragraph
  33 + return '' if body.blank?
  34 + paragraphs = Hpricot(body).search('p')
  35 + paragraphs.empty? ? '' : paragraphs.first.to_html
  36 + end
27 37 end
... ...
app/models/person.rb
... ... @@ -435,6 +435,10 @@ class Person &lt; Profile
435 435 user.save!
436 436 end
437 437  
  438 + def activities
  439 + 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")
  440 + end
  441 +
438 442 protected
439 443  
440 444 def followed_by?(profile)
... ...
app/models/profile.rb
... ... @@ -822,6 +822,10 @@ private :generate_url, :url_options
822 822 name
823 823 end
824 824  
  825 + # Override in your subclasses
  826 + def activities
  827 + []
  828 + end
825 829 protected
826 830  
827 831 def followed_by?(person)
... ...
app/models/scrap.rb
... ... @@ -12,6 +12,7 @@ class Scrap &lt; ActiveRecord::Base
12 12 named_scope :not_replies, :conditions => {:scrap_id => nil}
13 13  
14 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 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 18 after_create do |scrap|
... ...
app/models/uploaded_file.rb
... ... @@ -4,7 +4,7 @@
4 4 # of the file itself is kept. (FIXME?)
5 5 class UploadedFile < Article
6 6  
7   - 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? }
  7 + 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
8 8  
9 9 include ShortFilename
10 10  
... ... @@ -25,7 +25,7 @@ class UploadedFile &lt; Article
25 25 end
26 26  
27 27 def thumbnail_path
28   - self.image? ? self.full_filename(:thumb).gsub(File.join(RAILS_ROOT, 'public'), '') : nil
  28 + self.image? ? self.full_filename(:display).gsub(File.join(RAILS_ROOT, 'public'), '') : nil
29 29 end
30 30  
31 31 def display_title
... ... @@ -140,4 +140,9 @@ class UploadedFile &lt; Article
140 140 def uploaded_file?
141 141 true
142 142 end
  143 +
  144 + def action_tracker_target
  145 + self
  146 + end
  147 +
143 148 end
... ...
app/views/profile/_add_member_in_community.rhtml 0 → 100644
... ... @@ -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,63 @@
  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) %> <%= txt2html comment.body %>
  21 + </div>
  22 + <div class="profile-activity-time">
  23 + <%= time_ago_as_sentence(comment.created_at) %>
  24 + </div>
  25 + </div>
  26 +
  27 + <% if logged_in? && (user == profile || user == comment.author || user.has_permission?(:moderate_comments, profile)) %>
  28 + <% button_bar(:style => 'float: right; margin-top: 0px;') do %>
  29 + <%= 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?')) %>
  30 + <% end %>
  31 + <% end %>
  32 + <br style="clear: both;" />
  33 +
  34 + <div class="comment_reply post_comment_box closed">
  35 + <% if @comment && @comment.errors.any? && @comment.reply_of_id.to_i == comment.id %>
  36 + <%= error_messages_for :comment %>
  37 + <script type="text/javascript">
  38 + jQuery(function() {
  39 + document.location.href = '#<%= comment.anchor %>';
  40 + add_comment_reply_form('#comment-reply-to-<%= comment.id %>', <%= comment.id %>);
  41 + });
  42 + </script>
  43 + <% end %>
  44 + <%= report_abuse(comment.author, :comment_link, comment) if comment.author %>
  45 + <%= link_to_function _('Reply'),
  46 + "var f = add_comment_reply_form(this, %s); f.find('input[name=comment[title]], textarea').val(''); return false" % comment.id,
  47 + :class => 'comment-footer comment-footer-link comment-footer-hide',
  48 + :id => 'comment-reply-to-' + comment.id.to_s
  49 + %>
  50 + </div>
  51 +
  52 + </div>
  53 +
  54 + <% unless comment.replies.blank? %>
  55 + <ul class="comment-replies">
  56 + <% comment.replies.each do |reply| %>
  57 + <%= render :partial => 'comment', :locals => { :comment => reply } %>
  58 + <% end %>
  59 + </ul>
  60 + <% end %>
  61 +
  62 + </div>
  63 +</li>
... ...
app/views/profile/_create_article.rhtml 0 → 100644
... ... @@ -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 + <b><%= link_to(activity.params['name'], activity.params['url']) %></b>
  11 + <span title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-new<%= activity.target.class.icon_name %>'></span><br />
  12 + <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(activity.params['lead']).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 @@
  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 @@
  1 +_add_member_in_community.rhtml
0 2 \ No newline at end of file
... ...
app/views/profile/_leave_comment_on_activity.rhtml 0 → 100644
... ... @@ -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 @@
  1 +_leave_scrap.rhtml
0 2 \ No newline at end of file
... ...
app/views/profile/_new_friendship.rhtml 0 → 120000
... ... @@ -0,0 +1 @@
  1 +_add_member_in_community.rhtml
0 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   -<% 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 @@
  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 @@
  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 @@
  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 @@
  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 %>
  11 +</ul>
  12 +
  13 +<%= render :partial => 'profile_comment_form', :locals => { :activity => activity, :tab_action => tab_action } %>
... ...
app/views/profile/_profile_network.rhtml
1 1 <h3><%= _("%s's network activity") % @profile.name %></h3>
2   -<ul>
  2 +<ul id='network-activities' class='profile-activities'>
3 3 <%= render :partial => 'profile_network_activities', :locals => {:network_activities => @network_activities} %>
4 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 4 <% if network_activities.current_page < network_activities.total_pages %>
32 5 <div id='profile_network_activities_page_<%= network_activities.current_page %>'>
33 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 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 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 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 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 26 <% scrap.replies.map do |reply| %>
19 27 <%= render :partial => 'profile_scrap', :locals => {:scrap => reply} %>
20 28 <% end %>
21 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 31 <hr />
50 32 </li>
... ...
app/views/profile/_profile_scrap_reply_form.rhtml 0 → 100644
... ... @@ -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 1 <h3><%= _("%s's wall") % @profile.name %></h3>
2 2 <div id='leave_scrap'>
3 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 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 7 <% end %>
8 8 </div>
9 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 12 </ul>
... ...
app/views/profile/_update_article.rhtml 0 → 100644
... ... @@ -0,0 +1 @@
  1 +NAO É PRA APARECER
... ...
app/views/profile/_upload_image.rhtml 0 → 100644
... ... @@ -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 17  
18 18 <% if @profile.public? || (logged_in? && current_person.follows?(@profile)) %>
19 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 46 </table>
22 47 <% end %>
... ...
app/views/tasks/_abuse_complaint_accept_details.rhtml
... ... @@ -2,7 +2,7 @@
2 2 <% task.abuse_reports.each do |abuse_report| %>
3 3 <div>
4 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 6 <% if !abuse_report.content.blank? %>
7 7 <button class="display-abuse-report-details" data-report="<%=abuse_report.id%>"><%=_('View details')%></button>
8 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 5 ActionTrackerConfig.verbs = {
6 6  
7 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 11 :new_friendship => {
... ... @@ -33,24 +22,11 @@ ActionTrackerConfig.verbs = {
33 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 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 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 30 :leave_scrap => {
55 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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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
... ...
db/schema.rb
... ... @@ -29,6 +29,8 @@ ActiveRecord::Schema.define(:version =&gt; 20120307200651) do
29 29 t.string "verb"
30 30 t.datetime "created_at"
31 31 t.datetime "updated_at"
  32 + t.integer "comments_count", :default => 0
  33 + t.boolean "visible", :default => true
32 34 end
33 35  
34 36 add_index "action_tracker", ["target_id", "target_type"], :name => "index_action_tracker_on_dispatcher_id_and_dispatcher_type"
... ... @@ -198,7 +200,7 @@ ActiveRecord::Schema.define(:version =&gt; 20120307200651) do
198 200 create_table "comments", :force => true do |t|
199 201 t.string "title"
200 202 t.text "body"
201   - t.integer "article_id"
  203 + t.integer "source_id"
202 204 t.integer "author_id"
203 205 t.string "name"
204 206 t.string "email"
... ... @@ -206,6 +208,7 @@ ActiveRecord::Schema.define(:version =&gt; 20120307200651) do
206 208 t.integer "reply_of_id"
207 209 t.string "ip_address"
208 210 t.boolean "spam"
  211 + t.string "source_type"
209 212 end
210 213  
211 214 create_table "contact_lists", :force => true do |t|
... ...
lib/notify_activity_to_profiles_job.rb
1 1 class NotifyActivityToProfilesJob < Struct.new(:tracked_action_id)
2 2 NOTIFY_ONLY_COMMUNITY = [
3   - 'add_member_in_community',
4   - 'remove_member_in_community',
  3 + 'add_member_in_community'
5 4 ]
6 5  
7 6 NOT_NOTIFY_COMMUNITY = [
8   - 'join_community',
9   - 'leave_community',
  7 + 'join_community'
10 8 ]
11 9 def perform
12 10 return unless ActionTracker::Record.exists?(tracked_action_id)
... ... @@ -19,6 +17,7 @@ class NotifyActivityToProfilesJob &lt; Struct.new(:tracked_action_id)
19 17  
20 18 ActionTrackerNotification.create(:profile_id => tracked_action.user.id, :action_tracker_id => tracked_action.id)
21 19  
  20 + #Notify all friends
22 21 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 22  
24 23 if target.is_a?(Community)
... ... @@ -26,5 +25,12 @@ class NotifyActivityToProfilesJob &lt; Struct.new(:tracked_action_id)
26 25  
27 26 ActionTrackerNotification.create(:profile_id => target.id, :action_tracker_id => tracked_action.id) unless NOT_NOTIFY_COMMUNITY.include?(tracked_action.verb)
28 27 end
  28 +
  29 + if target.is_a?(Article) && target.profile.is_a?(Community)
  30 + 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.profile.id}")
  31 +
  32 + ActionTrackerNotification.create(:profile_id => target.profile.id, :action_tracker_id => tracked_action.id) unless NOT_NOTIFY_COMMUNITY.include?(tracked_action.verb)
  33 + end
  34 +
29 35 end
30 36 end
... ...
public/designs/icons/tango/style.css
... ... @@ -91,7 +91,7 @@
91 91 .icon-lock { background-image: url(Tango/16x16/actions/lock.png) }
92 92 .icon-chat { background-image: url(Tango/16x16/apps/internet-group-chat.png); background-repeat: no-repeat }
93 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 95 .icon-forum { background-image: url(Tango/16x16/apps/system-users.png) }
96 96 .icon-gallery { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) }
97 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 24 #profile-wall ul {
25 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,54 @@
23 23 #profile-wall ul {
24 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 span a,
  59 +#profile-network li.profile-activity-item.upload_image span a {
  60 + background-image: url(/images/gallery-image-activity-border-onecol.png);
  61 +}
  62 +
  63 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  64 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span img,
  65 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a,
  66 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  67 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span img,
  68 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a {
  69 + width: 549px;
  70 + height: 254px;
  71 +}
  72 +
  73 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a,
  74 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a {
  75 + background-image: url(/images/gallery-image-activity-border-big-onecol.png);
  76 +}
... ...
public/designs/templates/rightbar/stylesheets/style.css
... ... @@ -23,3 +23,54 @@
23 23 #profile-wall ul {
24 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 span a,
  59 +#profile-network li.profile-activity-item.upload_image span a {
  60 + background-image: url(/images/gallery-image-activity-border-onecol.png);
  61 +}
  62 +
  63 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  64 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span img,
  65 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a,
  66 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  67 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span img,
  68 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a {
  69 + width: 549px;
  70 + height: 254px;
  71 +}
  72 +
  73 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a,
  74 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a {
  75 + background-image: url(/images/gallery-image-activity-border-big-onecol.png);
  76 +}
... ...
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,3 +711,37 @@ Array.min = function(array) {
711 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 +});
... ...
public/stylesheets/application.css
... ... @@ -268,6 +268,12 @@ td.field-name {
268 268 vertical-align: top;
269 269 }
270 270  
  271 +table.profile .ui-tabs .ui-tabs-panel {
  272 + border-left: 0;
  273 + border-right: 0;
  274 + border-bottom: 0;
  275 +}
  276 +
271 277 table.profile th {
272 278 border-bottom: 2px solid #eeeeec;
273 279 padding: 10px 0px 0px 0px;
... ... @@ -1429,7 +1435,8 @@ a.comment-picture {
1429 1435 border-radius: 5px;
1430 1436 }
1431 1437  
1432   -.comment-replies .article-comment-inner {
  1438 +.comment-replies .article-comment-inner,
  1439 +.scrap-replies {
1433 1440 border: 1px solid #fff;
1434 1441 padding: 0;
1435 1442 -moz-border-radius: 4px;
... ... @@ -5883,8 +5890,183 @@ h1#agenda-title {
5883 5890  
5884 5891 #profile-activity li, #profile-network li, #profile-wall li {
5885 5892 display: block;
5886   - padding: 0;
5887   - margin-bottom: 8px;
  5893 + padding: 3px;
  5894 + margin-bottom: 3px;
  5895 + background-color: #fff;
  5896 + border-bottom: 1px solid #e8e8e8;
  5897 + position: relative;
  5898 +}
  5899 +
  5900 +#profile-activity li, #profile-network li, #profile-wall li {
  5901 +}
  5902 +
  5903 +.profile-activity-lead img {
  5904 + width: 124px;
  5905 + float: left;
  5906 + margin-right: 5px;
  5907 +}
  5908 +
  5909 +.profile-activity-lead {
  5910 + width: 370px;
  5911 + display: inline-block;
  5912 + text-align: left;
  5913 + margin: 5px 0;
  5914 +}
  5915 +
  5916 +.profile-activity-article-forum .profile-activity-lead {
  5917 + height: 50px;
  5918 + width: 297px;
  5919 + padding-left: 60px;
  5920 + float: none;
  5921 + overflow: hidden;
  5922 + background: transparent url(/images/forum-activity-bg.png) left center no-repeat;
  5923 +}
  5924 +
  5925 +.profile-activity-article-forum .see-forum {
  5926 + text-align: right;
  5927 +}
  5928 +
  5929 +.profile-activity-article-forum .see-forum a {
  5930 + background: transparent url(/images/forum-activity-icon.png) left center no-repeat;
  5931 + padding-left: 30px;
  5932 + font-weight: bold;
  5933 + color: #dadada !important;
  5934 + text-decoration: none;
  5935 + font-size: 11px;
  5936 +}
  5937 +
  5938 +.profile-activity-article-forum .profile-activity-lead b {
  5939 + font-weight: normal;
  5940 +}
  5941 +
  5942 +#profile-activity li a, #profile-network li a, #profile-wall li a,
  5943 +#profile-wall .profile-wall-send-reply {
  5944 + color: #333;
  5945 +}
  5946 +
  5947 +#profile-activity li a, #profile-network li a, #profile-wall li a {
  5948 + font-weight: bold;
  5949 + text-decoration: none;
  5950 +}
  5951 +
  5952 +#profile-activity li a:hover, #profile-network li a:hover, #profile-wall li a:hover {
  5953 + text-decoration: underline;
  5954 +}
  5955 +
  5956 +.profile-activity-text {
  5957 + margin: 0;
  5958 + color: #000;
  5959 +}
  5960 +
  5961 +#profile-wall li.profile-activity-item.upload_image span,
  5962 +#profile-wall li.profile-activity-item.upload_image span a,
  5963 +#profile-network li.profile-activity-item.upload_image span,
  5964 +#profile-network li.profile-activity-item.upload_image span a {
  5965 + width: 110px;
  5966 + height: 100px;
  5967 + display: block;
  5968 + overflow: hidden;
  5969 + position: absolute;
  5970 +}
  5971 +
  5972 +#profile-wall li.profile-activity-item.upload_image span a img,
  5973 +#profile-network li.profile-activity-item.upload_image span a img {
  5974 + width: 110px;
  5975 + height: 100px;
  5976 +}
  5977 +
  5978 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  5979 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a,
  5980 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a img,
  5981 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span,
  5982 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a img {
  5983 + width: 383px;
  5984 + height: auto;
  5985 +}
  5986 +
  5987 +#profile-wall li.profile-activity-item.upload_image span img,
  5988 +#profile-network li.profile-activity-item.upload_image span img {
  5989 + display: block;
  5990 +}
  5991 +
  5992 +#profile-wall li.profile-activity-item.upload_image span,
  5993 +#profile-network li.profile-activity-item.upload_image span {
  5994 + position: relative;
  5995 + display: inline-block;
  5996 + margin: 5px 0px 0px 5px;
  5997 +}
  5998 +
  5999 +#profile-wall li.profile-activity-item.upload_image .profile-activity-text span,
  6000 +#profile-network li.profile-activity-item.upload_image .profile-activity-text span {
  6001 + border: 4px solid #D2D2D2;
  6002 + border-radius: 4px;
  6003 + -webkit-border-radius: 4px;
  6004 + -moz-border-radius: 4px;
  6005 +}
  6006 +
  6007 +#profile-wall li.profile-activity-item.upload_image span a,
  6008 +#profile-network li.profile-activity-item.upload_image span a {
  6009 + Xbackground: transparent url(/images/gallery-image-activity-border.png) center center no-repeat;
  6010 + text-indent: -5000em;
  6011 +}
  6012 +
  6013 +#profile-wall li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a,
  6014 +#profile-network li.profile-activity-item.upload_image .activity-gallery-images-count-1 span a {
  6015 + Xbackground-image: url(/images/gallery-image-activity-border-big.png);
  6016 + position: relative;
  6017 +}
  6018 +
  6019 +#profile-wall li.profile-activity-item.upload_image .article-comment span,
  6020 +#profile-wall li.profile-activity-item.upload_image .profile-wall-actions span,
  6021 +#profile-network li.profile-activity-item.upload_image .article-comment span,
  6022 +#profile-network li.profile-activity-item.upload_image .profile-wall-actions span {
  6023 + display: inline;
  6024 + position: static;
  6025 + margin: 0;
  6026 + float: none;
  6027 + width: auto;
  6028 + height: auto;
  6029 + font-weight: normal;
  6030 +}
  6031 +
  6032 +#profile-wall li.profile-activity-item ul.profile-wall-activities-comments,
  6033 +#profile-network li.profile-activity-item ul.profile-wall-activities-comments {
  6034 + margin-top: 0;
  6035 +}
  6036 +
  6037 +#profile-wall li.profile-activity-item.upload_image .profile-activity-text,
  6038 +#profile-network li.profile-activity-item.upload_image .profile-activity-text,
  6039 +#profile-network li.profile-activity-item ul.profile-wall-activities-comments {
  6040 + padding-left: 50px;
  6041 +}
  6042 +
  6043 +#profile-wall li.profile-activity-item.join_community .profile-activity-text a img,
  6044 +#profile-wall li.profile-activity-item.new_friendship .profile-activity-text a img,
  6045 +#profile-network li.profile-activity-item.join_community .profile-activity-text a img,
  6046 +#profile-network li.profile-activity-item.new_friendship .profile-activity-text a img {
  6047 + margin: 5px 5px 0 0;
  6048 + padding: 1px;
  6049 + border: 1px solid #ccc;
  6050 +}
  6051 +
  6052 +#profile-wall li.profile-activity-item.create_article,
  6053 +#profile-netowrk li.profile-activity-item.create_article {
  6054 + position: relative;
  6055 +}
  6056 +
  6057 +.profile-activity-icon {
  6058 + width: 16px;
  6059 + height: 16px;
  6060 + display: inline-block;
  6061 + position: absolute;
  6062 + top: 0px;
  6063 + right: 0px;
  6064 +}
  6065 +
  6066 +#profile-activity .profile-wall-scrap-replies li,
  6067 +#profile-network .profile-wall-scrap-replies li,
  6068 +#profile-wall .profile-wall-scrap-replies li {
  6069 + border-bottom: none;
5888 6070 }
5889 6071  
5890 6072 #profile-activity .profile-activity-image, #profile-network .profile-network-image, #profile-wall .profile-wall-image {
... ... @@ -5898,12 +6080,12 @@ h1#agenda-title {
5898 6080  
5899 6081 #profile-activity .profile-activity-description, #profile-network .profile-network-description, #profile-wall .profile-wall-description {
5900 6082 float: left;
5901   - min-height: 60px;
  6083 + Xmin-height: 60px;
5902 6084 margin: 0;
5903 6085 padding: 0;
5904 6086 border: 1px solid #ccc;
5905 6087 overflow: hidden;
5906   - background-color: #fff;
  6088 + Xbackground-color: #fff;
5907 6089 position: relative;
5908 6090 }
5909 6091  
... ... @@ -5918,7 +6100,7 @@ h1#agenda-title {
5918 6100 }
5919 6101  
5920 6102 #profile-activity .profile-activity-description .icon-delete,
5921   -#profile-network .profile-network-description .icon-delete,
  6103 +#profile-network .profile-activity-description .icon-delete,
5922 6104 #profile-wall .profile-wall-description .icon-delete {
5923 6105 position: absolute;
5924 6106 top: 4px;
... ... @@ -5930,24 +6112,56 @@ h1#agenda-title {
5930 6112 -moz-border-radius: 3px;
5931 6113 }
5932 6114  
5933   -#profile-activity .profile-activity-text, #profile-network .profile-network-text, #profile-wall .profile-wall-text {
  6115 +#profile-activity .profile-activity-text,
  6116 +#profile-network .profile-activity-text,
  6117 +#profile-wall .profile-wall-text {
5934 6118 font-size: 13px;
5935   - margin: 5px;
  6119 + margin: 2px 5px;
5936 6120 }
5937 6121  
5938 6122 #profile-wall .profile-wall-text {
5939 6123 padding-top: 0;
5940 6124 }
5941 6125  
5942   -#profile-activity .profile-activity-time, #profile-network .profile-network-time, #profile-wall .profile-wall-time {
  6126 +.profile-activities .profile-activity-time,
  6127 +#profile-network .profile-activity-time,
  6128 +#profile-wall .profile-wall-time {
5943 6129 font-size: 11px;
5944 6130 margin: 5px;
5945 6131 color: #babdb6;
  6132 + text-align: right;
  6133 +}
  6134 +
  6135 +#profile-wall .profile-wall-send-reply,
  6136 +.profile-activities .profile-activity-time,
  6137 +#profile-network .profile-activity-time,
  6138 +#profile-wall .profile-wall-time,
  6139 +.profile-wall-actions a {
  6140 + display: block;
  6141 + float: right;
  6142 + font-size: 10px;
  6143 + margin: 2px 0 3px 10px;
  6144 + color: #ccc;
  6145 + padding: 0;
  6146 +}
  6147 +
  6148 +#profile-wall li .profile-wall-actions a,
  6149 +#profile-activity li .profile-wall-actions a,
  6150 +#profile-network li .profile-wall-actions a,
  6151 +#profile-wall .profile-wall-send-reply a {
  6152 + text-decoration: none;
  6153 + color: #333;
  6154 + font-weight: normal;
  6155 +}
  6156 +
  6157 +#profile-wall li .profile-wall-actions a:hover,
  6158 +#profile-network li .profile-wall-actions a:hover,
  6159 +#profile-wall .profile-wall-send-reply a:hover {
  6160 + text-decoration: underline;
5946 6161 }
5947 6162  
5948 6163 #profile-activity hr, #profile-network hr, #profile-wall hr {
5949   - clear: both;
5950   - border: 0;
  6164 + display: none;
5951 6165 }
5952 6166  
5953 6167 #profile-activity .profile-activity-send-message, #profile-network .profile-network-send-message, #profile-wall .profile-wall-send-message {
... ... @@ -6029,11 +6243,13 @@ h1#agenda-title {
6029 6243 .profile-network-time,
6030 6244 .profile-network-description {
6031 6245 padding-left: 5px;
  6246 + margin: 5px;
6032 6247 }
6033 6248  
6034 6249 .profile-network-sender,
  6250 +.profile-activity-sender,
6035 6251 .profile-wall-sender {
6036   - margin: 2px 0;
  6252 + margin: 0;
6037 6253 }
6038 6254  
6039 6255 #profile-activity .profile-activity-time,
... ... @@ -6050,6 +6266,13 @@ h1#agenda-title {
6050 6266 overflow: hidden;
6051 6267 }
6052 6268  
  6269 +#profile-network li textarea:focus,
  6270 +#profile-wall li textarea:focus {
  6271 + background-position: left center;
  6272 + background-repeat: no-repeat;
  6273 + text-indent: 28px;
  6274 +}
  6275 +
6053 6276 .profile-network-message,
6054 6277 .profile-wall-message {
6055 6278 margin: 0;
... ... @@ -6084,21 +6307,25 @@ h1#agenda-title {
6084 6307 }
6085 6308  
6086 6309 .profile-send-reply {
6087   - background-color: #eee;
6088   - border: 1px solid #aaa;
6089   - padding: 2px;
6090   - padding-left: 20px;
6091   - background-repeat: no-repeat;
6092   - background-position: 2px center;
  6310 + xbackground-color: #eee;
  6311 + xborder: 1px solid #aaa;
  6312 + xpadding: 2px;
  6313 + xpadding-left: 20px;
  6314 + xbackground-repeat: no-repeat;
  6315 + xbackground-position: 2px center;
6093 6316 color: #aaa;
6094   - text-decoration: none;
6095   - margin-left: 8px;
  6317 + Xtext-decoration: none;
  6318 + Xmargin-left: 8px;
6096 6319 }
6097 6320  
6098 6321 #content .profile-send-reply:hover {
6099 6322 text-decoration: none;
6100 6323 }
6101 6324  
  6325 +#profile-wall .profile-wall-actions {
  6326 + text-align: right;
  6327 +}
  6328 +
6102 6329 #profile-wall .profile-wall-scrap-replies .profile-wall-description {
6103 6330 background: transparent;
6104 6331 }
... ... @@ -6116,6 +6343,104 @@ h1#agenda-title {
6116 6343 background: transparent;
6117 6344 }
6118 6345  
  6346 +#profile-wall ul.profile-wall-activities-comments,
  6347 +#profile-network ul.profile-wall-activities-comments {
  6348 + margin-top: 35px;
  6349 + padding-left: 50px;
  6350 + width: auto;
  6351 +}
  6352 +
  6353 +#profile-wall ul.profile-wall-activities-comments ul,
  6354 +#profile-network ul.profile-wall-activities-comments ul {
  6355 + padding-left: 0px;
  6356 +}
  6357 +
  6358 +#profile-wall .profile-wall-activities-comments li,
  6359 +#profile-network .profile-wall-activities-comments li {
  6360 + background: #f0f0f1;
  6361 + border-bottom: 1px solid #d2d2d2 !important;
  6362 + border-top: 1px solid #fff;
  6363 + margin-bottom: 0;
  6364 +}
  6365 +
  6366 +#profile-wall .profile-wall-activities-comments img,
  6367 +#profile-network .profile-wall-activities-comments img {
  6368 + width: 33px;
  6369 + height: 33px;
  6370 +}
  6371 +
  6372 +#profile-wall .profile-wall-activities-comments .comment_reply,
  6373 +#profile-wall .profile-wall-activities-comments h4,
  6374 +#profile-network .profile-wall-activities-comments .comment_reply,
  6375 +#profile-network .profile-wall-activities-comments h4 {
  6376 + display: none;
  6377 +}
  6378 +
  6379 +#profile-wall .profile-wall-activities-comments .comment-picture,
  6380 +#profile-network .profile-wall-activities-comments .comment-picture {
  6381 + width: 33px;
  6382 + margin-right: 10px;
  6383 +}
  6384 +
  6385 +#profile-wall .profile-wall-activities-comments .comment-text p,
  6386 +#profile-network .profile-wall-activities-comments .comment-text p {
  6387 + margin: 0;
  6388 +}
  6389 +
  6390 +#profile-wall .profile-wall-activities-comments .profile-activity-time,
  6391 +#profile-network .profile-wall-activities-comments .profile-activity-time {
  6392 + clear: both;
  6393 +}
  6394 +
  6395 +#profile-wall .profile-wall-activities-comments .comment-details,
  6396 +#profile-network .profile-wall-activities-comments .comment-details {
  6397 + padding: 0;
  6398 +}
  6399 +
  6400 +#profile-wall .profile-wall-activities-comments .article-comment .button-bar,
  6401 +#profile-network .profile-wall-activities-comments .article-comment .button-bar {
  6402 + float: right;
  6403 + padding: 0;
  6404 + text-align: right;
  6405 + position: static;
  6406 + clear: none;
  6407 + display: none;
  6408 +}
  6409 +
  6410 +#profile-wall .profile-wall-activities-comments .article-comment:hover .button-bar,
  6411 +#profile-network .profile-wall-activities-comments .article-comment:hover .button-bar {
  6412 + display: block;
  6413 +}
  6414 +
  6415 +#profile-wall .profile-wall-activities-comments .article-comment .button-bar a.button,
  6416 +#profile-network .profile-wall-activities-comments .article-comment .button-bar a.button {
  6417 + background: transparent;
  6418 + border: 0;
  6419 + height: auto;
  6420 + line-height: auto;
  6421 + color: #333;
  6422 + text-decoration: none;
  6423 + font-size: 10px;
  6424 + padding: 0;
  6425 + margin: 0;
  6426 + display: inline;
  6427 + position: static;
  6428 + float: none;
  6429 + font-weight: normal;
  6430 +}
  6431 +
  6432 +#profile-wall .profile-wall-activities-comments .article-comment .button-bar a.button:hover,
  6433 +#profile-network .profile-wall-activities-comments .article-comment .button-bar a.button:hover {
  6434 + text-decoration: underline;
  6435 +}
  6436 +
  6437 +#profile-wall .profile-wall-activities-comments .article-comment .button-bar .button span,
  6438 +#profile-network .profile-wall-activities-comments .article-comment .button-bar .button span {
  6439 + display: inline;
  6440 + position: static;
  6441 + display: inline;
  6442 +}
  6443 +
6119 6444 /* friends online {{{ */
6120 6445  
6121 6446 #chat-online-users {
... ... @@ -6245,18 +6570,37 @@ h1#agenda-title {
6245 6570 }
6246 6571  
6247 6572 #profile-wall .comment-balloon-content {
6248   - padding: 3px 0 3px 15px;
  6573 + padding: 3px 0px;
6249 6574 }
6250 6575  
6251 6576 .profile-wall-reply {
6252 6577 margin: 0;
6253 6578 }
6254 6579  
  6580 +.profile-wall-reply-form {
  6581 + display: block;
  6582 + background: #f0f0f1;
  6583 + border-bottom: 1px solid #d2d2d2;
  6584 + border-top: 1px solid #fff;
  6585 + margin-left: 50px;
  6586 + padding: 0 5px;
  6587 +}
  6588 +
  6589 +.scrap-replies .profile-wall-reply-form {
  6590 + margin-left: 0px;
  6591 +}
  6592 +
6255 6593 .profile-wall-scrap-replies {
6256 6594 float: right;
6257 6595 margin-right: 2px;
6258 6596 }
6259 6597  
  6598 +.view-all-comments {
  6599 + clear: both;
  6600 + margin-left: 50px;
  6601 + padding-left: 20px;
  6602 +}
  6603 +
6260 6604 /* Profile activity relative dimensions */
6261 6605  
6262 6606 #leave_scrap {
... ... @@ -6267,18 +6611,36 @@ h1#agenda-title {
6267 6611 width: 98%;
6268 6612 }
6269 6613  
6270   -#profile-activity .profile-activity-image, #profile-network .profile-network-image, #profile-wall .profile-wall-image {
6271   - width: 19%;
  6614 +.profile-activities .profile-activity-image,
  6615 +#profile-network .profile-activity-image,
  6616 +#profile-wall .profile-wall-image {
  6617 + width: 50px;
  6618 + margin: 5px;
  6619 + float: left;
6272 6620 }
6273 6621  
6274   -#profile-activity .profile-activity-description, #profile-network .profile-network-description, #profile-wall .profile-wall-description {
6275   - width: 80%;
  6622 +#profile-activity .profile-activity-description,
  6623 +#profile-network .profile-activity-description,
  6624 +#profile-wall .profile-wall-description {
6276 6625 word-wrap: break-word;
6277 6626 }
6278 6627  
  6628 +#profile-wall textarea {
  6629 + width: 375px;
  6630 +}
  6631 +
  6632 +#profile-wall li textarea {
  6633 + width: 388px;
  6634 +}
  6635 +
6279 6636 #profile-wall .profile-wall-scrap-replies textarea,
6280   -#profile-network textarea, #profile-wall textarea {
6281   - width: 99%;
  6637 +#profile-network textarea, #profile-wall textarea,
  6638 +#profile-wall li .profile-wall-reply-form textarea {
  6639 + width: 98%;
  6640 +}
  6641 +
  6642 +#profile-wall #leave_scrap textarea {
  6643 + width: 442px;
6282 6644 }
6283 6645  
6284 6646 .profile-wall-scrap-replies {
... ...
test/factories.rb
... ... @@ -372,7 +372,7 @@ module Noosfero::Factory
372 372 ###############################################
373 373  
374 374 def defaults_for_scrap(params = {})
375   - { :content => 'soment content ', :sender_id => 1, :receiver_id => 1, :created_at => DateTime.now }.merge(params)
  375 + { :content => 'some content ', :sender_id => 1, :receiver_id => 1, :created_at => DateTime.now }.merge(params)
376 376 end
377 377  
378 378 ###############################################
... ... @@ -440,7 +440,7 @@ module Noosfero::Factory
440 440  
441 441 def defaults_for_comment(params = {})
442 442 name = "comment_#{rand(1000)}"
443   - { :title => name, :body => "my own comment", :article_id => 1 }.merge(params)
  443 + { :title => name, :body => "my own comment", :source_id => 1 }.merge(params)
444 444 end
445 445  
446 446 ###############################################
... ...
test/functional/profile_controller_test.rb
... ... @@ -714,25 +714,23 @@ class ProfileControllerTest &lt; ActionController::TestCase
714 714 assert_no_tag :tag => 'p', :content => 'A scrap'
715 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 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 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 731 login_as(profile.identifier)
733 732 get :index, :profile => p1.identifier
734   - assert_not_nil assigns(:activities)
735   - assert_equal [a1], assigns(:activities)
  733 + assert_nil assigns(:activities)
736 734 end
737 735  
738 736 should 'see the activities_items paginated' do
... ... @@ -744,26 +742,27 @@ class ProfileControllerTest &lt; ActionController::TestCase
744 742 assert_equal 30, assigns(:activities).count
745 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 746 p2= fast_create(Person)
750   - assert !p1.is_a_friend?(p2)
  747 + assert !profile.is_a_friend?(p2)
751 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 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 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 762 login_as(profile.identifier)
764   - get :index, :profile => p1.identifier
  763 + get :index, :profile => p3.identifier
765 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 766 end
768 767  
769 768 should 'see all the activities in the current profile network' do
... ... @@ -931,13 +930,29 @@ class ProfileControllerTest &lt; ActionController::TestCase
931 930 assert_template 'index'
932 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 942 get :index, :profile => p1.identifier
937   - assert_equal [], assigns(:wall_items)
  943 + assert_nil assigns(:activities)
938 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 956 p1 = ActionTracker::Record.current_user_from_model
942 957 p2 = fast_create(Person)
943 958 p3 = fast_create(Person)
... ... @@ -952,10 +967,10 @@ class ProfileControllerTest &lt; ActionController::TestCase
952 967 @controller.stubs(:current_user).returns(user)
953 968 Person.any_instance.stubs(:follows?).returns(true)
954 969 get :index, :profile => p1.identifier
955   - assert_equal [s2,s3], assigns(:wall_items)
  970 + assert_equal [s2,s3], assigns(:activities)
956 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 974 c = fast_create(Community)
960 975 p1 = fast_create(Person)
961 976 p2 = fast_create(Person)
... ... @@ -971,12 +986,12 @@ class ProfileControllerTest &lt; ActionController::TestCase
971 986 @controller.stubs(:current_user).returns(user)
972 987 Person.any_instance.stubs(:follows?).returns(true)
973 988 get :index, :profile => c.identifier
974   - assert_equal [s2,s3], assigns(:wall_items)
  989 + assert_equal [s2,s3], assigns(:activities)
975 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 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 996 @controller.stubs(:logged_in?).returns(true)
982 997 user = mock()
... ... @@ -986,10 +1001,10 @@ class ProfileControllerTest &lt; ActionController::TestCase
986 1001 Person.any_instance.stubs(:follows?).returns(true)
987 1002 assert_equal 40, p1.scraps_received.not_replies.count
988 1003 get :index, :profile => p1.identifier
989   - assert_equal 30, assigns(:wall_items).count
  1004 + assert_equal 30, assigns(:activities).count
990 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 1008 p1 = Person.first
994 1009 c = fast_create(Community)
995 1010 40.times{fast_create(Scrap, :receiver_id => c.id)}
... ... @@ -1002,7 +1017,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
1002 1017 Person.any_instance.stubs(:follows?).returns(true)
1003 1018 assert_equal 40, c.scraps_received.not_replies.count
1004 1019 get :index, :profile => c.identifier
1005   - assert_equal 30, assigns(:wall_items).count
  1020 + assert_equal 30, assigns(:activities).count
1006 1021 end
1007 1022  
1008 1023 should "the owner of activity could remove it" do
... ... @@ -1072,17 +1087,17 @@ class ProfileControllerTest &lt; ActionController::TestCase
1072 1087 end
1073 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 1091 login_as(profile.identifier)
1077 1092 person = fast_create(Person)
1078 1093 at = fast_create(ActionTracker::Record, :user_id => person.id)
1079 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 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 1101 end
1087 1102  
1088 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 1108 assert_no_tag :tag => 'p', :attributes => {:class => 'profile-network-send-message'}
1094 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 1112 login_as(profile.identifier)
1098 1113 person = fast_create(Person)
1099 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 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 1121 end
1107 1122  
1108 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 1173 assert_equal 40, profile.tracked_actions.count
1159 1174 get :view_more_activities, :profile => profile.identifier, :page => 2
1160 1175 assert_response :success
1161   - assert_template '_profile_activities'
  1176 + assert_template '_profile_activities_list'
1162 1177 assert_equal 10, assigns(:activities).count
1163 1178 end
1164 1179  
... ... @@ -1247,4 +1262,70 @@ class ProfileControllerTest &lt; ActionController::TestCase
1247 1262 post :register_report, :profile => reported.identifier, :abuse_report => {:reason => 'some reason'}
1248 1263 end
1249 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 1331 end
... ...
test/unit/action_tracker_notification_test.rb
... ... @@ -76,4 +76,28 @@ class ActionTrackerNotificationTest &lt; ActiveSupport::TestCase
76 76 assert_equal [last_notification], at.action_tracker_notifications
77 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 103 end
... ...
test/unit/approve_article_test.rb
... ... @@ -250,7 +250,7 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase
250 250 assert_equal 1, ActionTracker::Record.count
251 251 end
252 252  
253   - should 'notify with different trackers activity create with different targets' do
  253 + should 'not group trackers activity of article\'s creation' do
254 254 ActionTracker::Record.delete_all
255 255  
256 256 article = fast_create(TextileArticle)
... ... @@ -260,28 +260,15 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase
260 260 article = fast_create(TextileArticle)
261 261 a = ApproveArticle.create!(:name => 'another bar', :article => article, :target => community, :requestor => profile)
262 262 a.finish
263   - assert_equal 1, ActionTracker::Record.count
264 263  
265 264 article = fast_create(TextileArticle)
266 265 other_community = fast_create(Community)
267 266 a = ApproveArticle.create!(:name => 'another bar', :article => article, :target => other_community, :requestor => profile)
268 267 a.finish
269   - assert_equal 2, ActionTracker::Record.count
270   - end
271   -
272   - should 'notify activity on update' do
273   - ActionTracker::Record.delete_all
274   - a = ApproveArticle.create!(:name => 'bar', :article => article, :target => community, :requestor => profile)
275   - a.finish
276   - assert_equal 1, ActionTracker::Record.count
277   -
278   - published = article.class.last
279   - published.name = 'foo'
280   - published.save!
281   - assert_equal 2, ActionTracker::Record.count
  268 + assert_equal 3, ActionTracker::Record.count
282 269 end
283 270  
284   - should 'notify with different trackers activity update with different targets' do
  271 + should 'not create trackers activity when updating articles' do
285 272 ActionTracker::Record.delete_all
286 273 article1 = fast_create(TextileArticle)
287 274 a = ApproveArticle.create!(:name => 'bar', :article => article1, :target => community, :requestor => profile)
... ... @@ -293,16 +280,16 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase
293 280 a.finish
294 281 assert_equal 2, ActionTracker::Record.count
295 282  
296   - published = article1.class.last
297   - published.name = 'foo';published.save!
298   - assert_equal 3, ActionTracker::Record.count
299   -
300   - published = article2.class.last
301   - published.name = 'another foo';published.save!
302   - assert_equal 4, ActionTracker::Record.count
  283 + assert_no_difference ActionTracker::Record, :count do
  284 + published = article1.class.last
  285 + published.name = 'foo';published.save!
  286 +
  287 + published = article2.class.last
  288 + published.name = 'another foo';published.save!
  289 + end
303 290 end
304 291  
305   - should "the tracker action target be defined as Community by custom_target method on articles'creation in communities" do
  292 + should "the tracker action target be defined as the article on articles'creation in communities" do
306 293 ActionTracker::Record.delete_all
307 294 person = fast_create(Person)
308 295 community.add_member(person)
... ... @@ -310,17 +297,21 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase
310 297 a = ApproveArticle.create!(:article => article, :target => community, :requestor => profile)
311 298 a.finish
312 299  
313   - assert_equal Community, ActionTracker::Record.last.target.class
  300 + approved_article = community.articles.find_by_name(article.name)
  301 +
  302 + assert_equal approved_article, ActionTracker::Record.last.target
314 303 end
315 304  
316   - should "the tracker action target be defined as person by custom_target method on articles'creation in profile" do
  305 + should "the tracker action target be defined as the article on articles'creation in profile" do
317 306 ActionTracker::Record.delete_all
318 307 person = fast_create(Person)
319 308  
320 309 a = ApproveArticle.create!(:article => article, :target => person, :requestor => profile)
321 310 a.finish
322 311  
323   - assert_equal Person, ActionTracker::Record.last.target.class
  312 + approved_article = person.articles.find_by_name(article.name)
  313 +
  314 + assert_equal approved_article, ActionTracker::Record.last.target
324 315 end
325 316  
326 317 should "have the same is_trackable method as original article" do
... ...
test/unit/article_test.rb
... ... @@ -320,15 +320,16 @@ class ArticleTest &lt; ActiveSupport::TestCase
320 320  
321 321 should 'list most commented articles' do
322 322 Article.delete_all
  323 + (1..4).each do |n|
  324 + create(TextileArticle, :name => "art #{n}", :profile_id => profile.id)
  325 + end
  326 + first_article = profile.articles.first
  327 + 2.times { Comment.create(:title => 'test', :body => 'asdsad', :author => profile, :source => first_article).save! }
323 328  
324   - person = create_user('testuser').person
325   - articles = (1..4).map {|n| a = person.articles.build(:name => "art #{n}"); a.save!; a }
326   -
327   - 2.times { articles[0].comments.build(:title => 'test', :body => 'asdsad', :author => person).save! }
328   - 4.times { articles[1].comments.build(:title => 'test', :body => 'asdsad', :author => person).save! }
329   -
  329 + last_article = profile.articles.last
  330 + 4.times { Comment.create(:title => 'test', :body => 'asdsad', :author => profile, :source => last_article).save! }
330 331 # should respect the order (more commented comes first)
331   - assert_equal [articles[1], articles[0]], person.articles.most_commented(2)
  332 + assert_equal [last_article, first_article], profile.articles.most_commented(2)
332 333 end
333 334  
334 335 should 'identify itself as a non-folder' do
... ... @@ -362,16 +363,16 @@ class ArticleTest &lt; ActiveSupport::TestCase
362 363  
363 364 should 'index comments title together with article' do
364 365 owner = create_user('testuser').person
365   - art = owner.articles.build(:name => 'ytest'); art.save!
366   - c1 = art.comments.build(:title => 'a nice comment', :body => 'anything', :author => owner); c1.save!
  366 + art = fast_create(TinyMceArticle, :profile_id => owner.id, :name => 'ytest')
  367 + c1 = Comment.create(:title => 'a nice comment', :body => 'anything', :author => owner, :source => art ); c1.save!
367 368  
368 369 assert_includes Article.find_by_contents('nice'), art
369 370 end
370 371  
371 372 should 'index comments body together with article' do
372 373 owner = create_user('testuser').person
373   - art = owner.articles.build(:name => 'ytest'); art.save!
374   - c1 = art.comments.build(:title => 'test comment', :body => 'anything', :author => owner); c1.save!
  374 + art = fast_create(TinyMceArticle, :profile_id => owner.id, :name => 'ytest')
  375 + c1 = Comment.create(:title => 'test comment', :body => 'anything', :author => owner, :source => art); c1.save!
375 376  
376 377 assert_includes Article.find_by_contents('anything'), art
377 378 end
... ... @@ -934,79 +935,34 @@ class ArticleTest &lt; ActiveSupport::TestCase
934 935 end
935 936  
936 937 should 'track action when a published article is created outside a community' do
937   - article = TinyMceArticle.create! :name => 'Tracked Article', :profile_id => profile.id
938   - assert article.published?
939   - assert_kind_of Person, article.profile
940   - ta = ActionTracker::Record.last
941   - assert_equal 'Tracked Article', ta.get_name.last
942   - assert_equal article.url, ta.get_url.last
943   - assert_kind_of Person, ta.user
944   - ta.created_at = Time.now.ago(26.hours); ta.save!
945   - article = TinyMceArticle.create! :name => 'Another Tracked Article', :profile_id => profile.id
946   - ta = ActionTracker::Record.last
947   - assert_equal ['Another Tracked Article'], ta.get_name
948   - assert_equal [article.url], ta.get_url
  938 + article = create(TinyMceArticle, :profile_id => profile.id)
  939 + ta = article.activity
  940 + assert_equal article.name, ta.get_name
  941 + assert_equal article.url, ta.get_url
949 942 end
950 943  
951 944 should 'track action when a published article is created in a community' do
952 945 community = fast_create(Community)
953   - p1 = ActionTracker::Record.current_user_from_model
  946 + p1 = fast_create(Person)
954 947 p2 = fast_create(Person)
955 948 p3 = fast_create(Person)
956 949 community.add_member(p1)
957 950 community.add_member(p2)
958   - assert p1.is_member_of?(community)
959   - assert p2.is_member_of?(community)
960   - assert !p3.is_member_of?(community)
961   - Article.destroy_all
962   - ActionTracker::Record.destroy_all
963   - article = TinyMceArticle.create! :name => 'Tracked Article', :profile_id => community.id
964   - assert article.published?
965   - assert_kind_of Community, article.profile
966   - ta = ActionTracker::Record.last
967   - assert_equal 'Tracked Article', ta.get_name.last
968   - assert_equal article.url, ta.get_url.last
969   - assert_kind_of Person, ta.user
  951 + UserStampSweeper.any_instance.expects(:current_user).returns(p1).at_least_once
  952 +
  953 + article = create(TinyMceArticle, :profile_id => community.id)
  954 + activity = article.activity
  955 +
970 956 process_delayed_job_queue
971   - assert_equal 3, ActionTrackerNotification.count
972   - ActionTrackerNotification.all.map{|a|a.profile}.map do |profile|
973   - assert [p1,p2,community].include?(profile)
974   - end
  957 + assert_equal 3, ActionTrackerNotification.find_all_by_action_tracker_id(activity.id).count
  958 + assert_equivalent [p1,p2,community], ActionTrackerNotification.find_all_by_action_tracker_id(activity.id).map(&:profile)
975 959 end
976 960  
977   - should 'track action when a published article is updated' do
978   - a = TinyMceArticle.create! :name => 'a', :profile_id => profile.id
979   - a.update_attributes! :name => 'b'
980   - ta = ActionTracker::Record.last
981   - assert_equal ['b'], ta.get_name
982   - assert_equal [a.reload.url], ta.get_url
983   - a.update_attributes! :name => 'c'
984   - ta = ActionTracker::Record.last
985   - assert_equal ['b','c'], ta.get_name
986   - assert_equal [a.url,a.reload.url], ta.get_url
987   - a.update_attributes! :body => 'test'
988   - ta = ActionTracker::Record.last
989   - assert_equal ['b','c','c'], ta.get_name
990   - assert_equal [a.url,a.reload.url,a.reload.url], ta.get_url
991   - a.update_attributes! :hits => 50
992   - ta = ActionTracker::Record.last
993   - assert_equal ['b','c','c'], ta.get_name
994   - assert_equal [a.url,a.reload.url,a.reload.url], ta.get_url
995   - end
996   -
997   - should 'track action when a published article is removed' do
998   - a = TinyMceArticle.create! :name => 'a', :profile_id => profile.id
999   - a.destroy
1000   - ta = ActionTracker::Record.last
1001   - assert_equal ['a'], ta.get_name
1002   - a = TinyMceArticle.create! :name => 'b', :profile_id => profile.id
1003   - a.destroy
1004   - ta = ActionTracker::Record.last
1005   - assert_equal ['a','b'], ta.get_name
1006   - a = TinyMceArticle.create! :name => 'c', :profile_id => profile.id, :published => false
1007   - a.destroy
1008   - ta = ActionTracker::Record.last
1009   - assert_equal ['a','b'], ta.get_name
  961 + should 'not track action when a published article is removed' do
  962 + a = create(TinyMceArticle, :profile_id => profile.id)
  963 + assert_no_difference ActionTracker::Record, :count do
  964 + a.destroy
  965 + end
1010 966 end
1011 967  
1012 968 should 'notifiable is false by default' do
... ... @@ -1035,6 +991,15 @@ class ArticleTest &lt; ActiveSupport::TestCase
1035 991 assert_equal 0, ActionTracker::Record.count
1036 992 end
1037 993  
  994 + should 'create activity' do
  995 + a = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
  996 + a.activity.destroy
  997 + assert_nil a.activity
  998 +
  999 + a.create_activity
  1000 + assert_not_nil a.activity
  1001 + end
  1002 +
1038 1003 should "the action_tracker_target method be defined" do
1039 1004 assert Article.method_defined?(:action_tracker_target)
1040 1005 end
... ... @@ -1071,141 +1036,64 @@ class ArticleTest &lt; ActiveSupport::TestCase
1071 1036 assert_equal false, a.is_trackable?
1072 1037 end
1073 1038  
1074   - should 'not create more than one notification track action to community when update more than one artile' do
1075   - community = fast_create(Community)
1076   - p1 = Person.first || fast_create(Person)
1077   - community.add_member(p1)
1078   - assert p1.is_member_of?(community)
1079   - Article.destroy_all
1080   - ActionTracker::Record.destroy_all
1081   - article = TinyMceArticle.create! :name => 'Tracked Article 1', :profile_id => community.id
1082   - assert article.published?
1083   - assert_kind_of Community, article.profile
1084   - assert_equal 1, ActionTracker::Record.count
1085   - ta = ActionTracker::Record.last
1086   - assert_equal 'Tracked Article 1', ta.get_name.last
1087   - assert_equal article.url, ta.get_url.last
1088   - assert p1, ta.user
1089   - assert community, ta.target
1090   - process_delayed_job_queue
1091   - assert_equal 2, ActionTrackerNotification.count
1092   -
1093   - article = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => community.id
1094   - assert article.published?
1095   - assert_kind_of Community, article.profile
1096   - assert_equal 1, ActionTracker::Record.count
1097   - ta = ActionTracker::Record.last
1098   - assert_equal 'Tracked Article 2', ta.get_name.last
1099   - assert_equal article.url, ta.get_url.last
1100   - assert_equal p1, ta.user
1101   - assert_equal community, ta.target
1102   - process_delayed_job_queue
1103   - assert_equal 2, ActionTrackerNotification.count
  1039 + should "not be trackable if article is inside a private community" do
  1040 + private_community = fast_create(Community, :public_profile => false)
  1041 + a = fast_create(TinyMceArticle, :profile_id => private_community.id)
  1042 + assert_equal false, a.is_trackable?
1104 1043 end
1105 1044  
1106   - should 'create the notification to the member when one member has the notification and the other no' do
  1045 + should 'create the notification to organization and all organization members' do
1107 1046 community = fast_create(Community)
1108   - p1 = Person.first || fast_create(Person)
1109   - community.add_member(p1)
1110   - assert p1.is_member_of?(community)
1111   - Article.destroy_all
1112   - ActionTracker::Record.destroy_all
  1047 + member_1 = Person.first
  1048 + community.add_member(member_1)
  1049 +
1113 1050 article = TinyMceArticle.create! :name => 'Tracked Article 1', :profile_id => community.id
1114   - assert article.published?
1115   - assert_kind_of Community, article.profile
1116   - assert_equal 1, ActionTracker::Record.count
1117   - ta = ActionTracker::Record.first
1118   - assert_equal 'Tracked Article 1', ta.get_name.last
1119   - assert_equal article.url, ta.get_url.last
1120   - assert p1, ta.user
1121   - assert community, ta.target
1122   - process_delayed_job_queue
1123   - assert_equal 2, ActionTrackerNotification.count
  1051 + first_activity = article.activity
  1052 + assert_equal [first_activity], ActionTracker::Record.find_all_by_verb('create_article')
1124 1053  
1125   - p2 = fast_create(Person)
1126   - community.add_member(p2)
1127 1054 process_delayed_job_queue
1128   - assert_equal 5, ActionTrackerNotification.count
1129   -
1130   - article = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => community.id
1131   - assert article.published?
1132   - assert_kind_of Community, article.profile
1133   - assert_equal 3, ActionTracker::Record.count
1134   - ta = ActionTracker::Record.first
1135   - assert_equal 'Tracked Article 2', ta.get_name.last
1136   - assert_equal article.url, ta.get_url.last
1137   - assert_equal p1, ta.user
1138   - assert_equal community, ta.target
  1055 + assert_equal 2, ActionTrackerNotification.find_all_by_action_tracker_id(first_activity.id).count
  1056 +
  1057 + member_2 = fast_create(Person)
  1058 + community.add_member(member_2)
  1059 +
  1060 + article2 = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => community.id
  1061 + second_activity = article2.activity
  1062 + assert_equivalent [first_activity, second_activity], ActionTracker::Record.find_all_by_verb('create_article')
  1063 +
1139 1064 process_delayed_job_queue
1140   - assert_equal 6, ActionTrackerNotification.count
  1065 + assert_equal 3, ActionTrackerNotification.find_all_by_action_tracker_id(second_activity.id).count
1141 1066 end
1142 1067  
1143   - should 'not create more than one notification track action to friends when update more than one artile' do
1144   - p1 = Person.first || fast_create(Person)
  1068 + should 'create notifications to friends when creating an article' do
1145 1069 friend = fast_create(Person)
1146   - p1.add_friend(friend)
  1070 + profile.add_friend(friend)
1147 1071 Article.destroy_all
1148 1072 ActionTracker::Record.destroy_all
1149 1073 ActionTrackerNotification.destroy_all
1150   - article = TinyMceArticle.create! :name => 'Tracked Article 1', :profile_id => p1.id
1151   - assert article.published?
1152   - assert_kind_of Person, article.profile
1153   - assert_equal 1, ActionTracker::Record.count
1154   - ta = ActionTracker::Record.last
1155   - assert_equal 'Tracked Article 1', ta.get_name.last
1156   - assert_equal article.url, ta.get_url.last
1157   - assert p1, ta.user
1158   - assert p1, ta.target
1159   - process_delayed_job_queue
1160   - assert_equal 2, ActionTrackerNotification.count
1161   -
1162   - article = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => p1.id
1163   - assert article.published?
1164   - assert_kind_of Person, article.profile
1165   - assert_equal 1, ActionTracker::Record.count
1166   - ta = ActionTracker::Record.last
1167   - assert_equal 'Tracked Article 2', ta.get_name.last
1168   - assert_equal article.url, ta.get_url.last
1169   - assert_equal p1, ta.user
1170   - assert_equal p1, ta.target
  1074 + UserStampSweeper.any_instance.expects(:current_user).returns(profile).at_least_once
  1075 + article = create(TinyMceArticle, :profile_id => profile.id)
  1076 +
1171 1077 process_delayed_job_queue
1172   - assert_equal 2, ActionTrackerNotification.count
  1078 + assert_equal friend, ActionTrackerNotification.last.profile
1173 1079 end
1174 1080  
1175 1081 should 'create the notification to the friend when one friend has the notification and the other no' do
1176   - p1 = Person.first || fast_create(Person)
1177 1082 f1 = fast_create(Person)
1178   - p1.add_friend(f1)
1179   - Article.destroy_all
1180   - ActionTracker::Record.destroy_all
1181   - ActionTrackerNotification.destroy_all
1182   - article = TinyMceArticle.create! :name => 'Tracked Article 1', :profile_id => p1.id
1183   - assert article.published?
1184   - assert_kind_of Person, article.profile
1185   - assert_equal 1, ActionTracker::Record.count
1186   - ta = ActionTracker::Record.first
1187   - assert_equal 'Tracked Article 1', ta.get_name.last
1188   - assert_equal article.url, ta.get_url.last
1189   - assert p1, ta.user
1190   - assert p1, ta.target
  1083 + profile.add_friend(f1)
  1084 +
  1085 + UserStampSweeper.any_instance.expects(:current_user).returns(profile).at_least_once
  1086 + article = TinyMceArticle.create! :name => 'Tracked Article 1', :profile_id => profile.id
  1087 + assert_equal 1, ActionTracker::Record.find_all_by_verb('create_article').count
1191 1088 process_delayed_job_queue
1192   - assert_equal 2, ActionTrackerNotification.count
  1089 + assert_equal 2, ActionTrackerNotification.find_all_by_action_tracker_id(article.activity.id).count
1193 1090  
1194 1091 f2 = fast_create(Person)
1195   - p1.add_friend(f2)
1196   - process_delayed_job_queue
1197   - assert_equal 5, ActionTrackerNotification.count
1198   - article = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => p1.id
1199   - assert article.published?
1200   - assert_kind_of Person, article.profile
1201   - assert_equal 2, ActionTracker::Record.count
1202   - ta = ActionTracker::Record.first
1203   - assert_equal 'Tracked Article 2', ta.get_name.last
1204   - assert_equal article.url, ta.get_url.last
1205   - assert_equal p1, ta.user
1206   - assert_equal p1, ta.target
  1092 + profile.add_friend(f2)
  1093 + article2 = TinyMceArticle.create! :name => 'Tracked Article 2', :profile_id => profile.id
  1094 + assert_equal 2, ActionTracker::Record.find_all_by_verb('create_article').count
1207 1095 process_delayed_job_queue
1208   - assert_equal 6, ActionTrackerNotification.count
  1096 + assert_equal 3, ActionTrackerNotification.find_all_by_action_tracker_id(article2.activity.id).count
1209 1097 end
1210 1098  
1211 1099 should 'found articles with published date between a range' do
... ... @@ -1560,7 +1448,7 @@ class ArticleTest &lt; ActiveSupport::TestCase
1560 1448 should 'survive to a invalid src attribute while looking for images in body' do
1561 1449 article = Article.new(:body => "An article with invalid src in img tag <img src='path with spaces.png' />", :profile => @profile)
1562 1450 assert_nothing_raised URI::InvalidURIError do
1563   - assert_equal ['http://localhost/path%20with%20spaces.png'], article.body_images_paths
  1451 + assert_equal ["http://#{profile.environment.default_hostname}/path%20with%20spaces.png"], article.body_images_paths
1564 1452 end
1565 1453 end
1566 1454  
... ... @@ -1671,4 +1559,24 @@ class ArticleTest &lt; ActiveSupport::TestCase
1671 1559 assert !a.allow_edit?(nil)
1672 1560 end
1673 1561  
  1562 + should 'get first image from lead' do
  1563 + a = fast_create(Article, :body => '<p>Foo</p><p><img src="bar.png" />Bar<img src="foo.png" /></p>',
  1564 + :abstract => '<p>Lead</p><p><img src="leadbar.png" />Bar<img src="leadfoo.png" /></p>')
  1565 + assert_equal 'leadbar.png', a.first_image
  1566 + end
  1567 +
  1568 + should 'get first image from body' do
  1569 + a = fast_create(Article, :body => '<p>Foo</p><p><img src="bar.png" />Bar<img src="foo.png" /></p>')
  1570 + assert_equal 'bar.png', a.first_image
  1571 + end
  1572 +
  1573 + should 'not get first image from anywhere' do
  1574 + a = fast_create(Article, :body => '<p>Foo</p><p>Bar</p>')
  1575 + assert_equal '', a.first_image
  1576 + end
  1577 +
  1578 + should 'store first image in tracked action' do
  1579 + a = TinyMceArticle.create! :name => 'Tracked Article', :body => '<p>Foo<img src="foo.png" />Bar</p>', :profile_id => profile.id
  1580 + assert_equal 'foo.png', ActionTracker::Record.last.get_first_image
  1581 + end
1674 1582 end
... ...
test/unit/category_finder_test.rb
... ... @@ -188,17 +188,20 @@ class CategoryFinderTest &lt; ActiveSupport::TestCase
188 188 end
189 189  
190 190 should 'return most commented articles' do
  191 + person = create_user('testuser').person
191 192 Article.delete_all
192 193  
193   - person = create_user('testuser').person
194   - articles = (1..4).map {|n| a = person.articles.build(:name => "art #{n}", :category_ids => [@category.id]); a.save!; a }
  194 + (1..4).map {|n| create(TextileArticle, :profile_id => person.id, :name => "art #{n}", :category_ids => [@category.id]) }
  195 +
  196 + first_article = person.articles.first
  197 + 2.times { Comment.create(:title => 'test', :body => 'asdsad', :author => person, :source => first_article) }
195 198  
196   - 2.times { articles[0].comments.build(:title => 'test', :body => 'asdsad', :author => person).save! }
197   - 4.times { articles[1].comments.build(:title => 'test', :body => 'asdsad', :author => person).save! }
  199 + last_article = person.articles.last
  200 + 4.times { Comment.create(:title => 'test', :body => 'asdsad', :author => person, :source => last_article) }
198 201  
199 202 result = @finder.most_commented_articles(2)
200 203 # should respect the order (more commented comes first)
201   - assert_equal [articles[1], articles[0]], result
  204 + assert_equal [last_article, first_article], result
202 205 assert_respond_to result, :total_entries
203 206 end
204 207  
... ...
test/unit/category_test.rb
... ... @@ -260,13 +260,14 @@ class CategoryTest &lt; ActiveSupport::TestCase
260 260 a2 = person.articles.build(:name => 'art2', :category_ids => [c.id]); a2.save!
261 261 a3 = person.articles.build(:name => 'art3', :category_ids => [c.id]); a3.save!
262 262  
263   - a1.comments.build(:title => 'test', :body => 'asdsa', :author => person).save!
264   - 5.times { a2.comments.build(:title => 'test', :body => 'asdsa', :author => person).save! }
  263 + Comment.create(:title => 'test', :body => 'asdsa', :author => person, :source => a1)
  264 + 5.times { Comment.create(:title => 'test', :body => 'asdsa', :author => person, :source => a2) }
265 265  
266   - 10.times { a3.comments.build(:title => 'test', :body => 'kajsdsa', :author => person).save! }
  266 + 10.times { Comment.create(:title => 'test', :body => 'kajsdsa', :author => person, :source => a3) }
267 267  
268 268 assert_equal [a3, a2], c.most_commented_articles(2)
269 269 end
  270 +
270 271 should 'have comments' do
271 272 c = @env.categories.build(:name => 'my category'); c.save!
272 273 person = create_user('testuser').person
... ...
test/unit/comment_notifier_test.rb
... ... @@ -12,26 +12,26 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase
12 12 @article = fast_create(Article, :name => 'Article test', :profile_id => @profile.id, :notify_comments => true)
13 13 end
14 14  
15   - should 'deliver mail after make aarticle commment' do
  15 + should 'deliver mail after make an article comment' do
16 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 18 end
19 19 end
20 20  
21 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 23 sent = ActionMailer::Base.deliveries.first
24 24 assert_equal [@profile.email], sent.to
25 25 end
26 26  
27 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 29 sent = ActionMailer::Base.deliveries.first
30 30 assert_match /user_comment_test/, sent.body
31 31 end
32 32  
33 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 35 sent = ActionMailer::Base.deliveries.first
36 36 assert_match /flatline/, sent.body
37 37 assert_match /flatline@invalid.com/, sent.body
... ... @@ -45,13 +45,13 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase
45 45 end
46 46  
47 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 49 sent = ActionMailer::Base.deliveries.first
50 50 assert_match /comment title/, sent.body
51 51 end
52 52  
53 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 55 sent = ActionMailer::Base.deliveries.first
56 56 assert_match /comment body/, sent.body
57 57 end
... ...
test/unit/comment_test.rb
... ... @@ -13,13 +13,13 @@ class CommentTest &lt; ActiveSupport::TestCase
13 13 assert_mandatory(Comment.new, :body)
14 14 end
15 15  
16   - should 'belong to an article' do
  16 + should 'have a polymorphic relationship with source' do
17 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 20 end
21 21 assert_nothing_raised do
22   - c.article = Article.new
  22 + c.source = ActionTracker::Record.new
23 23 end
24 24 end
25 25  
... ... @@ -65,12 +65,33 @@ class CommentTest &lt; ActiveSupport::TestCase
65 65  
66 66 should 'update counter cache in article' do
67 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 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 95 end
75 96  
76 97 should 'provide author name for authenticated authors' do
... ... @@ -217,30 +238,10 @@ class CommentTest &lt; ActiveSupport::TestCase
217 238 assert File.exists?(File.join(Rails.root, 'public', image)), "#{image} does not exist."
218 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 241 should 'have the action_tracker_target defined' do
233 242 assert Comment.method_defined?(:action_tracker_target)
234 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 245 should "get children of a comment" do
245 246 c = fast_create(Comment)
246 247 c1 = fast_create(Comment, :reply_of_id => c.id)
... ... @@ -307,11 +308,11 @@ class CommentTest &lt; ActiveSupport::TestCase
307 308  
308 309 should "return comments as a thread" do
309 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 316 result = a.comments.as_thread
316 317 assert_equal c0.id, result[0].id
317 318 assert_equal [c1.id, c3.id], result[0].replies.map(&:id)
... ... @@ -338,4 +339,27 @@ class CommentTest &lt; ActiveSupport::TestCase
338 339 assert c.rejected?
339 340 end
340 341  
  342 + should 'update article activity when add a comment' do
  343 + profile = create_user('testuser').person
  344 + article = create(TinyMceArticle, :profile => profile)
  345 + action = article.activity
  346 + time = action.updated_at
  347 +
  348 + Time.stubs(:now).returns(time + 1.day)
  349 +
  350 + comment = create(Comment, :source => article, :author => profile)
  351 + assert_equal time + 1.day, article.activity.updated_at
  352 + end
  353 +
  354 + should 'create a new activity when add a comment and the activity was removed' do
  355 + profile = create_user('testuser').person
  356 + article = create(TinyMceArticle, :profile => profile)
  357 + article.activity.destroy
  358 +
  359 + assert_nil article.activity
  360 +
  361 + comment = create(Comment, :source => article, :author => profile)
  362 + assert_not_nil article.activity
  363 + end
  364 +
341 365 end
... ...
test/unit/community_test.rb
... ... @@ -274,22 +274,19 @@ class CommunityTest &lt; ActiveSupport::TestCase
274 274 end
275 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 278 ActionTrackerNotification.delete_all
279 279 p1 = Person.first
280 280 community = fast_create(Community)
281 281 p2 = fast_create(Person)
282 282 p3 = fast_create(Person)
283 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 290 end
294 291  
295 292 should "see get all received scraps" do
... ... @@ -341,4 +338,35 @@ class CommunityTest &lt; ActiveSupport::TestCase
341 338 assert_equal false, community.receives_scrap_notification?
342 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 372 end
... ...
test/unit/enterprise_test.rb
... ... @@ -450,4 +450,37 @@ class EnterpriseTest &lt; ActiveSupport::TestCase
450 450 e = fast_create(Enterprise)
451 451 assert_respond_to e, :production_costs
452 452 end
  453 +
  454 + should 'return scraps as activities' do
  455 + person = fast_create(Person)
  456 + enterprise = fast_create(Enterprise)
  457 +
  458 +
  459 + activity = ActionTracker::Record.last
  460 + scrap = Scrap.create!(defaults_for_scrap(:sender => person, :receiver => enterprise, :content => 'A scrap'))
  461 +
  462 + assert_equal [scrap], enterprise.activities.map { |a| a.klass.constantize.find(a.id) }
  463 + end
  464 +
  465 + should 'return tracked_actions of community as activities' do
  466 + person = fast_create(Person)
  467 + enterprise = fast_create(Enterprise)
  468 +
  469 + UserStampSweeper.any_instance.expects(:current_user).returns(person).at_least_once
  470 + article = create(TinyMceArticle, :profile => enterprise, :name => 'An article about free software')
  471 +
  472 + assert_equal [article.activity], enterprise.activities.map { |a| a.klass.constantize.find(a.id) }
  473 + end
  474 +
  475 + should 'not return tracked_actions of other community as activities' do
  476 + person = fast_create(Person)
  477 + enterprise = fast_create(Enterprise)
  478 + enterprise2 = fast_create(Enterprise)
  479 +
  480 + UserStampSweeper.any_instance.expects(:current_user).returns(person).at_least_once
  481 + article = create(TinyMceArticle, :profile => enterprise2, :name => 'Another article about free software')
  482 +
  483 + assert_not_includes enterprise.activities.map { |a| a.klass.constantize.find(a.id) }, article.activity
  484 + end
  485 +
453 486 end
... ...
test/unit/event_test.rb
... ... @@ -274,4 +274,7 @@ class EventTest &lt; ActiveSupport::TestCase
274 274 assert Event.new.tiny_mce?
275 275 end
276 276  
  277 + should 'be notifiable' do
  278 + assert Event.new.notifiable?
  279 + end
277 280 end
... ...
test/unit/forum_helper_test.rb
... ... @@ -63,7 +63,7 @@ class ForumHelperTest &lt; ActiveSupport::TestCase
63 63 some_post.comments << Comment.new(:name => 'John', :email => 'lenon@example.com', :title => 'test', :body => 'test')
64 64 c = Comment.last
65 65 out = last_topic_update(some_post)
66   - assert_match "#{c.created_at.to_s} ago by John", out
  66 + assert_match "#{c.created_at.to_s} by John", out
67 67 assert_match 'John', out
68 68 end
69 69  
... ...
test/unit/forum_test.rb
... ... @@ -28,21 +28,21 @@ class ForumTest &lt; ActiveSupport::TestCase
28 28  
29 29 should 'create rss feed automatically' do
30 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 32 assert_kind_of RssFeed, b.feed
33 33 end
34 34  
35 35 should 'save feed options' do
36 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 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 40 end
41 41  
42 42 should 'save feed options after create forum' do
43 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 46 end
47 47  
48 48 should 'list 5 posts per page by default' do
... ... @@ -52,16 +52,15 @@ class ForumTest &lt; ActiveSupport::TestCase
52 52  
53 53 should 'update posts per page setting' do
54 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 56 forum.posts_per_page = 7
58 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 59 end
61 60  
62 61 should 'has posts' do
63 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 64 post = fast_create(TextileArticle, :name => 'First post', :profile_id => p.id, :parent_id => forum.id)
66 65 forum.children << post
67 66 assert_includes forum.posts, post
... ... @@ -69,7 +68,7 @@ class ForumTest &lt; ActiveSupport::TestCase
69 68  
70 69 should 'not includes rss feed in posts' do
71 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 72 assert_includes forum.children, forum.feed
74 73 assert_not_includes forum.posts, forum.feed
75 74 end
... ... @@ -89,13 +88,13 @@ class ForumTest &lt; ActiveSupport::TestCase
89 88 p = create_user('testuser').person
90 89 fast_create(Forum, :name => 'Forum test', :profile_id => p.id)
91 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 92 end
94 93 end
95 94  
96 95 should 'not update slug from name for existing forum' do
97 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 98 assert_equal 'forum-test', forum.slug
100 99 forum.name = 'Changed name'
101 100 assert_not_equal 'changed-name', forum.slug
... ... @@ -110,4 +109,28 @@ class ForumTest &lt; ActiveSupport::TestCase
110 109 assert !folder.accept_uploads?
111 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 136 end
... ...
test/unit/notify_activity_to_profiles_job_test.rb
... ... @@ -24,28 +24,6 @@ class NotifyActivityToProfilesJobTest &lt; ActiveSupport::TestCase
24 24 end
25 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 27 should 'notify just the users and his friends tracking user actions' do
50 28 person = fast_create(Person)
51 29 community = fast_create(Community)
... ... @@ -132,36 +110,14 @@ class NotifyActivityToProfilesJobTest &lt; ActiveSupport::TestCase
132 110 end
133 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 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 115 assert_equal [], notify_community_verbs - NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY
160 116 assert_equal [], NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY - notify_community_verbs
161 117 end
162 118  
163 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 121 assert_equal [], not_notify_community_verbs - NotifyActivityToProfilesJob::NOT_NOTIFY_COMMUNITY
166 122 assert_equal [], NotifyActivityToProfilesJob::NOT_NOTIFY_COMMUNITY - not_notify_community_verbs
167 123 end
... ...
test/unit/person_test.rb
... ... @@ -1013,65 +1013,14 @@ class PersonTest &lt; ActiveSupport::TestCase
1013 1013 assert has_add_member_notification
1014 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 1017 p = create_user('test_user').person
1018 1018 c = fast_create(Community, :name => "Foo")
1019 1019 c.add_member(p)
1020 1020 c.add_moderator(p)
1021 1021 ActionTracker::Record.delete_all
1022 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 1024 end
1076 1025  
1077 1026 should 'get all friends online' do
... ... @@ -1243,4 +1192,32 @@ class PersonTest &lt; ActiveSupport::TestCase
1243 1192 assert !person.visible
1244 1193 assert_not_equal password, person.user.password
1245 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_equal [person_scrap,person_activity], person.activities.map { |a| a.klass.constantize.find(a.id) }
  1222 + end
1246 1223 end
... ...
test/unit/profile_test.rb
... ... @@ -1623,7 +1623,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1623 1623  
1624 1624 should 'have forum' do
1625 1625 p = fast_create(Profile)
1626   - p.articles << Forum.new(:profile => p, :name => 'forum_feed_test')
  1626 + p.articles << Forum.new(:profile => p, :name => 'forum_feed_test', :body => 'Forum test')
1627 1627 assert p.has_forum?
1628 1628 end
1629 1629  
... ... @@ -1639,9 +1639,9 @@ class ProfileTest &lt; ActiveSupport::TestCase
1639 1639  
1640 1640 should 'get first forum when has multiple forums' do
1641 1641 p = fast_create(Profile)
1642   - p.forums << Forum.new(:profile => p, :name => 'Forum one')
1643   - p.forums << Forum.new(:profile => p, :name => 'Forum two')
1644   - p.forums << Forum.new(:profile => p, :name => 'Forum three')
  1642 + p.forums << Forum.new(:profile => p, :name => 'Forum one', :body => 'Forum test')
  1643 + p.forums << Forum.new(:profile => p, :name => 'Forum two', :body => 'Forum test')
  1644 + p.forums << Forum.new(:profile => p, :name => 'Forum three', :body => 'Forum test')
1645 1645 assert_equal 'Forum one', p.forum.name
1646 1646 assert_equal 3, p.forums.count
1647 1647 end
... ... @@ -1704,6 +1704,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1704 1704 assert profile.is_on_homepage?("/#{profile.identifier}/#{homepage.slug}", homepage)
1705 1705 end
1706 1706  
  1707 +
1707 1708 should 'find profiles with image' do
1708 1709 env = fast_create(Environment)
1709 1710 2.times do |n|
... ... @@ -1764,6 +1765,11 @@ class ProfileTest &lt; ActiveSupport::TestCase
1764 1765 end
1765 1766 end
1766 1767  
  1768 + should 'return empty array as activities' do
  1769 + profile = Profile.new
  1770 + assert_equal [], profile.activities
  1771 + end
  1772 +
1767 1773 private
1768 1774  
1769 1775 def assert_invalid_identifier(id)
... ...
test/unit/textile_article_test.rb
... ... @@ -38,80 +38,72 @@ class TextileArticleTest &lt; ActiveSupport::TestCase
38 38 assert_equal 1, ActionTracker::Record.count
39 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 42 ActionTracker::Record.delete_all
43 43 profile = fast_create(Profile)
44 44 TextileArticle.create! :name => 'bar', :profile_id => profile.id, :published => true
45 45 TextileArticle.create! :name => 'another bar', :profile_id => profile.id, :published => true
46   - assert_equal 1, ActionTracker::Record.count
47 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 48 end
50 49  
51   - should 'notify activity on update' do
  50 + should 'not update activity on update of an article' do
52 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 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 64 ActionTracker::Record.delete_all
62 65 a1 = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
63 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 71 end
72 72  
73   - should 'notify activity on destroy' do
  73 + should 'not notify activity on destroy' do
74 74 ActionTracker::Record.delete_all
75 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 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 82 ActionTracker::Record.delete_all
83 83 a1 = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
84 84 a2 = TextileArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
85 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 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 93 ActionTracker::Record.delete_all
94 94 community = fast_create(Community)
95 95 p1 = Person.first
96 96 community.add_member(p1)
97 97 assert p1.is_member_of?(community)
98 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 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 103 ActionTracker::Record.delete_all
108 104 person = Person.first
109 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 107 end
116 108  
117 109 should 'not notify activity if the article is not advertise' do
... ...
test/unit/tiny_mce_article_test.rb
... ... @@ -134,80 +134,64 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase
134 134 assert_equal 1, ActionTracker::Record.count
135 135 end
136 136  
137   - should 'notify with different trackers activity create with different targets' do
  137 + should 'not group trackers activity of article\'s creation' do
138 138 ActionTracker::Record.delete_all
139 139 profile = fast_create(Profile)
140 140 TinyMceArticle.create! :name => 'bar', :profile_id => profile.id, :published => true
141 141 TinyMceArticle.create! :name => 'another bar', :profile_id => profile.id, :published => true
142   - assert_equal 1, ActionTracker::Record.count
143   - TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
144 142 assert_equal 2, ActionTracker::Record.count
  143 + TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
  144 + assert_equal 3, ActionTracker::Record.count
145 145 end
146 146  
147   - should 'notify activity on update' do
  147 + should 'not update activity on update of an article' do
148 148 ActionTracker::Record.delete_all
149   - a = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
150   - assert_equal 1, ActionTracker::Record.count
151   - a.name = 'foo'
152   - a.save!
153   - assert_equal 2, ActionTracker::Record.count
  149 + profile = fast_create(Profile)
  150 + article = create(TinyMceArticle, :profile_id => profile.id)
  151 + time = article.activity.updated_at
  152 + Time.stubs(:now).returns(time + 1.day)
  153 + assert_no_difference ActionTracker::Record, :count do
  154 + article.name = 'foo'
  155 + article.save!
  156 + end
  157 + assert_equal time, article.activity.updated_at
154 158 end
155 159  
156   - should 'notify with different trackers activity update with different targets' do
  160 + should 'not create trackers activity when updating articles' do
157 161 ActionTracker::Record.delete_all
158 162 a1 = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
159 163 a2 = TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
160   - assert_equal 2, ActionTracker::Record.count
161   - a1.name = 'foo'
162   - a1.save!
163   - assert_equal 3, ActionTracker::Record.count
164   - a2.name = 'another foo'
165   - a2.save!
166   - assert_equal 4, ActionTracker::Record.count
  164 + assert_no_difference ActionTracker::Record, :count do
  165 + a1.name = 'foo';a1.save!
  166 + a2.name = 'another foo';a2.save!
  167 + end
167 168 end
168 169  
169   - should 'notify activity on destroy' do
170   - ActionTracker::Record.delete_all
171   - a = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
172   - assert_equal 1, ActionTracker::Record.count
173   - a.destroy
174   - assert_equal 2, ActionTracker::Record.count
175   - end
176   -
177   - should 'notify different activities when destroy articles with diferrents targets' do
  170 + should 'not notify when an article is destroyed' do
178 171 ActionTracker::Record.delete_all
179 172 a1 = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
180 173 a2 = TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
181   - assert_equal 2, ActionTracker::Record.count
182   - a1.destroy
183   - assert_equal 3, ActionTracker::Record.count
184   - a2.destroy
185   - assert_equal 4, ActionTracker::Record.count
  174 + assert_no_difference ActionTracker::Record, :count do
  175 + a1.destroy
  176 + a2.destroy
  177 +end
186 178 end
187 179  
188   - should "the tracker action target be defined as Community by custom_target method on articles'creation in communities" do
  180 + should "the tracker action target be defined as the article on articles'creation in communities" do
189 181 ActionTracker::Record.delete_all
190 182 community = fast_create(Community)
191 183 p1 = Person.first
192 184 community.add_member(p1)
193 185 assert p1.is_member_of?(community)
194 186 article = TinyMceArticle.create! :name => 'test', :profile_id => community.id
195   - assert_equal true, article.published?
196   - assert_equal true, article.notifiable?
197   - assert_equal false, article.image?
198   - assert_equal Community, article.profile.class
199   - assert_equal Community, ActionTracker::Record.last.target.class
  187 + assert_equal article, ActionTracker::Record.last.target
200 188 end
201 189  
202   - should "the tracker action target be defined as person by custom_target method on articles'creation in profile" do
  190 + should "the tracker action target be defined as the article on articles'creation in profile" do
203 191 ActionTracker::Record.delete_all
204 192 person = Person.first
205 193 article = TinyMceArticle.create! :name => 'test', :profile_id => person.id
206   - assert_equal true, article.published?
207   - assert_equal true, article.notifiable?
208   - assert_equal false, article.image?
209   - assert_equal Person, article.profile.class
210   - assert_equal person, ActionTracker::Record.last.target
  194 + assert_equal article, ActionTracker::Record.last.target
211 195 end
212 196  
213 197 should 'not notify activity if the article is not advertise' do
... ...
test/unit/uploaded_file_test.rb
... ... @@ -231,10 +231,10 @@ class UploadedFileTest &lt; ActiveSupport::TestCase
231 231 should 'return a thumbnail for images' do
232 232 f = UploadedFile.new
233 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 235 assert_equal '/images/0000/0005/x.png', f.thumbnail_path
236 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 238 f.expects(:image?).returns(false)
239 239 assert_nil f.thumbnail_path
240 240 end
... ... @@ -330,4 +330,11 @@ class UploadedFileTest &lt; ActiveSupport::TestCase
330 330 assert_equal 'hello_world.php.txt', file.filename
331 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 340 end
... ...
vendor/plugins/access_control/lib/role_assignment.rb
... ... @@ -7,12 +7,8 @@ class RoleAssignment &lt; ActiveRecord::Base
7 7  
8 8 track_actions :join_community, :after_create, :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
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 12 def has_permission?(perm, res)
17 13 return false unless role.has_permission?(perm.to_s) && (resource || is_global)
18 14 return true if is_global
... ...
vendor/plugins/action_tracker/lib/action_tracker_model.rb
... ... @@ -24,6 +24,7 @@ module ActionTracker
24 24 RECENT_DELAY = 30
25 25  
26 26 named_scope :recent, :conditions => ['created_at >= ?', RECENT_DELAY.days.ago]
  27 + named_scope :visible, :conditions => { :visible => true }
27 28  
28 29 def self.current_user_from_model
29 30 u = new
... ...
vendor/plugins/action_tracker_has_comments/init.rb 0 → 100644
... ... @@ -0,0 +1,12 @@
  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 +end
... ...
vendor/plugins/active_record_counter_cache_on_polymorphic_association/init.rb 0 → 100644
... ... @@ -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
... ...