Commit 66a944b5fd58e50fcc767ce1d91640fef80ff6d7
1 parent
9db0c7d6
Exists in
private-scraps
Profile followers feature
Signed-off-by: Artur Bersan de Faria <arturbersan@gmail.com> Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com> Signed-off-by: Matheus Miranda <matheusmirandalacerda@gmail.com> Signed-off-by: Sabryna Sousa <sabryna.sousa1323@gmail.com> Signed-off-by: Victor Matias Navarro <victor.matias.navarro@gmail.com> Signed-off-by: Vitor Barbosa <vitormga15@gmail.com>
Showing
50 changed files
with
1005 additions
and
90 deletions
Show diff stats
app/controllers/my_profile/follow_categories_controller.rb
0 → 100644
@@ -0,0 +1,46 @@ | @@ -0,0 +1,46 @@ | ||
1 | +class FollowCategoriesController < MyProfileController | ||
2 | + | ||
3 | + def index | ||
4 | + @categories = current_person.follow_categories | ||
5 | + end | ||
6 | + | ||
7 | + def new | ||
8 | + @follow_category = FollowCategory.new | ||
9 | + end | ||
10 | + | ||
11 | + def create | ||
12 | + @follow_category = FollowCategory.new(:name => params[:follow_category][:name], | ||
13 | + :person => current_person) | ||
14 | + if @follow_category.save | ||
15 | + redirect_to :action => 'index' | ||
16 | + else | ||
17 | + render :action => 'new' | ||
18 | + end | ||
19 | + end | ||
20 | + | ||
21 | + def edit | ||
22 | + @follow_category = FollowCategory.find_by_id(params[:id]) | ||
23 | + render_not_found if @follow_category.nil? | ||
24 | + end | ||
25 | + | ||
26 | + def update | ||
27 | + @follow_category = FollowCategory.find_by_id(params[:id]) | ||
28 | + return render_not_found if @follow_category.nil? | ||
29 | + | ||
30 | + if @follow_category.update(params[:follow_category]) | ||
31 | + redirect_to :action => 'index' | ||
32 | + else | ||
33 | + render :action => 'edit' | ||
34 | + end | ||
35 | + end | ||
36 | + | ||
37 | + def destroy | ||
38 | + @follow_category = FollowCategory.find_by_id(params[:id]) | ||
39 | + return render_not_found if @follow_category.nil? | ||
40 | + | ||
41 | + if !@follow_category.destroy | ||
42 | + session[:notice] = _('Failed to remove category') | ||
43 | + end | ||
44 | + redirect_to :action => 'index' | ||
45 | + end | ||
46 | +end |
@@ -0,0 +1,39 @@ | @@ -0,0 +1,39 @@ | ||
1 | +class FollowersController < MyProfileController | ||
2 | + | ||
3 | + before_filter :only_for_person, :only => :index | ||
4 | + | ||
5 | + def index | ||
6 | + @followed_people = current_person.following_profiles.order(:type).paginate(:per_page => 15, :page => params[:npage]) | ||
7 | + end | ||
8 | + | ||
9 | + def set_category_modal | ||
10 | + categories = FollowCategory.where(:person => current_person).map(&:name) | ||
11 | + profile = Profile.find(params[:followed_profile_id]) | ||
12 | + render :partial => 'blocks/profile_info_actions/follow_categories', :locals => { :categories => categories, :profile => profile } | ||
13 | + end | ||
14 | + | ||
15 | + def update_category | ||
16 | + params["followed_profile_id"] ||= profile.id | ||
17 | + follower = ProfileFollower.find_by(follower_id: current_person.id, profile_id: params[:followed_profile_id]) | ||
18 | + if params[:category_name] | ||
19 | + category = FollowCategory.find_or_create_by(:name => params[:category_name], :person => current_person) | ||
20 | + else | ||
21 | + category = nil | ||
22 | + end | ||
23 | + | ||
24 | + if follower | ||
25 | + follower.follow_category = category | ||
26 | + follower.save | ||
27 | + end | ||
28 | + | ||
29 | + redirect_url = params["redirect_to"] ? params["redirect_to"] : url_for(:controller => "followers", :action => "index", :profile => current_person.identifier) | ||
30 | + redirect_to redirect_url | ||
31 | + end | ||
32 | + | ||
33 | + protected | ||
34 | + | ||
35 | + def only_for_person | ||
36 | + render_not_found unless profile.person? | ||
37 | + end | ||
38 | + | ||
39 | +end |
app/controllers/public/content_viewer_controller.rb
@@ -128,9 +128,9 @@ class ContentViewerController < ApplicationController | @@ -128,9 +128,9 @@ class ContentViewerController < ApplicationController | ||
128 | end | 128 | end |
129 | 129 | ||
130 | unless @page.display_to?(user) | 130 | unless @page.display_to?(user) |
131 | - if !profile.visible? || profile.secret? || (user && user.follows?(profile)) || user.blank? | 131 | + if !profile.visible? || profile.secret? || (user && profile.in_social_circle?(user)) || user.blank? |
132 | render_access_denied | 132 | render_access_denied |
133 | - else #!profile.public? | 133 | + else |
134 | private_profile_partial_parameters | 134 | private_profile_partial_parameters |
135 | render :template => 'profile/_private_profile', :status => 403, :formats => [:html] | 135 | render :template => 'profile/_private_profile', :status => 403, :formats => [:html] |
136 | end | 136 | end |
app/controllers/public/profile_controller.rb
@@ -3,7 +3,8 @@ class ProfileController < PublicController | @@ -3,7 +3,8 @@ class ProfileController < PublicController | ||
3 | needs_profile | 3 | needs_profile |
4 | before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] | 4 | before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] |
5 | before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse, :send_mail] | 5 | before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse, :send_mail] |
6 | - before_filter :login_required, :only => [:add, :join, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity, :send_mail] | 6 | + before_filter :login_required, :only => [:add, :join, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity, :send_mail, :follow, :unfollow] |
7 | + before_filter :allow_following?, :only => [:follow, :unfollow] | ||
7 | 8 | ||
8 | helper TagsHelper | 9 | helper TagsHelper |
9 | helper ActionTrackerHelper | 10 | helper ActionTrackerHelper |
@@ -65,6 +66,10 @@ class ProfileController < PublicController | @@ -65,6 +66,10 @@ class ProfileController < PublicController | ||
65 | end | 66 | end |
66 | end | 67 | end |
67 | 68 | ||
69 | + def following | ||
70 | + @followed_people = [].paginate(:per_page => per_page, :page => params[:npage], :total_entries => profile.friends.count) | ||
71 | + end | ||
72 | + | ||
68 | def members | 73 | def members |
69 | if is_cache_expired?(profile.members_cache_key(params)) | 74 | if is_cache_expired?(profile.members_cache_key(params)) |
70 | sort = (params[:sort] == 'desc') ? params[:sort] : 'asc' | 75 | sort = (params[:sort] == 'desc') ? params[:sort] : 'asc' |
@@ -151,6 +156,26 @@ class ProfileController < PublicController | @@ -151,6 +156,26 @@ class ProfileController < PublicController | ||
151 | end | 156 | end |
152 | end | 157 | end |
153 | 158 | ||
159 | + def follow | ||
160 | + if !current_person.follows?(profile) | ||
161 | + group = params['follow'] ? params['follow']['category'] : '' | ||
162 | + current_person.follow(profile, group) | ||
163 | + | ||
164 | + categories = FollowCategory.where(:person => current_person).map(&:name) | ||
165 | + render :partial => 'blocks/profile_info_actions/follow_categories', :locals => { :categories => categories } | ||
166 | + else | ||
167 | + render :text => _("It was not possible to follow %s") % profile.name, :status => 400 | ||
168 | + end | ||
169 | + end | ||
170 | + | ||
171 | + def unfollow | ||
172 | + if current_person.follows?(profile) | ||
173 | + current_person.unfollow(profile) | ||
174 | + end | ||
175 | + redirect_url = params["redirect_to"] ? params["redirect_to"] : profile.url | ||
176 | + redirect_to redirect_url | ||
177 | + end | ||
178 | + | ||
154 | def check_friendship | 179 | def check_friendship |
155 | unless logged_in? | 180 | unless logged_in? |
156 | render :text => '' | 181 | render :text => '' |
@@ -437,4 +462,8 @@ class ProfileController < PublicController | @@ -437,4 +462,8 @@ class ProfileController < PublicController | ||
437 | [:image, :domains, :preferred_domain, :environment] | 462 | [:image, :domains, :preferred_domain, :environment] |
438 | end | 463 | end |
439 | 464 | ||
465 | + def allow_following? | ||
466 | + render_not_found unless profile.allow_following? | ||
467 | + end | ||
468 | + | ||
440 | end | 469 | end |
app/helpers/action_tracker_helper.rb
@@ -14,13 +14,23 @@ module ActionTrackerHelper | @@ -14,13 +14,23 @@ module ActionTrackerHelper | ||
14 | } | 14 | } |
15 | end | 15 | end |
16 | 16 | ||
17 | + def new_follower_description ta | ||
18 | + n_('has 1 new follower:<br />%{name}', 'has %{num} new followers:<br />%{name}', ta.get_follower_name.size).html_safe % { | ||
19 | + num: ta.get_follower_name.size, | ||
20 | + name: safe_join(ta.collect_group_with_index(:follower_name) do |n,i| | ||
21 | + link_to image_tag(ta.get_follower_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/person-icon.png")), | ||
22 | + ta.get_follower_url[i], title: n | ||
23 | + end) | ||
24 | + } | ||
25 | + end | ||
26 | + | ||
17 | def join_community_description ta | 27 | def join_community_description ta |
18 | - n_('has joined 1 community:<br />%{name}'.html_safe, 'has joined %{num} communities:<br />%{name}'.html_safe, ta.get_resource_name.size) % { | 28 | + n_('has joined 1 community:<br />%{name}', 'has joined %{num} communities:<br />%{name}', ta.get_resource_name.size).html_safe % { |
19 | num: ta.get_resource_name.size, | 29 | num: ta.get_resource_name.size, |
20 | - name: ta.collect_group_with_index(:resource_name) do |n,i| | 30 | + name: safe_join(ta.collect_group_with_index(:resource_name) do |n,i| |
21 | link = link_to image_tag(ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png")), | 31 | link = link_to image_tag(ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png")), |
22 | ta.get_resource_url[i], title: n | 32 | ta.get_resource_url[i], title: n |
23 | - end.join.html_safe | 33 | + end) |
24 | } | 34 | } |
25 | end | 35 | end |
26 | 36 | ||
@@ -68,9 +78,9 @@ module ActionTrackerHelper | @@ -68,9 +78,9 @@ module ActionTrackerHelper | ||
68 | end | 78 | end |
69 | 79 | ||
70 | def favorite_enterprise_description ta | 80 | def favorite_enterprise_description ta |
71 | - _('favorited enterprise %{title}') % { | 81 | + (_('favorited enterprise %{title}') % { |
72 | title: link_to(truncate(ta.get_enterprise_name), ta.get_enterprise_url), | 82 | title: link_to(truncate(ta.get_enterprise_name), ta.get_enterprise_url), |
73 | - } | 83 | + }).html_safe |
74 | end | 84 | end |
75 | 85 | ||
76 | end | 86 | end |
app/jobs/notify_activity_to_profiles_job.rb
@@ -19,8 +19,9 @@ class NotifyActivityToProfilesJob < Struct.new(:tracked_action_id) | @@ -19,8 +19,9 @@ class NotifyActivityToProfilesJob < Struct.new(:tracked_action_id) | ||
19 | # Notify the user | 19 | # Notify the user |
20 | ActionTrackerNotification.create(:profile_id => tracked_action.user.id, :action_tracker_id => tracked_action.id) | 20 | ActionTrackerNotification.create(:profile_id => tracked_action.user.id, :action_tracker_id => tracked_action.id) |
21 | 21 | ||
22 | - # Notify all friends | ||
23 | - ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select f.friend_id, #{tracked_action.id} from friendships as f where person_id=#{tracked_action.user.id} and f.friend_id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id})") | 22 | + #TODO fix spaming notifications when following and unfolling many times |
23 | + # Notify all followers | ||
24 | + ActionTrackerNotification.connection.execute("INSERT INTO action_tracker_notifications(profile_id, action_tracker_id) SELECT f.follower_id, #{tracked_action.id} FROM profile_followers AS f WHERE profile_id=#{tracked_action.user.id} AND (f.follower_id NOT IN (SELECT atn.profile_id FROM action_tracker_notifications AS atn WHERE atn.action_tracker_id = #{tracked_action.id}))") | ||
24 | 25 | ||
25 | if tracked_action.user.is_a? Organization | 26 | if tracked_action.user.is_a? Organization |
26 | ActionTrackerNotification.connection.execute "insert into action_tracker_notifications(profile_id, action_tracker_id) " + | 27 | ActionTrackerNotification.connection.execute "insert into action_tracker_notifications(profile_id, action_tracker_id) " + |
app/models/add_member.rb
@@ -22,6 +22,7 @@ class AddMember < Task | @@ -22,6 +22,7 @@ class AddMember < Task | ||
22 | self.roles = [Profile::Roles.member(organization.environment.id).id] | 22 | self.roles = [Profile::Roles.member(organization.environment.id).id] |
23 | end | 23 | end |
24 | target.affiliate(requestor, self.roles.select{|r| !r.to_i.zero? }.map{|i| Role.find(i)}) | 24 | target.affiliate(requestor, self.roles.select{|r| !r.to_i.zero? }.map{|i| Role.find(i)}) |
25 | + person.follow(organization, _('memberships')) | ||
25 | end | 26 | end |
26 | 27 | ||
27 | def title | 28 | def title |
app/models/article.rb
@@ -534,13 +534,13 @@ class Article < ApplicationRecord | @@ -534,13 +534,13 @@ class Article < ApplicationRecord | ||
534 | 534 | ||
535 | scope :display_filter, lambda {|user, profile| | 535 | scope :display_filter, lambda {|user, profile| |
536 | return published if (user.nil? && profile && profile.public?) | 536 | return published if (user.nil? && profile && profile.public?) |
537 | - return [] if user.nil? || (profile && !profile.public? && !user.follows?(profile)) | 537 | + return [] if user.nil? || (profile && !profile.public? && !profile.in_social_circle?(user)) |
538 | where( | 538 | where( |
539 | [ | 539 | [ |
540 | "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ? | 540 | "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ? |
541 | OR (show_to_followers = ? AND ? AND profile_id IN (?))", true, user.id, user.id, | 541 | OR (show_to_followers = ? AND ? AND profile_id IN (?))", true, user.id, user.id, |
542 | profile.nil? ? false : user.has_permission?(:view_private_content, profile), | 542 | profile.nil? ? false : user.has_permission?(:view_private_content, profile), |
543 | - true, (profile.nil? ? true : user.follows?(profile)), ( profile.nil? ? (user.friends.select('profiles.id')) : [profile.id]) | 543 | + true, (profile.nil? ? true : profile.in_social_circle?(user)), ( profile.nil? ? (user.friends.select('profiles.id')) : [profile.id]) |
544 | ] | 544 | ] |
545 | ) | 545 | ) |
546 | } | 546 | } |
app/models/block.rb
@@ -88,7 +88,7 @@ class Block < ApplicationRecord | @@ -88,7 +88,7 @@ class Block < ApplicationRecord | ||
88 | end | 88 | end |
89 | 89 | ||
90 | def display_to_user?(user) | 90 | def display_to_user?(user) |
91 | - display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') || (user && display_user == 'followers' && user.follows?(owner)) | 91 | + display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') || (user && display_user == 'followers' && owner.in_social_circle?(user)) |
92 | end | 92 | end |
93 | 93 | ||
94 | def display_always(context) | 94 | def display_always(context) |
app/models/enterprise.rb
app/models/favorite_enterprise_person.rb
@@ -7,6 +7,10 @@ class FavoriteEnterprisePerson < ApplicationRecord | @@ -7,6 +7,10 @@ class FavoriteEnterprisePerson < ApplicationRecord | ||
7 | belongs_to :enterprise | 7 | belongs_to :enterprise |
8 | belongs_to :person | 8 | belongs_to :person |
9 | 9 | ||
10 | + after_create do |favorite| | ||
11 | + favorite.person.follow(favorite.enterprise, _('favorites')) | ||
12 | + end | ||
13 | + | ||
10 | protected | 14 | protected |
11 | 15 | ||
12 | def is_trackable? | 16 | def is_trackable? |
app/models/friendship.rb
@@ -9,11 +9,13 @@ class Friendship < ApplicationRecord | @@ -9,11 +9,13 @@ class Friendship < ApplicationRecord | ||
9 | after_create do |friendship| | 9 | after_create do |friendship| |
10 | Friendship.update_cache_counter(:friends_count, friendship.person, 1) | 10 | Friendship.update_cache_counter(:friends_count, friendship.person, 1) |
11 | Friendship.update_cache_counter(:friends_count, friendship.friend, 1) | 11 | Friendship.update_cache_counter(:friends_count, friendship.friend, 1) |
12 | + friendship.person.follow(friendship.friend, friendship.group) | ||
12 | end | 13 | end |
13 | 14 | ||
14 | after_destroy do |friendship| | 15 | after_destroy do |friendship| |
15 | Friendship.update_cache_counter(:friends_count, friendship.person, -1) | 16 | Friendship.update_cache_counter(:friends_count, friendship.person, -1) |
16 | Friendship.update_cache_counter(:friends_count, friendship.friend, -1) | 17 | Friendship.update_cache_counter(:friends_count, friendship.friend, -1) |
18 | + friendship.person.unfollow(friendship.friend) | ||
17 | end | 19 | end |
18 | 20 | ||
19 | def self.remove_friendship(person1, person2) | 21 | def self.remove_friendship(person1, person2) |
app/models/person.rb
@@ -8,7 +8,6 @@ class Person < Profile | @@ -8,7 +8,6 @@ class Person < Profile | ||
8 | :display => %w[compact] | 8 | :display => %w[compact] |
9 | } | 9 | } |
10 | 10 | ||
11 | - | ||
12 | def self.type_name | 11 | def self.type_name |
13 | _('Person') | 12 | _('Person') |
14 | end | 13 | end |
@@ -93,6 +92,7 @@ class Person < Profile | @@ -93,6 +92,7 @@ class Person < Profile | ||
93 | has_many :following_articles, :class_name => 'Article', :through => :article_followers, :source => :article | 92 | has_many :following_articles, :class_name => 'Article', :through => :article_followers, :source => :article |
94 | has_many :friendships, :dependent => :destroy | 93 | has_many :friendships, :dependent => :destroy |
95 | has_many :friends, :class_name => 'Person', :through => :friendships | 94 | has_many :friends, :class_name => 'Person', :through => :friendships |
95 | + has_many :follow_categories | ||
96 | 96 | ||
97 | scope :online, -> { | 97 | scope :online, -> { |
98 | joins(:user).where("users.chat_status != '' AND users.chat_status_at >= ?", DateTime.now - User.expires_chat_status_every.minutes) | 98 | joins(:user).where("users.chat_status != '' AND users.chat_status_at >= ?", DateTime.now - User.expires_chat_status_every.minutes) |
@@ -200,6 +200,17 @@ class Person < Profile | @@ -200,6 +200,17 @@ class Person < Profile | ||
200 | end | 200 | end |
201 | end | 201 | end |
202 | 202 | ||
203 | + def follow(profile, category_name = "") | ||
204 | + unless self.following_profiles.include?(profile) | ||
205 | + profile_follower = ProfileFollower.new | ||
206 | + profile_follower.profile = profile | ||
207 | + profile_follower.follower = self | ||
208 | + category = FollowCategory.find_or_create_by(:name => category_name, :person => self) | ||
209 | + profile_follower.follow_category = category | ||
210 | + profile_follower.save | ||
211 | + end | ||
212 | + end | ||
213 | + | ||
203 | def already_request_friendship?(person) | 214 | def already_request_friendship?(person) |
204 | person.tasks.where(requestor_id: self.id, type: 'AddFriend', status: Task::Status::ACTIVE).first | 215 | person.tasks.where(requestor_id: self.id, type: 'AddFriend', status: Task::Status::ACTIVE).first |
205 | end | 216 | end |
@@ -208,6 +219,11 @@ class Person < Profile | @@ -208,6 +219,11 @@ class Person < Profile | ||
208 | Friendship.where(friend_id: friend, person_id: id).first.destroy | 219 | Friendship.where(friend_id: friend, person_id: id).first.destroy |
209 | end | 220 | end |
210 | 221 | ||
222 | + def unfollow(profile) | ||
223 | + follower = ProfileFollower.where(follower_id: id, profile_id: profile.id) if profile | ||
224 | + follower.first.destroy if follower.present? | ||
225 | + end | ||
226 | + | ||
211 | FIELDS = %w[ | 227 | FIELDS = %w[ |
212 | description | 228 | description |
213 | image | 229 | image |
@@ -580,9 +596,12 @@ class Person < Profile | @@ -580,9 +596,12 @@ class Person < Profile | ||
580 | person.has_permission?(:manage_friends, self) | 596 | person.has_permission?(:manage_friends, self) |
581 | end | 597 | end |
582 | 598 | ||
583 | - protected | 599 | + def following_profiles |
600 | + Profile.following_profiles self | ||
601 | + end | ||
584 | 602 | ||
585 | - def followed_by?(profile) | ||
586 | - self == profile || self.is_a_friend?(profile) | 603 | + def in_social_circle?(person) |
604 | + self.is_a_friend?(person) || super | ||
587 | end | 605 | end |
606 | + | ||
588 | end | 607 | end |
app/models/profile.rb
@@ -5,7 +5,7 @@ class Profile < ApplicationRecord | @@ -5,7 +5,7 @@ class Profile < ApplicationRecord | ||
5 | 5 | ||
6 | attr_accessible :name, :identifier, :public_profile, :nickname, :custom_footer, :custom_header, :address, :zip_code, :contact_phone, :image_builder, :description, :closed, :template_id, :environment, :lat, :lng, :is_template, :fields_privacy, :preferred_domain_id, :category_ids, :country, :city, :state, :national_region_code, :email, :contact_email, :redirect_l10n, :notification_time, | 6 | attr_accessible :name, :identifier, :public_profile, :nickname, :custom_footer, :custom_header, :address, :zip_code, :contact_phone, :image_builder, :description, :closed, :template_id, :environment, :lat, :lng, :is_template, :fields_privacy, :preferred_domain_id, :category_ids, :country, :city, :state, :national_region_code, :email, :contact_email, :redirect_l10n, :notification_time, |
7 | :redirection_after_login, :custom_url_redirection, | 7 | :redirection_after_login, :custom_url_redirection, |
8 | - :email_suggestions, :allow_members_to_invite, :invite_friends_only, :secret, :profile_admin_mail_notification | 8 | + :email_suggestions, :allow_members_to_invite, :invite_friends_only, :secret, :profile_admin_mail_notification, :allow_following |
9 | 9 | ||
10 | # use for internationalizable human type names in search facets | 10 | # use for internationalizable human type names in search facets |
11 | # reimplement on subclasses | 11 | # reimplement on subclasses |
@@ -203,6 +203,16 @@ class Profile < ApplicationRecord | @@ -203,6 +203,16 @@ class Profile < ApplicationRecord | ||
203 | scope :more_active, -> { order 'activities_count DESC' } | 203 | scope :more_active, -> { order 'activities_count DESC' } |
204 | scope :more_recent, -> { order "created_at DESC" } | 204 | scope :more_recent, -> { order "created_at DESC" } |
205 | 205 | ||
206 | + scope :following_profiles, -> person { | ||
207 | + distinct.select('profiles.*, follow_categories.name AS category'). | ||
208 | + joins('left join profile_followers ON profile_followers.profile_id = profiles.id'). | ||
209 | + joins('left join follow_categories ON follow_categories.id = profile_followers.follow_category_id'). | ||
210 | + where('profile_followers.follower_id = ?', person.id) | ||
211 | + } | ||
212 | + | ||
213 | + settings_items :allow_following, :type => :boolean, :default => true | ||
214 | + alias_method :allow_following?, :allow_following | ||
215 | + | ||
206 | acts_as_trackable :dependent => :destroy | 216 | acts_as_trackable :dependent => :destroy |
207 | 217 | ||
208 | has_many :profile_activities | 218 | has_many :profile_activities |
@@ -215,6 +225,9 @@ class Profile < ApplicationRecord | @@ -215,6 +225,9 @@ class Profile < ApplicationRecord | ||
215 | 225 | ||
216 | has_many :email_templates, :foreign_key => :owner_id | 226 | has_many :email_templates, :foreign_key => :owner_id |
217 | 227 | ||
228 | + has_many :profile_followers | ||
229 | + has_many :followers, :class_name => 'Person', :through => :profile_followers | ||
230 | + | ||
218 | # Although this should be a has_one relation, there are no non-silly names for | 231 | # Although this should be a has_one relation, there are no non-silly names for |
219 | # a foreign key on article to reference the template to which it is | 232 | # a foreign key on article to reference the template to which it is |
220 | # welcome_page... =P | 233 | # welcome_page... =P |
@@ -764,6 +777,7 @@ private :generate_url, :url_options | @@ -764,6 +777,7 @@ private :generate_url, :url_options | ||
764 | else | 777 | else |
765 | self.affiliate(person, Profile::Roles.admin(environment.id), attributes) if members.count == 0 | 778 | self.affiliate(person, Profile::Roles.admin(environment.id), attributes) if members.count == 0 |
766 | self.affiliate(person, Profile::Roles.member(environment.id), attributes) | 779 | self.affiliate(person, Profile::Roles.member(environment.id), attributes) |
780 | + person.follow(self, _('memberships')) | ||
767 | end | 781 | end |
768 | person.tasks.pending.of("InviteMember").select { |t| t.data[:community_id] == self.id }.each { |invite| invite.cancel } | 782 | person.tasks.pending.of("InviteMember").select { |t| t.data[:community_id] == self.id }.each { |invite| invite.cancel } |
769 | remove_from_suggestion_list person | 783 | remove_from_suggestion_list person |
@@ -1107,7 +1121,11 @@ private :generate_url, :url_options | @@ -1107,7 +1121,11 @@ private :generate_url, :url_options | ||
1107 | end | 1121 | end |
1108 | 1122 | ||
1109 | def followed_by?(person) | 1123 | def followed_by?(person) |
1110 | - person.is_member_of?(self) | 1124 | + (person == self) || (person.in? self.followers) |
1125 | + end | ||
1126 | + | ||
1127 | + def in_social_circle?(person) | ||
1128 | + (person == self) || (person.is_member_of?(self)) | ||
1111 | end | 1129 | end |
1112 | 1130 | ||
1113 | def display_private_info_to?(user) | 1131 | def display_private_info_to?(user) |
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class ProfileFollower < ApplicationRecord | ||
2 | + track_actions :new_follower, :after_create, :keep_params => ["follower.name", "follower.url", "follower.profile_custom_icon"], :custom_user => :profile | ||
3 | + | ||
4 | + attr_accessible :profile, :follower, :follow_category | ||
5 | + | ||
6 | + belongs_to :profile, :foreign_key => :profile_id | ||
7 | + belongs_to :follower, :class_name => 'Person', :foreign_key => :follower_id | ||
8 | + belongs_to :follow_category, :foreign_key => :follow_category_id | ||
9 | + | ||
10 | + validates_presence_of :profile_id, :follower_id | ||
11 | + validates :profile_id, :uniqueness => {:scope => :follower_id, :message => "can't follow the same profile twice"} | ||
12 | + | ||
13 | +end |
app/views/blocks/profile_info_actions/_common.html.erb
1 | <li><%= report_abuse(profile, :button) %></li> | 1 | <li><%= report_abuse(profile, :button) %></li> |
2 | +<%if logged_in? && (user != profile) && profile.allow_following?%> | ||
3 | +<li> | ||
4 | + <% if user.follows?(profile) %> | ||
5 | + <%= button(:unfollow, content_tag('span', _('Unfollow')), {:profile => profile.identifier, :controller => 'profile', :action => 'unfollow'}) %> | ||
6 | + <% else %> | ||
7 | + <%= button(:follow, content_tag('span', _('Follow')), {:profile => profile.identifier, :controller => 'profile', :action => 'follow'}, :class => 'action-follow') %> | ||
8 | + <div id="follow-categories-container" style="display: none;"> | ||
9 | + </div> | ||
10 | + <% end %> | ||
11 | +</li> | ||
12 | +<%end%> | ||
2 | <%= render_environment_features(:profile_actions) %> | 13 | <%= render_environment_features(:profile_actions) %> |
app/views/blocks/profile_info_actions/_follow_categories.html.erb
0 → 100644
@@ -0,0 +1,24 @@ | @@ -0,0 +1,24 @@ | ||
1 | +<div class="follow-categories"> | ||
2 | +<p><%= _("You can set a category for %s") % profile.name %></p> | ||
3 | + <% categories.each do |category| %> | ||
4 | + <div class="category"> | ||
5 | + <a href="<%= url_for(:controller => 'followers', :action => 'update_category', :category_name => category, | ||
6 | + :followed_profile_id => profile.id, :redirect_to => url_for(profile.url)) %>" class="action-change-category"> | ||
7 | + <span><%= category %></span> | ||
8 | + </a> | ||
9 | + </div> | ||
10 | + <% end %> | ||
11 | + <div id="no-category-link"> | ||
12 | + <a href="<%= url_for(:controller => 'followers', :action => 'update_category', | ||
13 | + :followed_profile_id => profile.id, :redirect_to => url_for(profile.url)) %>" class="action-change-category"> | ||
14 | + <span><%= _("No Category") %></span> | ||
15 | + </a> | ||
16 | + </div> | ||
17 | + <%= form_for :follow_categories, :url => {:controller => 'followers', :action => 'update_category'} do |f|%> | ||
18 | + <%= text_field_tag(:category_name,"", :id=>"new-category-field-actions-block") %> | ||
19 | + <%= hidden_field_tag(:redirect_to, url_for(profile.url)) %> | ||
20 | + <div id="new-category-submit-actions-block"> | ||
21 | + <%= submit_button :add, '', :id =>"new-category-submit-inline"%> | ||
22 | + </div> | ||
23 | + <% end %> | ||
24 | +</div> |
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +<%= error_messages_for :follow_category %> | ||
2 | + | ||
3 | +<%= labelled_form_for :follow_category, :url => (mode == :edit) ? {:action => 'update', :id => category} : {:action => 'create'} do |f| %> | ||
4 | + | ||
5 | + <%= required_fields_message %> | ||
6 | + | ||
7 | + <%= required f.text_field(:name) %> | ||
8 | + | ||
9 | + <%= button_bar do %> | ||
10 | + <%= submit_button('save', (mode == :edit) ? _('Save changes') : _('Create category'), :cancel => {:action => 'index'} ) %> | ||
11 | + <% end %> | ||
12 | +<% end %> |
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | +<h1><%= _('Manage follow categories') %></h1> | ||
2 | + | ||
3 | +<table> | ||
4 | + <tr> | ||
5 | + <th><%= _('Category') %></th> | ||
6 | + <th><%= _('Actions') %></th> | ||
7 | + </tr> | ||
8 | + <% @categories.each do |category| %> | ||
9 | + <tr> | ||
10 | + <td> | ||
11 | + <%= category.name %> | ||
12 | + </td> | ||
13 | + <td> | ||
14 | + <div style="text-align: center;"> | ||
15 | + <%= button_without_text :edit, _('Edit'), :action => 'edit', :id => category %> | ||
16 | + <%= button_without_text :delete, _('Delete'), :action => 'destroy', :id => category %> | ||
17 | + </div> | ||
18 | + </td> | ||
19 | + </tr> | ||
20 | + <% end %> | ||
21 | +</table> | ||
22 | + | ||
23 | +<%= button_bar do %> | ||
24 | + <%= button :add, _('Create a new category'), :action => 'new' %> | ||
25 | + <%= button :back, _('Back to control panel'), :controller => 'profile_editor' %> | ||
26 | +<% end %> |
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +<ul class="profile-list"> | ||
2 | + <% profiles.each do |profile| %> | ||
3 | + <li> | ||
4 | + <%= link_to_profile profile_image(profile) + tag('br') + profile.short_name, | ||
5 | + profile.identifier, :class => 'profile-link' %> | ||
6 | + <p class="category-name"> | ||
7 | + <%= profile.category %> | ||
8 | + </p> | ||
9 | + <div class="controll"> | ||
10 | + <%= button_without_text :remove, content_tag('span',_('unfollow')), | ||
11 | + { :controller => "profile", :profile => profile.identifier , :action => 'unfollow', :redirect_to => url_for({:controller => "followers", :profile => user.identifier}) }, | ||
12 | + :title => _('remove') %> | ||
13 | + <%= modal_icon_button :change_categoy, content_tag('span',_('change category')), | ||
14 | + url_for(:controller => 'followers', :action => 'set_category_modal', | ||
15 | + :followed_profile_id => profile.id) %> | ||
16 | + </div><!-- end class="controll" --> | ||
17 | + </li> | ||
18 | + <% end %> | ||
19 | +</ul> |
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +<div class='set-category-modal'> | ||
2 | + <h2><%= _("Choose a new category") %></h2> | ||
3 | + <%= form_for :follower_category, :url => url_for(:controller => 'followers', :action => 'set_category') do |f| %> | ||
4 | + <div id="category-name"> | ||
5 | + <%= labelled_text_field _("Category: "), "category_name" %> | ||
6 | + </div> | ||
7 | + <%= hidden_field_tag 'followed_profile_id', followed_profile_id %> | ||
8 | + <div id="actions-container"> | ||
9 | + <%= submit_button('save', _('Save')) %> | ||
10 | + <%= modal_close_button _("Cancel") %> | ||
11 | + </div> | ||
12 | + <% end %> | ||
13 | +</div> |
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +<div id="manage_followed people"> | ||
2 | + | ||
3 | +<h1><%= _("%s following") % profile.name %></h1> | ||
4 | + | ||
5 | +<% cache_timeout(profile.manage_friends_cache_key(params), 4.hours) do %> | ||
6 | + <% if @followed_people.empty? %> | ||
7 | + <p> | ||
8 | + <em> | ||
9 | + <%= _("You don't follow anybody yet.") %> | ||
10 | + </em> | ||
11 | + </p> | ||
12 | + <% end %> | ||
13 | + | ||
14 | + <%= button_bar do %> | ||
15 | + <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> | ||
16 | + <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> | ||
17 | + <% end %> | ||
18 | + | ||
19 | + <%= render :partial => 'profile_list', :locals => { :profiles => @followed_people } %> | ||
20 | + | ||
21 | + <br style="clear:both" /> | ||
22 | + <%= pagination_links @followed_people, :param_name => 'npage' %> | ||
23 | +<% end %> | ||
24 | + | ||
25 | +</div> |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +<%= render :partial => 'default_activity', :locals => { :activity => activity } %> |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +<%= render :partial => 'default_activity', :locals => { :activity => activity, :tab_action => tab_action } %> |
@@ -0,0 +1,24 @@ | @@ -0,0 +1,24 @@ | ||
1 | +<div class="common-profile-list-block"> | ||
2 | + | ||
3 | +<h1><%= _("%s is following") % profile.name %></h1> | ||
4 | + | ||
5 | +<% cache_timeout(profile.friends_cache_key(params), 4.hours) do %> | ||
6 | +<ul class='profile-list'> | ||
7 | + <% @followed_people.each do |followed_person| %> | ||
8 | + <%= profile_image_link(followed_person) %> | ||
9 | + <% end%> | ||
10 | +</ul> | ||
11 | + | ||
12 | + <div id='pagination-profiles'> | ||
13 | + <%= pagination_links @followed_people, :param_name => 'npage' %> | ||
14 | + </div> | ||
15 | +<% end %> | ||
16 | + | ||
17 | +<%= button_bar do %> | ||
18 | + <%= button :back, _('Go back'), { :controller => 'profile' } %> | ||
19 | + <% if user == profile %> | ||
20 | + <%= button :edit, _('Manage followed people'), :controller => 'friends', :action => 'index', :profile => profile.identifier %> | ||
21 | + <% end %> | ||
22 | +<% end %> | ||
23 | + | ||
24 | +</div> |
app/views/profile_editor/edit.html.erb
@@ -23,8 +23,11 @@ | @@ -23,8 +23,11 @@ | ||
23 | </div> | 23 | </div> |
24 | 24 | ||
25 | <h2><%= _('Privacy options') %></h2> | 25 | <h2><%= _('Privacy options') %></h2> |
26 | - | 26 | + <div> |
27 | + <%= labelled_check_box _("Allow other users to follow me"), 'profile_data[allow_following]', true, @profile.allow_following?, :class => "person-can-be-followed" %> | ||
28 | + </div> | ||
27 | <% if profile.person? %> | 29 | <% if profile.person? %> |
30 | + <br> | ||
28 | <div> | 31 | <div> |
29 | <%= labelled_radio_button _('Public — show my contents to all internet users').html_safe, 'profile_data[public_profile]', true, @profile.public_profile? %> | 32 | <%= labelled_radio_button _('Public — show my contents to all internet users').html_safe, 'profile_data[public_profile]', true, @profile.public_profile? %> |
30 | </div> | 33 | </div> |
app/views/profile_editor/index.html.erb
@@ -72,6 +72,12 @@ | @@ -72,6 +72,12 @@ | ||
72 | 72 | ||
73 | <%= control_panel_button(_('Email Templates'), 'email-templates', :controller => :profile_email_templates) if profile.organization? %> | 73 | <%= control_panel_button(_('Email Templates'), 'email-templates', :controller => :profile_email_templates) if profile.organization? %> |
74 | 74 | ||
75 | + <% if profile.person? %> | ||
76 | + <%= control_panel_button(_('Manage followed profiles'), 'manage-followed-people', :controller => :followers) %> | ||
77 | + <% end %> | ||
78 | + | ||
79 | + <%= control_panel_button(_('Manage follow categories'), 'manage-follow-categories', :controller => :follow_categories) if profile.person? %> | ||
80 | + | ||
75 | <% @plugins.dispatch(:control_panel_buttons).each do |button| %> | 81 | <% @plugins.dispatch(:control_panel_buttons).each do |button| %> |
76 | <%= control_panel_button(button[:title], button[:icon], button[:url], button[:html_options]) %> | 82 | <%= control_panel_button(button[:title], button[:icon], button[:url], button[:html_options]) %> |
77 | <% end %> | 83 | <% end %> |
config/initializers/action_tracker.rb
@@ -12,6 +12,10 @@ ActionTrackerConfig.verbs = { | @@ -12,6 +12,10 @@ ActionTrackerConfig.verbs = { | ||
12 | type: :groupable | 12 | type: :groupable |
13 | }, | 13 | }, |
14 | 14 | ||
15 | + new_follower: { | ||
16 | + type: :groupable | ||
17 | + }, | ||
18 | + | ||
15 | join_community: { | 19 | join_community: { |
16 | type: :groupable | 20 | type: :groupable |
17 | }, | 21 | }, |
db/migrate/20160608123748_create_profile_followers_table.rb
0 → 100644
@@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
1 | +class CreateProfileFollowersTable < ActiveRecord::Migration | ||
2 | + def up | ||
3 | + create_table :profile_followers do |t| | ||
4 | + t.column :profile_id, :integer | ||
5 | + t.column :follower_id, :integer | ||
6 | + t.column :follow_category_id, :integer | ||
7 | + t.timestamps | ||
8 | + end | ||
9 | + | ||
10 | + create_table :follow_categories do |t| | ||
11 | + t.column :name, :string | ||
12 | + t.belongs_to :person | ||
13 | + end | ||
14 | + | ||
15 | + add_foreign_key :profile_followers, :follow_categories, :on_delete => :nullify | ||
16 | + | ||
17 | + add_index :profile_followers, [:profile_id, :follower_id], :name => "profile_followers_composite_key_index", :unique => true | ||
18 | + | ||
19 | + #insert one category for each friend group a person has | ||
20 | + execute("INSERT INTO follow_categories(name, person_id) SELECT DISTINCT (CASE WHEN (f.group IS NULL OR f.group = '') THEN 'friendships' ELSE f.group END), f.person_id FROM friendships as f") | ||
21 | + #insert 'memberships' category if a person is in a community as a member, moderator or profile admin | ||
22 | + execute("INSERT INTO follow_categories(name, person_id) SELECT DISTINCT 'memberships', ra.accessor_id FROM role_assignments as ra JOIN roles ON ra.role_id = roles.id WHERE roles.name IN ('Member','Moderator','Profile Administrator')") | ||
23 | + #insert 'favorites' category if a person has any favorited enterprise | ||
24 | + execute("INSERT INTO follow_categories(name, person_id) SELECT DISTINCT 'favorites', person_id FROM favorite_enterprise_people") | ||
25 | + | ||
26 | + #insert a follower entry for each friend, with the category the same as the friendship group or equals 'friendships' | ||
27 | + execute("INSERT INTO profile_followers(follower_id, profile_id, follow_category_id) SELECT DISTINCT f.person_id, f.friend_id, c.id FROM friendships as f JOIN follow_categories as c ON f.person_id = c.person_id WHERE c.name = f.group OR c.name = 'friendships'") | ||
28 | + #insert a follower entry for each favorited enterprise, with the category 'favorites' | ||
29 | + execute("INSERT INTO profile_followers(follower_id, profile_id, follow_category_id) SELECT DISTINCT f.person_id, f.enterprise_id, c.id FROM favorite_enterprise_people AS f JOIN follow_categories as c ON f.person_id = c.person_id WHERE c.name = 'favorites' ") | ||
30 | + #insert a follower entry for each community a person participates as a member, moderator or admininstrator | ||
31 | + execute("INSERT INTO profile_followers(follower_id, profile_id, follow_category_id) SELECT DISTINCT ra.accessor_id, ra.resource_id, c.id FROM role_assignments as ra JOIN roles ON ra.role_id = roles.id JOIN follow_categories as c ON ra.accessor_id = c.person_id WHERE roles.name IN ('Member','Moderator','Profile Administrator') AND c.name = 'memberships'") | ||
32 | + | ||
33 | + end | ||
34 | + | ||
35 | + def down | ||
36 | + remove_foreign_key :profile_followers, :follow_categories | ||
37 | + drop_table :follow_categories | ||
38 | + remove_index :profile_followers, :name => "profile_followers_composite_key_index" | ||
39 | + drop_table :profile_followers | ||
40 | + end | ||
41 | +end |
@@ -0,0 +1,55 @@ | @@ -0,0 +1,55 @@ | ||
1 | +Feature: follow profile | ||
2 | + As a noosfero user | ||
3 | + I want to follow a profile | ||
4 | + So I can receive notifications from it | ||
5 | + | ||
6 | + Background: | ||
7 | + Given the following community | ||
8 | + | identifier | name | | ||
9 | + | nightswatch | Nights Watch | | ||
10 | + And the following users | ||
11 | + | login | | ||
12 | + | johnsnow | | ||
13 | + And the user "johnsnow" has the following categories to follow | ||
14 | + | name | | ||
15 | + | Family | | ||
16 | + | Work | | ||
17 | + | ||
18 | + @selenium | ||
19 | + Scenario: Common noofero user follow a community with a category | ||
20 | + Given I am logged in as "johnsnow" | ||
21 | + When I go to nightswatch's homepage | ||
22 | + When I follow "Follow" | ||
23 | + And I should see "Family" | ||
24 | + And I should see "Work" | ||
25 | + And I should see "No Category" | ||
26 | + Then "johnsnow" should be a follower of "nightswatch" with no category | ||
27 | + When I follow "Work" | ||
28 | + Then "johnsnow" should be a follower of "nightswatch" with category "Work" | ||
29 | + | ||
30 | + @selenium | ||
31 | + Scenario: Common noofero user follow a community with no category | ||
32 | + Given I am logged in as "johnsnow" | ||
33 | + When I go to nightswatch's homepage | ||
34 | + When I follow "Follow" | ||
35 | + When I follow "No Category" | ||
36 | + Then "johnsnow" should be a follower of "nightswatch" with no category | ||
37 | + | ||
38 | + @selenium | ||
39 | + Scenario: Common noofero user follow a community with a new category | ||
40 | + Given I am logged in as "johnsnow" | ||
41 | + When I go to nightswatch's homepage | ||
42 | + When I follow "Follow" | ||
43 | + And I fill in "category_name" with "Winterfell" | ||
44 | + When I click on anything with selector "#new-category-submit-inline" | ||
45 | + And I wait 3 second | ||
46 | + Then "johnsnow" should be a follower of "nightswatch" with category "Winterfell" | ||
47 | + | ||
48 | + @selenium | ||
49 | + Scenario: Common noofero user unfollow a community | ||
50 | + Given "johnsnow" is a follower of "nightswatch" with no category | ||
51 | + And I am logged in as "johnsnow" | ||
52 | + When I go to nightswatch's homepage | ||
53 | + When I follow "Unfollow" | ||
54 | + Then "johnsnow" should not be a follower of "nightswatch" | ||
55 | + |
@@ -0,0 +1,39 @@ | @@ -0,0 +1,39 @@ | ||
1 | +Given /^the user "(.+)" has the following categories to follow$/ do |user_name,table| | ||
2 | + person = User.find_by(:login => user_name).person | ||
3 | + table.hashes.each do |category| | ||
4 | + FollowCategory.create!(:person => person, :name => category[:name]) | ||
5 | + end | ||
6 | +end | ||
7 | + | ||
8 | +Then /^"(.+)" should be a follower of "(.+)" (?:with no category|with category "(.+)")$/ do |person, profile, category| | ||
9 | + profile = Profile.find_by(identifier: profile) | ||
10 | + followers = profile.followers | ||
11 | + person = Person.find_by(identifier: person) | ||
12 | + followers.should include(person) | ||
13 | + | ||
14 | + if category | ||
15 | + ProfileFollower.find_by(:follower => person, :profile => profile).follow_category.name.should == category | ||
16 | + else | ||
17 | + ProfileFollower.find_by(:follower => person, :profile => profile).follow_category.should == nil | ||
18 | + end | ||
19 | +end | ||
20 | + | ||
21 | +Then /^"(.+)" should not be a follower of "(.+)"$/ do |person, profile| | ||
22 | + profile = Profile.find_by(identifier: profile) | ||
23 | + followers = profile.followers | ||
24 | + person = Person.find_by(identifier: person) | ||
25 | + followers.should_not include(person) | ||
26 | +end | ||
27 | + | ||
28 | +Given /^"(.+)" is a follower of "(.+)" (?:with no category|with category "(.+)")$/ do |person, profile, category| | ||
29 | + profile = Profile.find_by(identifier: profile) | ||
30 | + person = Person.find_by(identifier: person) | ||
31 | + params = {:follower => person, :profile => profile} | ||
32 | + | ||
33 | + if category | ||
34 | + category = FollowCategory.find_by(:name => category, :person => person) | ||
35 | + params.merge!({:follow_category => category}) | ||
36 | + end | ||
37 | + ProfileFollower.create!(params) | ||
38 | +end | ||
39 | + |
features/step_definitions/web_steps.rb
@@ -298,3 +298,6 @@ When /^(?:|I )wait ([^ ]+) seconds?(?:| .+)$/ do |seconds| | @@ -298,3 +298,6 @@ When /^(?:|I )wait ([^ ]+) seconds?(?:| .+)$/ do |seconds| | ||
298 | sleep seconds.to_f | 298 | sleep seconds.to_f |
299 | end | 299 | end |
300 | 300 | ||
301 | +Given /^I click on anything with selector "([^"]*)"$/ do |selector| | ||
302 | + page.evaluate_script("jQuery('#{selector}').click();") | ||
303 | +end |
public/javascripts/application.js
@@ -26,6 +26,7 @@ | @@ -26,6 +26,7 @@ | ||
26 | *= require pagination.js | 26 | *= require pagination.js |
27 | * views speficics | 27 | * views speficics |
28 | *= require add-and-join.js | 28 | *= require add-and-join.js |
29 | +*= require followers.js | ||
29 | *= require report-abuse.js | 30 | *= require report-abuse.js |
30 | *= require autogrow.js | 31 | *= require autogrow.js |
31 | *= require require_login.js | 32 | *= require require_login.js |
@@ -550,6 +551,11 @@ function loading_for_button(selector) { | @@ -550,6 +551,11 @@ function loading_for_button(selector) { | ||
550 | jQuery(selector).css('cursor', 'progress'); | 551 | jQuery(selector).css('cursor', 'progress'); |
551 | } | 552 | } |
552 | 553 | ||
554 | +function hide_loading_for_button(selector) { | ||
555 | + selector.css("cursor",""); | ||
556 | + $(".small-loading").remove(); | ||
557 | +} | ||
558 | + | ||
553 | function new_qualifier_row(selector, select_qualifiers, delete_button) { | 559 | function new_qualifier_row(selector, select_qualifiers, delete_button) { |
554 | index = jQuery(selector + ' tr').size() - 1; | 560 | index = jQuery(selector + ' tr').size() - 1; |
555 | jQuery(selector).append("<tr><td>" + select_qualifiers + "</td><td id='certifier-area-" + index + "'><select></select>" + delete_button + "</td></tr>"); | 561 | jQuery(selector).append("<tr><td>" + select_qualifiers + "</td><td id='certifier-area-" + index + "'><select></select>" + delete_button + "</td></tr>"); |
@@ -0,0 +1,18 @@ | @@ -0,0 +1,18 @@ | ||
1 | +$(".action-follow").live("click", function() { | ||
2 | + var button = $(this); | ||
3 | + var url = button.attr("href"); | ||
4 | + loading_for_button(button); | ||
5 | + | ||
6 | + $.post(url, function(data) { | ||
7 | + button.fadeOut('fast', function() { | ||
8 | + $("#follow-categories-container").html(data); | ||
9 | + $("#follow-categories-container").fadeIn(); | ||
10 | + }); | ||
11 | + }).fail(function(response) { | ||
12 | + display_notice(response.responseText); | ||
13 | + }).always(function() { | ||
14 | + hide_loading_for_button(button); | ||
15 | + }); | ||
16 | + | ||
17 | + return false; | ||
18 | +}); |
public/stylesheets/blocks/profile-info.scss
@@ -99,3 +99,25 @@ | @@ -99,3 +99,25 @@ | ||
99 | margin: 0px 0px 5px 0px; | 99 | margin: 0px 0px 5px 0px; |
100 | padding: 2px; | 100 | padding: 2px; |
101 | } | 101 | } |
102 | +#follow-categories-container { | ||
103 | + background-color: #eee; | ||
104 | + padding: 5px; | ||
105 | + display: flex; | ||
106 | +} | ||
107 | +#follow-categories-container p { | ||
108 | + font-size: 12px; | ||
109 | + margin-bottom: 5px; | ||
110 | +} | ||
111 | +#no-category-link { | ||
112 | + margin-top: 10px; | ||
113 | + margin-bottom: 10px; | ||
114 | +} | ||
115 | +#new-category-field-actions-block { | ||
116 | + float: left; | ||
117 | + width: 80%; | ||
118 | +} | ||
119 | +#new-category-submit-actions-block { | ||
120 | + float: right; | ||
121 | + width: 10%; | ||
122 | + padding-right: 10px; | ||
123 | +} |
public/stylesheets/profile-activity.scss
@@ -167,7 +167,9 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { | @@ -167,7 +167,9 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { | ||
167 | 167 | ||
168 | #profile-wall li.profile-activity-item.join_community .profile-activity-text a img, | 168 | #profile-wall li.profile-activity-item.join_community .profile-activity-text a img, |
169 | #profile-wall li.profile-activity-item.new_friendship .profile-activity-text a img, | 169 | #profile-wall li.profile-activity-item.new_friendship .profile-activity-text a img, |
170 | +#profile-wall li.profile-activity-item.new_follower .profile-activity-text a img, | ||
170 | #profile-network li.profile-activity-item.join_community .profile-activity-text a img, | 171 | #profile-network li.profile-activity-item.join_community .profile-activity-text a img, |
172 | +#profile-network li.profile-activity-item.new_follower .profile-activity-text a img, | ||
171 | #profile-network li.profile-activity-item.new_friendship .profile-activity-text a img { | 173 | #profile-network li.profile-activity-item.new_friendship .profile-activity-text a img { |
172 | margin: 5px 5px 0 0; | 174 | margin: 5px 5px 0 0; |
173 | padding: 1px; | 175 | padding: 1px; |
public/stylesheets/profile-list.scss
@@ -23,6 +23,7 @@ | @@ -23,6 +23,7 @@ | ||
23 | } | 23 | } |
24 | .controller-favorite_enterprises .profile-list a.profile-link, | 24 | .controller-favorite_enterprises .profile-list a.profile-link, |
25 | .controller-friends .profile-list a.profile-link, | 25 | .controller-friends .profile-list a.profile-link, |
26 | +.controller-followers .profile-list a.profile-link, | ||
26 | .list-profile-connections .profile-list a.profile-link, | 27 | .list-profile-connections .profile-list a.profile-link, |
27 | .profiles-suggestions .profile-list a.profile-link { | 28 | .profiles-suggestions .profile-list a.profile-link { |
28 | text-decoration: none; | 29 | text-decoration: none; |
@@ -32,11 +33,13 @@ | @@ -32,11 +33,13 @@ | ||
32 | } | 33 | } |
33 | .controller-favorite_enterprises .profile-list a.profile-link:hover, | 34 | .controller-favorite_enterprises .profile-list a.profile-link:hover, |
34 | .controller-friends .profile-list a.profile-link:hover, | 35 | .controller-friends .profile-list a.profile-link:hover, |
36 | +.controller-followers .profile-list a.profile-link:hover, | ||
35 | .profiles-suggestions .profile-list a.profile-link:hover { | 37 | .profiles-suggestions .profile-list a.profile-link:hover { |
36 | color: #FFF; | 38 | color: #FFF; |
37 | } | 39 | } |
38 | .controller-favorite_enterprises .profile-list .profile_link span, | 40 | .controller-favorite_enterprises .profile-list .profile_link span, |
39 | .controller-friends .profile-list .profile_link span, | 41 | .controller-friends .profile-list .profile_link span, |
42 | +.controller-followers .profile-list .profile_link span, | ||
40 | .box-1 .profiles-suggestions .profile-list .profile_link span { | 43 | .box-1 .profiles-suggestions .profile-list .profile_link span { |
41 | width: 80px; | 44 | width: 80px; |
42 | display: block; | 45 | display: block; |
@@ -44,12 +47,14 @@ | @@ -44,12 +47,14 @@ | ||
44 | } | 47 | } |
45 | .controller-favorite_enterprises .profile-list, | 48 | .controller-favorite_enterprises .profile-list, |
46 | .controller-friends .profile-list, | 49 | .controller-friends .profile-list, |
50 | +.controller-followers .profile-list, | ||
47 | .profiles-suggestions .profile-list { | 51 | .profiles-suggestions .profile-list { |
48 | position: relative; | 52 | position: relative; |
49 | } | 53 | } |
50 | 54 | ||
51 | .controller-favorite_enterprises .profile-list .controll, | 55 | .controller-favorite_enterprises .profile-list .controll, |
52 | .controller-friends .profile-list .controll, | 56 | .controller-friends .profile-list .controll, |
57 | +.controller-followers .profile-list .controll, | ||
53 | .profiles-suggestions .profile-list .controll { | 58 | .profiles-suggestions .profile-list .controll { |
54 | position: absolute; | 59 | position: absolute; |
55 | top: 7px; | 60 | top: 7px; |
@@ -57,17 +62,20 @@ | @@ -57,17 +62,20 @@ | ||
57 | } | 62 | } |
58 | .controller-favorite_enterprises .profile-list .controll a, | 63 | .controller-favorite_enterprises .profile-list .controll a, |
59 | .controller-friends .profile-list .controll a, | 64 | .controller-friends .profile-list .controll a, |
65 | +.controller-followers .profile-list .controll a, | ||
60 | .profiles-suggestions .profile-list .controll a { | 66 | .profiles-suggestions .profile-list .controll a { |
61 | display: block; | 67 | display: block; |
62 | margin-bottom: 2px; | 68 | margin-bottom: 2px; |
63 | } | 69 | } |
64 | .controller-favorite_enterprises .msie6 .profile-list .controll a, | 70 | .controller-favorite_enterprises .msie6 .profile-list .controll a, |
65 | .controller-friends .msie6 .profile-list .controll a, | 71 | .controller-friends .msie6 .profile-list .controll a, |
72 | +.controller-folloed_people .msie6 .profile-list .controll a, | ||
66 | .profiles-suggestions .msie6 .profile-list .controll a { | 73 | .profiles-suggestions .msie6 .profile-list .controll a { |
67 | width: 0px; | 74 | width: 0px; |
68 | } | 75 | } |
69 | .controller-favorite_enterprises .button-bar, | 76 | .controller-favorite_enterprises .button-bar, |
70 | .controller-friends .button-bar, | 77 | .controller-friends .button-bar, |
78 | +.controller-followers .button-bar, | ||
71 | .profiles-suggestions .button-bar { | 79 | .profiles-suggestions .button-bar { |
72 | clear: both; | 80 | clear: both; |
73 | padding-top: 20px; | 81 | padding-top: 20px; |
@@ -208,22 +216,35 @@ | @@ -208,22 +216,35 @@ | ||
208 | font-size: 12px; | 216 | font-size: 12px; |
209 | } | 217 | } |
210 | .action-profile-members .profile_link{ | 218 | .action-profile-members .profile_link{ |
211 | - position: relative; | 219 | + position: relative; |
212 | } | 220 | } |
213 | .action-profile-members .profile_link span.new-profile:last-child{ | 221 | .action-profile-members .profile_link span.new-profile:last-child{ |
214 | - position: absolute; | ||
215 | - top: 3px; | ||
216 | - right: 2px; | ||
217 | - text-transform: uppercase; | ||
218 | - color: #FFF; | ||
219 | - font-size: 9px; | ||
220 | - background: #66CC33; | ||
221 | - padding: 2px; | ||
222 | - display: block; | ||
223 | - width: 35px; | ||
224 | - font-weight: 700; | 222 | + position: absolute; |
223 | + top: 3px; | ||
224 | + right: 2px; | ||
225 | + text-transform: uppercase; | ||
226 | + color: #FFF; | ||
227 | + font-size: 9px; | ||
228 | + background: #66CC33; | ||
229 | + padding: 2px; | ||
230 | + display: block; | ||
231 | + width: 35px; | ||
232 | + font-weight: 700; | ||
225 | } | 233 | } |
226 | .action-profile-members .profile_link .fn{ | 234 | .action-profile-members .profile_link .fn{ |
227 | - font-style: normal; | ||
228 | - color: #000; | 235 | + font-style: normal; |
236 | + color: #000; | ||
237 | +} | ||
238 | +.category-name { | ||
239 | + margin-top: 0px; | ||
240 | + margin-bottom: 0px; | ||
241 | + font-style: italic; | ||
242 | + color: #888a85; | ||
243 | + text-align: center; | ||
244 | +} | ||
245 | +.set-category-modal { | ||
246 | + width: 250px; | ||
247 | +} | ||
248 | +.set-category-modal #actions-container { | ||
249 | + margin-top: 20px | ||
229 | } | 250 | } |
@@ -0,0 +1,103 @@ | @@ -0,0 +1,103 @@ | ||
1 | +require_relative "../test_helper" | ||
2 | +require 'follow_categories_controller' | ||
3 | + | ||
4 | +class FollowCategoriesControllerTest < ActionController::TestCase | ||
5 | + | ||
6 | + def setup | ||
7 | + @controller = FollowCategoriesController.new | ||
8 | + @person = create_user('person').person | ||
9 | + login_as(@person.identifier) | ||
10 | + end | ||
11 | + | ||
12 | + should 'return all categories of a profile' do | ||
13 | + category1 = FollowCategory.create(:name => "category1", :person => @person) | ||
14 | + category2 = FollowCategory.create(:name => "category2", :person => @person) | ||
15 | + get :index, :profile => @person.identifier | ||
16 | + | ||
17 | + assert_equivalent [category1, category2], assigns[:categories] | ||
18 | + end | ||
19 | + | ||
20 | + should 'initialize an empty category for creation' do | ||
21 | + get :new, :profile => @person.identifier | ||
22 | + assert_nil assigns[:follow_category].id | ||
23 | + assert_nil assigns[:follow_category].name | ||
24 | + end | ||
25 | + | ||
26 | + should 'create a new category' do | ||
27 | + assert_difference '@person.follow_categories.count' do | ||
28 | + post :create, :profile => @person.identifier, | ||
29 | + :follow_category => { :name => 'category' } | ||
30 | + end | ||
31 | + assert_redirected_to :action => :index | ||
32 | + end | ||
33 | + | ||
34 | + should 'not create a category without a name' do | ||
35 | + assert_no_difference '@person.follow_categories.count' do | ||
36 | + post :create, :profile => @person.identifier, :follow_category => { :name => nil } | ||
37 | + end | ||
38 | + assert_template :new | ||
39 | + end | ||
40 | + | ||
41 | + should 'retrieve an existing category when editing' do | ||
42 | + category = FollowCategory.create(:name => "category", :person => @person) | ||
43 | + get :edit, :profile => @person.identifier, :id => category.id | ||
44 | + assert_equal category.name, assigns[:follow_category].name | ||
45 | + end | ||
46 | + | ||
47 | + should 'return 404 when editing a category that does not exist' do | ||
48 | + get :edit, :profile => @person.identifier, :id => "nope" | ||
49 | + assert_response 404 | ||
50 | + end | ||
51 | + | ||
52 | + should 'update an existing category' do | ||
53 | + category = FollowCategory.create(:name => "category", :person => @person) | ||
54 | + get :update, :profile => @person.identifier, :id => category.id, | ||
55 | + :follow_category => { :name => "new name" } | ||
56 | + | ||
57 | + category.reload | ||
58 | + assert_equal "new name", category.name | ||
59 | + assert_redirected_to :action => :index | ||
60 | + end | ||
61 | + | ||
62 | + should 'not update an existing category without a name' do | ||
63 | + category = FollowCategory.create(:name => "category", :person => @person) | ||
64 | + get :update, :profile => @person.identifier, :id => category.id, | ||
65 | + :follow_category => { :name => nil } | ||
66 | + | ||
67 | + category.reload | ||
68 | + assert_equal "category", category.name | ||
69 | + assert_template :edit | ||
70 | + end | ||
71 | + | ||
72 | + should 'return 404 when updating a category that does not exist' do | ||
73 | + get :update, :profile => @person.identifier, :id => "nope", :name => "new name" | ||
74 | + assert_response 404 | ||
75 | + end | ||
76 | + | ||
77 | + should 'destroy an existing category and update related profiles' do | ||
78 | + category = FollowCategory.create(:name => "category", :person => @person) | ||
79 | + follower = fast_create(ProfileFollower, :profile_id => fast_create(Person).id, | ||
80 | + :follower_id => @person.id, :follow_category_id => category.id) | ||
81 | + | ||
82 | + assert_difference "@person.follow_categories.count", -1 do | ||
83 | + get :destroy, :profile => @person.identifier, :id => category.id | ||
84 | + end | ||
85 | + | ||
86 | + follower.reload | ||
87 | + assert_nil follower.follow_category | ||
88 | + end | ||
89 | + | ||
90 | + should 'return 404 when deleting and category that does not exist' do | ||
91 | + get :destroy, :profile => @person.identifier, :id => "nope" | ||
92 | + assert_response 404 | ||
93 | + end | ||
94 | + | ||
95 | + should 'display notice when ' do | ||
96 | + category = FollowCategory.create(:name => "category", :person => @person) | ||
97 | + FollowCategory.any_instance.stubs(:destroy).returns(false) | ||
98 | + | ||
99 | + get :destroy, :profile => @person.identifier, :id => category.id | ||
100 | + assert_not_nil session[:notice] | ||
101 | + end | ||
102 | + | ||
103 | +end |
@@ -0,0 +1,48 @@ | @@ -0,0 +1,48 @@ | ||
1 | +require_relative "../test_helper" | ||
2 | +require 'followers_controller' | ||
3 | + | ||
4 | +class FollowersControllerTest < ActionController::TestCase | ||
5 | + def setup | ||
6 | + @profile = create_user('testuser').person | ||
7 | + end | ||
8 | + | ||
9 | + should 'return followed people list' do | ||
10 | + login_as(@profile.identifier) | ||
11 | + person = fast_create(Person) | ||
12 | + fast_create(ProfileFollower, :profile_id => person.id, :follower_id => @profile.id) | ||
13 | + | ||
14 | + get :index, :profile => @profile.identifier | ||
15 | + assert_includes assigns(:followed_people), person | ||
16 | + end | ||
17 | + | ||
18 | + should 'redirect to login page if not logged in' do | ||
19 | + person = fast_create(Person) | ||
20 | + get :index, :profile => @profile.identifier | ||
21 | + assert_redirected_to :controller => 'account', :action => 'login' | ||
22 | + end | ||
23 | + | ||
24 | + should 'render set category modal' do | ||
25 | + login_as(@profile.identifier) | ||
26 | + get :set_category, :profile => @profile.identifier, :followed_profile_id => 3 | ||
27 | + assert_tag :tag => "input", :attributes => { :id => "followed_profile_id", :value => 3 } | ||
28 | + end | ||
29 | + | ||
30 | + should 'update followed person category' do | ||
31 | + login_as(@profile.identifier) | ||
32 | + person = fast_create(Person) | ||
33 | + fast_create(ProfileFollower, :profile_id => person.id, :follower_id => @profile.id) | ||
34 | + | ||
35 | + post :set_category, :profile => @profile.identifier, :category_name => "category test", :followed_profile_id => person.id | ||
36 | + follower = ProfileFollower.find_by(:profile_id => person.id, :follower_id => @profile.id) | ||
37 | + assert_equal "WRONG","FIX THIS TEST TO USE CATEGORY INsTEAD OF GROUP" #follower.group, "category test" | ||
38 | + end | ||
39 | + | ||
40 | + should 'not update category of not followed person' do | ||
41 | + login_as(@profile.identifier) | ||
42 | + person = fast_create(Person) | ||
43 | + | ||
44 | + post :set_category, :profile => @profile.identifier, :category_name => "category test", :followed_profile_id => person.id | ||
45 | + follower = ProfileFollower.find_by(:profile_id => person.id, :follower_id => @profile.id) | ||
46 | + ProfileFollower.any_instance.expects(:update_attributes).times(0) | ||
47 | + end | ||
48 | +end |
test/functional/profile_controller_test.rb
@@ -771,12 +771,13 @@ class ProfileControllerTest < ActionController::TestCase | @@ -771,12 +771,13 @@ class ProfileControllerTest < ActionController::TestCase | ||
771 | assert_equal 15, assigns(:activities).size | 771 | assert_equal 15, assigns(:activities).size |
772 | end | 772 | end |
773 | 773 | ||
774 | - should 'not see the friends activities in the current profile' do | 774 | + should 'not see the followers activities in the current profile' do |
775 | p2 = create_user.person | 775 | p2 = create_user.person |
776 | - refute profile.is_a_friend?(p2) | 776 | + refute profile.follows?(p2) |
777 | p3 = create_user.person | 777 | p3 = create_user.person |
778 | - p3.add_friend(profile) | ||
779 | - assert p3.is_a_friend?(profile) | 778 | + profile.follow(p3) |
779 | + assert profile.follows?(p3) | ||
780 | + | ||
780 | ActionTracker::Record.destroy_all | 781 | ActionTracker::Record.destroy_all |
781 | 782 | ||
782 | scrap1 = create(Scrap, defaults_for_scrap(:sender => p2, :receiver => p3)) | 783 | scrap1 = create(Scrap, defaults_for_scrap(:sender => p2, :receiver => p3)) |
@@ -964,7 +965,9 @@ class ProfileControllerTest < ActionController::TestCase | @@ -964,7 +965,9 @@ class ProfileControllerTest < ActionController::TestCase | ||
964 | should 'have activities defined if logged in and is following profile' do | 965 | should 'have activities defined if logged in and is following profile' do |
965 | login_as(profile.identifier) | 966 | login_as(profile.identifier) |
966 | p1= fast_create(Person) | 967 | p1= fast_create(Person) |
967 | - p1.add_friend(profile) | 968 | + |
969 | + profile.follow(p1) | ||
970 | + | ||
968 | ActionTracker::Record.destroy_all | 971 | ActionTracker::Record.destroy_all |
969 | get :index, :profile => p1.identifier | 972 | get :index, :profile => p1.identifier |
970 | assert_equal [], assigns(:activities) | 973 | assert_equal [], assigns(:activities) |
@@ -1932,4 +1935,77 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1932,4 +1935,77 @@ class ProfileControllerTest < ActionController::TestCase | ||
1932 | assert_redirected_to :controller => 'account', :action => 'login' | 1935 | assert_redirected_to :controller => 'account', :action => 'login' |
1933 | end | 1936 | end |
1934 | 1937 | ||
1938 | + should 'follow a user without defining a group' do | ||
1939 | + login_as(@profile.identifier) | ||
1940 | + person = fast_create(Person) | ||
1941 | + get :follow, :profile => person.identifier | ||
1942 | + | ||
1943 | + follower = ProfileFollower.find_by(:profile_id => person.id, :follower_id => @profile.id) | ||
1944 | + assert_not_nil follower | ||
1945 | + end | ||
1946 | + | ||
1947 | + should "not follow user if not logged" do | ||
1948 | + person = fast_create(Person) | ||
1949 | + get :follow, :profile => person.identifier | ||
1950 | + | ||
1951 | + assert_redirected_to :controller => 'account', :action => 'login' | ||
1952 | + end | ||
1953 | + | ||
1954 | + should 'follow a user with a group' do | ||
1955 | + login_as(@profile.identifier) | ||
1956 | + person = fast_create(Person) | ||
1957 | + get :follow, :profile => person.identifier, :follow => { :category => "A Group" } | ||
1958 | + | ||
1959 | + follower = ProfileFollower.find_by(:profile_id => person.id, :follower_id => @profile.id) | ||
1960 | + assert_not_nil follower | ||
1961 | + assert_equal "A Group", "FIX THIS TEST TO USE CATEGORY INsTEAD OF GROUP"#follower.category.name | ||
1962 | + end | ||
1963 | + | ||
1964 | + should 'not follow if current_person already follows the person' do | ||
1965 | + login_as(@profile.identifier) | ||
1966 | + person = fast_create(Person) | ||
1967 | + fast_create(ProfileFollower, :profile_id => person.id, :follower_id => @profile.id) | ||
1968 | + | ||
1969 | + assert_no_difference 'ProfileFollower.count' do | ||
1970 | + get :follow, :profile => person.identifier, :follow => { :category => "A Group" } | ||
1971 | + end | ||
1972 | + assert_response 400 | ||
1973 | + end | ||
1974 | + | ||
1975 | + should "not unfollow user if not logged" do | ||
1976 | + person = fast_create(Person) | ||
1977 | + get :unfollow, :profile => person.identifier | ||
1978 | + | ||
1979 | + assert_redirected_to :controller => 'account', :action => 'login' | ||
1980 | + end | ||
1981 | + | ||
1982 | + should "unfollow a followed person" do | ||
1983 | + login_as(@profile.identifier) | ||
1984 | + person = fast_create(Person) | ||
1985 | + follower = fast_create(ProfileFollower, :profile_id => person.id, :follower_id => @profile.id) | ||
1986 | + assert_not_nil follower | ||
1987 | + | ||
1988 | + get :unfollow, :profile => person.identifier | ||
1989 | + follower = ProfileFollower.find_by(:profile_id => person.id, :follower_id => @profile.id) | ||
1990 | + assert_nil follower | ||
1991 | + end | ||
1992 | + | ||
1993 | + should "not unfollow a not followed person" do | ||
1994 | + login_as(@profile.identifier) | ||
1995 | + person = fast_create(Person) | ||
1996 | + | ||
1997 | + assert_no_difference 'ProfileFollower.count' do | ||
1998 | + get :unfollow, :profile => person.identifier | ||
1999 | + end | ||
2000 | + end | ||
2001 | + | ||
2002 | + should "redirect to page after unfollow" do | ||
2003 | + login_as(@profile.identifier) | ||
2004 | + person = fast_create(Person) | ||
2005 | + fast_create(ProfileFollower, :profile_id => person.id, :follower_id => @profile.id) | ||
2006 | + | ||
2007 | + get :unfollow, :profile => person.identifier, :redirect_to => "/some/url" | ||
2008 | + assert_redirected_to "/some/url" | ||
2009 | + end | ||
2010 | + | ||
1935 | end | 2011 | end |
test/unit/article_test.rb
@@ -1099,9 +1099,9 @@ class ArticleTest < ActiveSupport::TestCase | @@ -1099,9 +1099,9 @@ class ArticleTest < ActiveSupport::TestCase | ||
1099 | assert_equal 3, ActionTrackerNotification.where(action_tracker_id: second_activity.id).count | 1099 | assert_equal 3, ActionTrackerNotification.where(action_tracker_id: second_activity.id).count |
1100 | end | 1100 | end |
1101 | 1101 | ||
1102 | - should 'create notifications to friends when creating an article' do | 1102 | + should 'create notifications to followers when creating an article' do |
1103 | friend = fast_create(Person) | 1103 | friend = fast_create(Person) |
1104 | - profile.add_friend(friend) | 1104 | + friend.follow(profile) |
1105 | Article.destroy_all | 1105 | Article.destroy_all |
1106 | ActionTracker::Record.destroy_all | 1106 | ActionTracker::Record.destroy_all |
1107 | ActionTrackerNotification.destroy_all | 1107 | ActionTrackerNotification.destroy_all |
@@ -1112,9 +1112,9 @@ class ArticleTest < ActiveSupport::TestCase | @@ -1112,9 +1112,9 @@ class ArticleTest < ActiveSupport::TestCase | ||
1112 | assert_equal friend, ActionTrackerNotification.last.profile | 1112 | assert_equal friend, ActionTrackerNotification.last.profile |
1113 | end | 1113 | end |
1114 | 1114 | ||
1115 | - should 'create the notification to the friend when one friend has the notification and the other no' do | 1115 | + should 'create the notification to the follower when one follower has the notification and the other no' do |
1116 | f1 = fast_create(Person) | 1116 | f1 = fast_create(Person) |
1117 | - profile.add_friend(f1) | 1117 | + f1.follow(profile) |
1118 | 1118 | ||
1119 | User.current = profile.user | 1119 | User.current = profile.user |
1120 | article = create TinyMceArticle, :name => 'Tracked Article 1', :profile_id => profile.id | 1120 | article = create TinyMceArticle, :name => 'Tracked Article 1', :profile_id => profile.id |
@@ -1123,16 +1123,17 @@ class ArticleTest < ActiveSupport::TestCase | @@ -1123,16 +1123,17 @@ class ArticleTest < ActiveSupport::TestCase | ||
1123 | assert_equal 2, ActionTrackerNotification.where(action_tracker_id: article.activity.id).count | 1123 | assert_equal 2, ActionTrackerNotification.where(action_tracker_id: article.activity.id).count |
1124 | 1124 | ||
1125 | f2 = fast_create(Person) | 1125 | f2 = fast_create(Person) |
1126 | - profile.add_friend(f2) | 1126 | + f2.follow(profile) |
1127 | + | ||
1127 | article2 = create TinyMceArticle, :name => 'Tracked Article 2', :profile_id => profile.id | 1128 | article2 = create TinyMceArticle, :name => 'Tracked Article 2', :profile_id => profile.id |
1128 | assert_equal 2, ActionTracker::Record.where(verb: 'create_article').count | 1129 | assert_equal 2, ActionTracker::Record.where(verb: 'create_article').count |
1129 | process_delayed_job_queue | 1130 | process_delayed_job_queue |
1130 | assert_equal 3, ActionTrackerNotification.where(action_tracker_id: article2.activity.id).count | 1131 | assert_equal 3, ActionTrackerNotification.where(action_tracker_id: article2.activity.id).count |
1131 | end | 1132 | end |
1132 | 1133 | ||
1133 | - should 'destroy activity and notifications of friends when destroying an article' do | 1134 | + should 'destroy activity and notifications of followers when destroying an article' do |
1134 | friend = fast_create(Person) | 1135 | friend = fast_create(Person) |
1135 | - profile.add_friend(friend) | 1136 | + friend.follow(profile) |
1136 | Article.destroy_all | 1137 | Article.destroy_all |
1137 | ActionTracker::Record.destroy_all | 1138 | ActionTracker::Record.destroy_all |
1138 | ActionTrackerNotification.destroy_all | 1139 | ActionTrackerNotification.destroy_all |
test/unit/friendship_test.rb
@@ -28,14 +28,14 @@ class FriendshipTest < ActiveSupport::TestCase | @@ -28,14 +28,14 @@ class FriendshipTest < ActiveSupport::TestCase | ||
28 | f.person = a | 28 | f.person = a |
29 | f.friend = b | 29 | f.friend = b |
30 | f.save! | 30 | f.save! |
31 | - ta = ActionTracker::Record.last | 31 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last |
32 | assert_equal a, ta.user | 32 | assert_equal a, ta.user |
33 | assert_equal 'b', ta.get_friend_name[0] | 33 | assert_equal 'b', ta.get_friend_name[0] |
34 | f = Friendship.new | 34 | f = Friendship.new |
35 | f.person = a | 35 | f.person = a |
36 | f.friend = c | 36 | f.friend = c |
37 | f.save! | 37 | f.save! |
38 | - ta = ActionTracker::Record.last | 38 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last |
39 | assert_equal a, ta.user | 39 | assert_equal a, ta.user |
40 | assert_equal 'c', ta.get_friend_name[1] | 40 | assert_equal 'c', ta.get_friend_name[1] |
41 | end | 41 | end |
@@ -46,14 +46,14 @@ class FriendshipTest < ActiveSupport::TestCase | @@ -46,14 +46,14 @@ class FriendshipTest < ActiveSupport::TestCase | ||
46 | f.person = a | 46 | f.person = a |
47 | f.friend = b | 47 | f.friend = b |
48 | f.save! | 48 | f.save! |
49 | - ta = ActionTracker::Record.last | 49 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last |
50 | assert_equal a, ta.user | 50 | assert_equal a, ta.user |
51 | assert_equal ['b'], ta.get_friend_name | 51 | assert_equal ['b'], ta.get_friend_name |
52 | f = Friendship.new | 52 | f = Friendship.new |
53 | f.person = b | 53 | f.person = b |
54 | f.friend = a | 54 | f.friend = a |
55 | f.save! | 55 | f.save! |
56 | - ta = ActionTracker::Record.last | 56 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last |
57 | assert_equal b, ta.user | 57 | assert_equal b, ta.user |
58 | assert_equal ['a'], ta.get_friend_name | 58 | assert_equal ['a'], ta.get_friend_name |
59 | end | 59 | end |
@@ -72,4 +72,53 @@ class FriendshipTest < ActiveSupport::TestCase | @@ -72,4 +72,53 @@ class FriendshipTest < ActiveSupport::TestCase | ||
72 | assert_not_includes p2.friends(true), p1 | 72 | assert_not_includes p2.friends(true), p1 |
73 | end | 73 | end |
74 | 74 | ||
75 | + should 'add follower when adding friend' do | ||
76 | + p1 = create_user('testuser1').person | ||
77 | + p2 = create_user('testuser2').person | ||
78 | + | ||
79 | + assert_difference 'ProfileFollower.count', 2 do | ||
80 | + p1.add_friend(p2, 'friends') | ||
81 | + p2.add_friend(p1, 'friends') | ||
82 | + end | ||
83 | + | ||
84 | + assert_includes p1.followers(true), p2 | ||
85 | + assert_includes p2.followers(true), p1 | ||
86 | + end | ||
87 | + | ||
88 | + should 'remove follower when a friend removal occurs' do | ||
89 | + p1 = create_user('testuser1').person | ||
90 | + p2 = create_user('testuser2').person | ||
91 | + | ||
92 | + p1.add_friend(p2, 'friends') | ||
93 | + p2.add_friend(p1, 'friends') | ||
94 | + | ||
95 | + Friendship.remove_friendship(p1, p2) | ||
96 | + | ||
97 | + assert_not_includes p1.followers(true), p2 | ||
98 | + assert_not_includes p2.followers(true), p1 | ||
99 | + end | ||
100 | + | ||
101 | + should 'keep friendship intact when stop following' do | ||
102 | + p1 = create_user('testuser1').person | ||
103 | + p2 = create_user('testuser2').person | ||
104 | + | ||
105 | + p1.add_friend(p2, 'friends') | ||
106 | + p2.add_friend(p1, 'friends') | ||
107 | + | ||
108 | + p1.unfollow(p2) | ||
109 | + | ||
110 | + assert_includes p1.friends(true), p2 | ||
111 | + assert_includes p2.friends(true), p1 | ||
112 | + end | ||
113 | + | ||
114 | + should 'do not add friendship when start following' do | ||
115 | + p1 = create_user('testuser1').person | ||
116 | + p2 = create_user('testuser2').person | ||
117 | + | ||
118 | + p1.follow(p2, 'favorites') | ||
119 | + p2.follow(p1, 'favorites') | ||
120 | + | ||
121 | + assert_not_includes p1.friends(true), p2 | ||
122 | + assert_not_includes p2.friends(true), p1 | ||
123 | + end | ||
75 | end | 124 | end |
test/unit/notify_activity_to_profiles_job_test.rb
@@ -24,15 +24,15 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase | @@ -24,15 +24,15 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase | ||
24 | end | 24 | end |
25 | end | 25 | end |
26 | 26 | ||
27 | - should 'notify just the users and his friends tracking user actions' do | 27 | + should 'notify just the users and his followers tracking user actions' do |
28 | person = fast_create(Person) | 28 | person = fast_create(Person) |
29 | community = fast_create(Community) | 29 | community = fast_create(Community) |
30 | action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :verb => 'create_article') | 30 | action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :verb => 'create_article') |
31 | refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb) | 31 | refute 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) | 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(Friendship, :person_id => p1.id, :friend_id => m1.id) | 33 | + fast_create(ProfileFollower, :profile_id => person.id, :follower_id => p1.id) |
34 | + fast_create(ProfileFollower, :profile_id => person.id, :follower_id => p2.id) | ||
35 | + fast_create(ProfileFollower, :profile_id => m1.id, :follower_id => person.id) | ||
36 | fast_create(RoleAssignment, :accessor_id => m2.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 | 37 | ActionTrackerNotification.delete_all |
38 | job = NotifyActivityToProfilesJob.new(action_tracker.id) | 38 | job = NotifyActivityToProfilesJob.new(action_tracker.id) |
@@ -66,23 +66,21 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase | @@ -66,23 +66,21 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase | ||
66 | end | 66 | end |
67 | end | 67 | end |
68 | 68 | ||
69 | - should 'notify users its friends, the community and its members' do | 69 | + should 'notify users its followers, the community and its members' do |
70 | person = fast_create(Person) | 70 | person = fast_create(Person) |
71 | community = fast_create(Community) | 71 | community = fast_create(Community) |
72 | action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'create_article') | 72 | action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'create_article') |
73 | refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb) | 73 | refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb) |
74 | p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person) | 74 | p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person) |
75 | - fast_create(Friendship, :person_id => person.id, :friend_id => p1.id) | ||
76 | - fast_create(Friendship, :person_id => person.id, :friend_id => p2.id) | 75 | + fast_create(ProfileFollower, :profile_id => person.id, :follower_id => p1.id) |
77 | fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id) | 76 | fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id) |
78 | fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id) | 77 | fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id) |
79 | ActionTrackerNotification.delete_all | 78 | ActionTrackerNotification.delete_all |
80 | job = NotifyActivityToProfilesJob.new(action_tracker.id) | 79 | job = NotifyActivityToProfilesJob.new(action_tracker.id) |
81 | job.perform | 80 | job.perform |
82 | process_delayed_job_queue | 81 | process_delayed_job_queue |
83 | - | ||
84 | - assert_equal 6, ActionTrackerNotification.count | ||
85 | - [person, community, p1, p2, m1, m2].each do |profile| | 82 | + assert_equal 5, ActionTrackerNotification.count |
83 | + [person, community, p1, m1, m2].each do |profile| | ||
86 | notification = ActionTrackerNotification.find_by profile_id: profile.id | 84 | notification = ActionTrackerNotification.find_by profile_id: profile.id |
87 | assert_equal action_tracker, notification.action_tracker | 85 | assert_equal action_tracker, notification.action_tracker |
88 | end | 86 | end |
@@ -119,8 +117,8 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase | @@ -119,8 +117,8 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase | ||
119 | action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'join_community') | 117 | action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'join_community') |
120 | refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb) | 118 | refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb) |
121 | p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person) | 119 | p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person) |
122 | - fast_create(Friendship, :person_id => person.id, :friend_id => p1.id) | ||
123 | - fast_create(Friendship, :person_id => person.id, :friend_id => p2.id) | 120 | + fast_create(ProfileFollower, :profile_id => person.id, :follower_id => p1.id) |
121 | + fast_create(ProfileFollower, :profile_id => person.id, :follower_id => p2.id) | ||
124 | fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id) | 122 | fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id) |
125 | fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id) | 123 | fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id) |
126 | ActionTrackerNotification.delete_all | 124 | ActionTrackerNotification.delete_all |
test/unit/person_notifier_test.rb
@@ -178,6 +178,7 @@ class PersonNotifierTest < ActiveSupport::TestCase | @@ -178,6 +178,7 @@ class PersonNotifierTest < ActiveSupport::TestCase | ||
178 | update_product: -> { create Product, profile: @profile, product_category: create(ProductCategory, environment: Environment.default) }, | 178 | update_product: -> { create Product, profile: @profile, product_category: create(ProductCategory, environment: Environment.default) }, |
179 | remove_product: -> { create Product, profile: @profile, product_category: create(ProductCategory, environment: Environment.default) }, | 179 | remove_product: -> { create Product, profile: @profile, product_category: create(ProductCategory, environment: Environment.default) }, |
180 | favorite_enterprise: -> { create FavoriteEnterprisePerson, enterprise: create(Enterprise), person: @member }, | 180 | favorite_enterprise: -> { create FavoriteEnterprisePerson, enterprise: create(Enterprise), person: @member }, |
181 | + new_follower: -> { @member } | ||
181 | } | 182 | } |
182 | 183 | ||
183 | ActionTrackerConfig.verb_names.each do |verb| | 184 | ActionTrackerConfig.verb_names.each do |verb| |
@@ -197,6 +198,7 @@ class PersonNotifierTest < ActiveSupport::TestCase | @@ -197,6 +198,7 @@ class PersonNotifierTest < ActiveSupport::TestCase | ||
197 | 'friend_url' => '/', 'friend_profile_custom_icon' => [], 'friend_name' => ['joe'], | 198 | 'friend_url' => '/', 'friend_profile_custom_icon' => [], 'friend_name' => ['joe'], |
198 | 'resource_name' => ['resource'], 'resource_profile_custom_icon' => [], 'resource_url' => ['/'], | 199 | 'resource_name' => ['resource'], 'resource_profile_custom_icon' => [], 'resource_url' => ['/'], |
199 | 'enterprise_name' => 'coop', 'enterprise_url' => '/coop', | 200 | 'enterprise_name' => 'coop', 'enterprise_url' => '/coop', |
201 | + 'follower_url' => '/', 'follower_profile_custom_icon' => [], 'follower_name' => ['joe'], | ||
200 | 'view_url'=> ['/'], 'thumbnail_path' => ['1'], | 202 | 'view_url'=> ['/'], 'thumbnail_path' => ['1'], |
201 | } | 203 | } |
202 | a.get_url = '' | 204 | a.get_url = '' |
test/unit/person_test.rb
@@ -728,7 +728,7 @@ class PersonTest < ActiveSupport::TestCase | @@ -728,7 +728,7 @@ class PersonTest < ActiveSupport::TestCase | ||
728 | assert_equal [s4], p2.scraps_received.not_replies | 728 | assert_equal [s4], p2.scraps_received.not_replies |
729 | end | 729 | end |
730 | 730 | ||
731 | - should "the followed_by method be protected and true to the person friends and herself by default" do | 731 | + should "the followed_by method return true to the person friends and herself by default" do |
732 | p1 = fast_create(Person) | 732 | p1 = fast_create(Person) |
733 | p2 = fast_create(Person) | 733 | p2 = fast_create(Person) |
734 | p3 = fast_create(Person) | 734 | p3 = fast_create(Person) |
@@ -740,9 +740,9 @@ class PersonTest < ActiveSupport::TestCase | @@ -740,9 +740,9 @@ class PersonTest < ActiveSupport::TestCase | ||
740 | assert p1.is_a_friend?(p4) | 740 | assert p1.is_a_friend?(p4) |
741 | 741 | ||
742 | assert_equal true, p1.send(:followed_by?,p1) | 742 | assert_equal true, p1.send(:followed_by?,p1) |
743 | - assert_equal true, p1.send(:followed_by?,p2) | ||
744 | - assert_equal true, p1.send(:followed_by?,p4) | ||
745 | - assert_equal false, p1.send(:followed_by?,p3) | 743 | + assert_equal true, p2.send(:followed_by?,p1) |
744 | + assert_equal true, p4.send(:followed_by?,p1) | ||
745 | + assert_equal false, p3.send(:followed_by?,p1) | ||
746 | end | 746 | end |
747 | 747 | ||
748 | should "the person follows her friends and herself by default" do | 748 | should "the person follows her friends and herself by default" do |
@@ -757,9 +757,9 @@ class PersonTest < ActiveSupport::TestCase | @@ -757,9 +757,9 @@ class PersonTest < ActiveSupport::TestCase | ||
757 | assert p4.is_a_friend?(p1) | 757 | assert p4.is_a_friend?(p1) |
758 | 758 | ||
759 | assert_equal true, p1.follows?(p1) | 759 | assert_equal true, p1.follows?(p1) |
760 | - assert_equal true, p1.follows?(p2) | ||
761 | - assert_equal true, p1.follows?(p4) | ||
762 | - assert_equal false, p1.follows?(p3) | 760 | + assert_equal true, p2.follows?(p1) |
761 | + assert_equal true, p4.follows?(p1) | ||
762 | + assert_equal false, p3.follows?(p1) | ||
763 | end | 763 | end |
764 | 764 | ||
765 | should "a person member of a community follows the community" do | 765 | should "a person member of a community follows the community" do |
@@ -836,18 +836,18 @@ class PersonTest < ActiveSupport::TestCase | @@ -836,18 +836,18 @@ class PersonTest < ActiveSupport::TestCase | ||
836 | assert_nil Scrap.find_by(id: scrap.id) | 836 | assert_nil Scrap.find_by(id: scrap.id) |
837 | end | 837 | end |
838 | 838 | ||
839 | - should "the tracked action be notified to person friends and herself" do | 839 | + should "the tracked action be notified to person followers and herself" do |
840 | Person.destroy_all | 840 | Person.destroy_all |
841 | p1 = fast_create(Person) | 841 | p1 = fast_create(Person) |
842 | p2 = fast_create(Person) | 842 | p2 = fast_create(Person) |
843 | p3 = fast_create(Person) | 843 | p3 = fast_create(Person) |
844 | p4 = fast_create(Person) | 844 | p4 = fast_create(Person) |
845 | 845 | ||
846 | - p1.add_friend(p2) | ||
847 | - assert p1.is_a_friend?(p2) | ||
848 | - refute p1.is_a_friend?(p3) | ||
849 | - p1.add_friend(p4) | ||
850 | - assert p1.is_a_friend?(p4) | 846 | + p2.follow(p1) |
847 | + assert p2.follows?(p1) | ||
848 | + refute p3.follows?(p1) | ||
849 | + p4.follow(p1) | ||
850 | + assert p4.follows?(p1) | ||
851 | 851 | ||
852 | action_tracker = fast_create(ActionTracker::Record, :user_id => p1.id) | 852 | action_tracker = fast_create(ActionTracker::Record, :user_id => p1.id) |
853 | ActionTrackerNotification.delete_all | 853 | ActionTrackerNotification.delete_all |
@@ -880,17 +880,17 @@ class PersonTest < ActiveSupport::TestCase | @@ -880,17 +880,17 @@ class PersonTest < ActiveSupport::TestCase | ||
880 | end | 880 | end |
881 | end | 881 | end |
882 | 882 | ||
883 | - should "the tracked action notify friends with one delayed job process" do | 883 | + should "the tracked action notify followers with one delayed job process" do |
884 | p1 = fast_create(Person) | 884 | p1 = fast_create(Person) |
885 | p2 = fast_create(Person) | 885 | p2 = fast_create(Person) |
886 | p3 = fast_create(Person) | 886 | p3 = fast_create(Person) |
887 | p4 = fast_create(Person) | 887 | p4 = fast_create(Person) |
888 | 888 | ||
889 | - p1.add_friend(p2) | ||
890 | - assert p1.is_a_friend?(p2) | ||
891 | - refute p1.is_a_friend?(p3) | ||
892 | - p1.add_friend(p4) | ||
893 | - assert p1.is_a_friend?(p4) | 889 | + p2.follow(p1) |
890 | + assert p2.follows?(p1) | ||
891 | + refute p3.follows?(p1) | ||
892 | + p4.follow(p1) | ||
893 | + assert p4.follows?(p1) | ||
894 | 894 | ||
895 | action_tracker = fast_create(ActionTracker::Record, :user_id => p1.id) | 895 | action_tracker = fast_create(ActionTracker::Record, :user_id => p1.id) |
896 | 896 | ||
@@ -1035,11 +1035,13 @@ class PersonTest < ActiveSupport::TestCase | @@ -1035,11 +1035,13 @@ class PersonTest < ActiveSupport::TestCase | ||
1035 | p2 = create_user('p2').person | 1035 | p2 = create_user('p2').person |
1036 | p3 = create_user('p3').person | 1036 | p3 = create_user('p3').person |
1037 | c = fast_create(Community, :name => "Foo") | 1037 | c = fast_create(Community, :name => "Foo") |
1038 | + | ||
1038 | c.add_member(p1) | 1039 | c.add_member(p1) |
1039 | process_delayed_job_queue | 1040 | process_delayed_job_queue |
1040 | c.add_member(p3) | 1041 | c.add_member(p3) |
1041 | process_delayed_job_queue | 1042 | process_delayed_job_queue |
1042 | - assert_equal 4, ActionTracker::Record.count | 1043 | + |
1044 | + assert_equal 5, ActionTracker::Record.count | ||
1043 | assert_equal 5, ActionTrackerNotification.count | 1045 | assert_equal 5, ActionTrackerNotification.count |
1044 | has_add_member_notification = false | 1046 | has_add_member_notification = false |
1045 | ActionTrackerNotification.all.map do |notification| | 1047 | ActionTrackerNotification.all.map do |notification| |
@@ -0,0 +1,68 @@ | @@ -0,0 +1,68 @@ | ||
1 | +require_relative "../test_helper" | ||
2 | + | ||
3 | +class ProfileFollowersTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'a person follow another' do | ||
6 | + p1 = create_user('person_test').person | ||
7 | + p2 = create_user('person_test_2').person | ||
8 | + | ||
9 | + assert_difference 'ProfileFollower.count' do | ||
10 | + p1.follow(p2) | ||
11 | + end | ||
12 | + | ||
13 | + assert_includes p2.followers(true), p1 | ||
14 | + assert_not_includes p1.followers(true), p2 | ||
15 | + end | ||
16 | + | ||
17 | + should 'a person unfollow another person' do | ||
18 | + p1 = create_user('person_test').person | ||
19 | + p2 = create_user('person_test_2').person | ||
20 | + | ||
21 | + p1.follow(p2) | ||
22 | + | ||
23 | + assert_difference 'ProfileFollower.count', -1 do | ||
24 | + p1.unfollow(p2) | ||
25 | + end | ||
26 | + | ||
27 | + assert_not_includes p2.followers(true), p1 | ||
28 | + end | ||
29 | + | ||
30 | + should 'get the followed persons for a profile' do | ||
31 | + p1 = create_user('person_test').person | ||
32 | + p2 = create_user('person_test_2').person | ||
33 | + p3 = create_user('person_test_3').person | ||
34 | + | ||
35 | + p1.follow(p2) | ||
36 | + p1.follow(p3) | ||
37 | + | ||
38 | + assert_equivalent p1.following_profiles, [p2,p3] | ||
39 | + assert_equivalent Profile.following_profiles(p1), [p2,p3] | ||
40 | + end | ||
41 | + | ||
42 | + should 'not follow same person twice' do | ||
43 | + p1 = create_user('person_test').person | ||
44 | + p2 = create_user('person_test_2').person | ||
45 | + | ||
46 | + assert_difference 'ProfileFollower.count' do | ||
47 | + p1.follow(p2) | ||
48 | + p1.follow(p2) | ||
49 | + end | ||
50 | + | ||
51 | + assert_equivalent p1.following_profiles, [p2] | ||
52 | + assert_equivalent p2.followers, [p1] | ||
53 | + end | ||
54 | + | ||
55 | + should 'show the correct message when a profile is followed by the same person' do | ||
56 | + p1 = create_user('person_test').person | ||
57 | + p2 = create_user('person_test_2').person | ||
58 | + | ||
59 | + p1.follow(p2) | ||
60 | + profile_follower = ProfileFollower.new | ||
61 | + profile_follower.follower = p1 | ||
62 | + profile_follower.profile = p2 | ||
63 | + profile_follower.valid? | ||
64 | + | ||
65 | + assert_includes profile_follower.errors.messages[:profile_id], | ||
66 | + "can't follow the same profile twice" | ||
67 | + end | ||
68 | +end |
test/unit/scrap_test.rb
@@ -125,11 +125,11 @@ class ScrapTest < ActiveSupport::TestCase | @@ -125,11 +125,11 @@ class ScrapTest < ActiveSupport::TestCase | ||
125 | assert_equal c, ta.target | 125 | assert_equal c, ta.target |
126 | end | 126 | end |
127 | 127 | ||
128 | - should "notify leave_scrap action tracker verb to friends and itself" do | 128 | + should "notify leave_scrap action tracker verb to followers and itself" do |
129 | User.current = create_user | 129 | User.current = create_user |
130 | p1 = User.current.person | 130 | p1 = User.current.person |
131 | p2 = create_user.person | 131 | p2 = create_user.person |
132 | - p1.add_friend(p2) | 132 | + p2.add_friend(p1) |
133 | process_delayed_job_queue | 133 | process_delayed_job_queue |
134 | s = Scrap.new | 134 | s = Scrap.new |
135 | s.sender= p1 | 135 | s.sender= p1 |
@@ -180,11 +180,11 @@ class ScrapTest < ActiveSupport::TestCase | @@ -180,11 +180,11 @@ class ScrapTest < ActiveSupport::TestCase | ||
180 | assert_equal p, ta.user | 180 | assert_equal p, ta.user |
181 | end | 181 | end |
182 | 182 | ||
183 | - should "notify leave_scrap_to_self action tracker verb to friends and itself" do | 183 | + should "notify leave_scrap_to_self action tracker verb to followers and itself" do |
184 | User.current = create_user | 184 | User.current = create_user |
185 | p1 = User.current.person | 185 | p1 = User.current.person |
186 | p2 = create_user.person | 186 | p2 = create_user.person |
187 | - p1.add_friend(p2) | 187 | + p2.add_friend(p1) |
188 | ActionTrackerNotification.delete_all | 188 | ActionTrackerNotification.delete_all |
189 | Delayed::Job.delete_all | 189 | Delayed::Job.delete_all |
190 | s = Scrap.new | 190 | s = Scrap.new |