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 @@ |
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 @@ |
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 | 128 | end |
129 | 129 | |
130 | 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 | 132 | render_access_denied |
133 | - else #!profile.public? | |
133 | + else | |
134 | 134 | private_profile_partial_parameters |
135 | 135 | render :template => 'profile/_private_profile', :status => 403, :formats => [:html] |
136 | 136 | end | ... | ... |
app/controllers/public/profile_controller.rb
... | ... | @@ -3,7 +3,8 @@ class ProfileController < PublicController |
3 | 3 | needs_profile |
4 | 4 | before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] |
5 | 5 | before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse, :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 | 9 | helper TagsHelper |
9 | 10 | helper ActionTrackerHelper |
... | ... | @@ -65,6 +66,10 @@ class ProfileController < PublicController |
65 | 66 | end |
66 | 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 | 73 | def members |
69 | 74 | if is_cache_expired?(profile.members_cache_key(params)) |
70 | 75 | sort = (params[:sort] == 'desc') ? params[:sort] : 'asc' |
... | ... | @@ -151,6 +156,26 @@ class ProfileController < PublicController |
151 | 156 | end |
152 | 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 | 179 | def check_friendship |
155 | 180 | unless logged_in? |
156 | 181 | render :text => '' |
... | ... | @@ -437,4 +462,8 @@ class ProfileController < PublicController |
437 | 462 | [:image, :domains, :preferred_domain, :environment] |
438 | 463 | end |
439 | 464 | |
465 | + def allow_following? | |
466 | + render_not_found unless profile.allow_following? | |
467 | + end | |
468 | + | |
440 | 469 | end | ... | ... |
app/helpers/action_tracker_helper.rb
... | ... | @@ -14,13 +14,23 @@ module ActionTrackerHelper |
14 | 14 | } |
15 | 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 | 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 | 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 | 31 | link = link_to image_tag(ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png")), |
22 | 32 | ta.get_resource_url[i], title: n |
23 | - end.join.html_safe | |
33 | + end) | |
24 | 34 | } |
25 | 35 | end |
26 | 36 | |
... | ... | @@ -68,9 +78,9 @@ module ActionTrackerHelper |
68 | 78 | end |
69 | 79 | |
70 | 80 | def favorite_enterprise_description ta |
71 | - _('favorited enterprise %{title}') % { | |
81 | + (_('favorited enterprise %{title}') % { | |
72 | 82 | title: link_to(truncate(ta.get_enterprise_name), ta.get_enterprise_url), |
73 | - } | |
83 | + }).html_safe | |
74 | 84 | end |
75 | 85 | |
76 | 86 | end | ... | ... |
app/jobs/notify_activity_to_profiles_job.rb
... | ... | @@ -19,8 +19,9 @@ class NotifyActivityToProfilesJob < Struct.new(:tracked_action_id) |
19 | 19 | # Notify the user |
20 | 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 | 26 | if tracked_action.user.is_a? Organization |
26 | 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 | 22 | self.roles = [Profile::Roles.member(organization.environment.id).id] |
23 | 23 | end |
24 | 24 | target.affiliate(requestor, self.roles.select{|r| !r.to_i.zero? }.map{|i| Role.find(i)}) |
25 | + person.follow(organization, _('memberships')) | |
25 | 26 | end |
26 | 27 | |
27 | 28 | def title | ... | ... |
app/models/article.rb
... | ... | @@ -534,13 +534,13 @@ class Article < ApplicationRecord |
534 | 534 | |
535 | 535 | scope :display_filter, lambda {|user, profile| |
536 | 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 | 538 | where( |
539 | 539 | [ |
540 | 540 | "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ? |
541 | 541 | OR (show_to_followers = ? AND ? AND profile_id IN (?))", true, user.id, user.id, |
542 | 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 | 88 | end |
89 | 89 | |
90 | 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 | 92 | end |
93 | 93 | |
94 | 94 | def display_always(context) | ... | ... |
app/models/enterprise.rb
app/models/favorite_enterprise_person.rb
app/models/friendship.rb
... | ... | @@ -9,11 +9,13 @@ class Friendship < ApplicationRecord |
9 | 9 | after_create do |friendship| |
10 | 10 | Friendship.update_cache_counter(:friends_count, friendship.person, 1) |
11 | 11 | Friendship.update_cache_counter(:friends_count, friendship.friend, 1) |
12 | + friendship.person.follow(friendship.friend, friendship.group) | |
12 | 13 | end |
13 | 14 | |
14 | 15 | after_destroy do |friendship| |
15 | 16 | Friendship.update_cache_counter(:friends_count, friendship.person, -1) |
16 | 17 | Friendship.update_cache_counter(:friends_count, friendship.friend, -1) |
18 | + friendship.person.unfollow(friendship.friend) | |
17 | 19 | end |
18 | 20 | |
19 | 21 | def self.remove_friendship(person1, person2) | ... | ... |
app/models/person.rb
... | ... | @@ -8,7 +8,6 @@ class Person < Profile |
8 | 8 | :display => %w[compact] |
9 | 9 | } |
10 | 10 | |
11 | - | |
12 | 11 | def self.type_name |
13 | 12 | _('Person') |
14 | 13 | end |
... | ... | @@ -93,6 +92,7 @@ class Person < Profile |
93 | 92 | has_many :following_articles, :class_name => 'Article', :through => :article_followers, :source => :article |
94 | 93 | has_many :friendships, :dependent => :destroy |
95 | 94 | has_many :friends, :class_name => 'Person', :through => :friendships |
95 | + has_many :follow_categories | |
96 | 96 | |
97 | 97 | scope :online, -> { |
98 | 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 | 200 | end |
201 | 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 | 214 | def already_request_friendship?(person) |
204 | 215 | person.tasks.where(requestor_id: self.id, type: 'AddFriend', status: Task::Status::ACTIVE).first |
205 | 216 | end |
... | ... | @@ -208,6 +219,11 @@ class Person < Profile |
208 | 219 | Friendship.where(friend_id: friend, person_id: id).first.destroy |
209 | 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 | 227 | FIELDS = %w[ |
212 | 228 | description |
213 | 229 | image |
... | ... | @@ -580,9 +596,12 @@ class Person < Profile |
580 | 596 | person.has_permission?(:manage_friends, self) |
581 | 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 | 605 | end |
606 | + | |
588 | 607 | end | ... | ... |
app/models/profile.rb
... | ... | @@ -5,7 +5,7 @@ class Profile < ApplicationRecord |
5 | 5 | |
6 | 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 | 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 | 10 | # use for internationalizable human type names in search facets |
11 | 11 | # reimplement on subclasses |
... | ... | @@ -203,6 +203,16 @@ class Profile < ApplicationRecord |
203 | 203 | scope :more_active, -> { order 'activities_count DESC' } |
204 | 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 | 216 | acts_as_trackable :dependent => :destroy |
207 | 217 | |
208 | 218 | has_many :profile_activities |
... | ... | @@ -215,6 +225,9 @@ class Profile < ApplicationRecord |
215 | 225 | |
216 | 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 | 231 | # Although this should be a has_one relation, there are no non-silly names for |
219 | 232 | # a foreign key on article to reference the template to which it is |
220 | 233 | # welcome_page... =P |
... | ... | @@ -764,6 +777,7 @@ private :generate_url, :url_options |
764 | 777 | else |
765 | 778 | self.affiliate(person, Profile::Roles.admin(environment.id), attributes) if members.count == 0 |
766 | 779 | self.affiliate(person, Profile::Roles.member(environment.id), attributes) |
780 | + person.follow(self, _('memberships')) | |
767 | 781 | end |
768 | 782 | person.tasks.pending.of("InviteMember").select { |t| t.data[:community_id] == self.id }.each { |invite| invite.cancel } |
769 | 783 | remove_from_suggestion_list person |
... | ... | @@ -1107,7 +1121,11 @@ private :generate_url, :url_options |
1107 | 1121 | end |
1108 | 1122 | |
1109 | 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 | 1129 | end |
1112 | 1130 | |
1113 | 1131 | def display_private_info_to?(user) | ... | ... |
... | ... | @@ -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 | 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 | 13 | <%= render_environment_features(:profile_actions) %> | ... | ... |
app/views/blocks/profile_info_actions/_follow_categories.html.erb
0 → 100644
... | ... | @@ -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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
1 | +<%= render :partial => 'default_activity', :locals => { :activity => activity } %> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => 'default_activity', :locals => { :activity => activity, :tab_action => tab_action } %> | ... | ... |
... | ... | @@ -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 | 23 | </div> |
24 | 24 | |
25 | 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 | 29 | <% if profile.person? %> |
30 | + <br> | |
28 | 31 | <div> |
29 | 32 | <%= labelled_radio_button _('Public — show my contents to all internet users').html_safe, 'profile_data[public_profile]', true, @profile.public_profile? %> |
30 | 33 | </div> | ... | ... |
app/views/profile_editor/index.html.erb
... | ... | @@ -72,6 +72,12 @@ |
72 | 72 | |
73 | 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 | 81 | <% @plugins.dispatch(:control_panel_buttons).each do |button| %> |
76 | 82 | <%= control_panel_button(button[:title], button[:icon], button[:url], button[:html_options]) %> |
77 | 83 | <% end %> | ... | ... |
config/initializers/action_tracker.rb
db/migrate/20160608123748_create_profile_followers_table.rb
0 → 100644
... | ... | @@ -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 @@ |
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 @@ |
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
public/javascripts/application.js
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 | *= require pagination.js |
27 | 27 | * views speficics |
28 | 28 | *= require add-and-join.js |
29 | +*= require followers.js | |
29 | 30 | *= require report-abuse.js |
30 | 31 | *= require autogrow.js |
31 | 32 | *= require require_login.js |
... | ... | @@ -550,6 +551,11 @@ function loading_for_button(selector) { |
550 | 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 | 559 | function new_qualifier_row(selector, select_qualifiers, delete_button) { |
554 | 560 | index = jQuery(selector + ' tr').size() - 1; |
555 | 561 | jQuery(selector).append("<tr><td>" + select_qualifiers + "</td><td id='certifier-area-" + index + "'><select></select>" + delete_button + "</td></tr>"); | ... | ... |
... | ... | @@ -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 | 99 | margin: 0px 0px 5px 0px; |
100 | 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 | 167 | |
168 | 168 | #profile-wall li.profile-activity-item.join_community .profile-activity-text a img, |
169 | 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 | 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 | 173 | #profile-network li.profile-activity-item.new_friendship .profile-activity-text a img { |
172 | 174 | margin: 5px 5px 0 0; |
173 | 175 | padding: 1px; | ... | ... |
public/stylesheets/profile-list.scss
... | ... | @@ -23,6 +23,7 @@ |
23 | 23 | } |
24 | 24 | .controller-favorite_enterprises .profile-list a.profile-link, |
25 | 25 | .controller-friends .profile-list a.profile-link, |
26 | +.controller-followers .profile-list a.profile-link, | |
26 | 27 | .list-profile-connections .profile-list a.profile-link, |
27 | 28 | .profiles-suggestions .profile-list a.profile-link { |
28 | 29 | text-decoration: none; |
... | ... | @@ -32,11 +33,13 @@ |
32 | 33 | } |
33 | 34 | .controller-favorite_enterprises .profile-list a.profile-link:hover, |
34 | 35 | .controller-friends .profile-list a.profile-link:hover, |
36 | +.controller-followers .profile-list a.profile-link:hover, | |
35 | 37 | .profiles-suggestions .profile-list a.profile-link:hover { |
36 | 38 | color: #FFF; |
37 | 39 | } |
38 | 40 | .controller-favorite_enterprises .profile-list .profile_link span, |
39 | 41 | .controller-friends .profile-list .profile_link span, |
42 | +.controller-followers .profile-list .profile_link span, | |
40 | 43 | .box-1 .profiles-suggestions .profile-list .profile_link span { |
41 | 44 | width: 80px; |
42 | 45 | display: block; |
... | ... | @@ -44,12 +47,14 @@ |
44 | 47 | } |
45 | 48 | .controller-favorite_enterprises .profile-list, |
46 | 49 | .controller-friends .profile-list, |
50 | +.controller-followers .profile-list, | |
47 | 51 | .profiles-suggestions .profile-list { |
48 | 52 | position: relative; |
49 | 53 | } |
50 | 54 | |
51 | 55 | .controller-favorite_enterprises .profile-list .controll, |
52 | 56 | .controller-friends .profile-list .controll, |
57 | +.controller-followers .profile-list .controll, | |
53 | 58 | .profiles-suggestions .profile-list .controll { |
54 | 59 | position: absolute; |
55 | 60 | top: 7px; |
... | ... | @@ -57,17 +62,20 @@ |
57 | 62 | } |
58 | 63 | .controller-favorite_enterprises .profile-list .controll a, |
59 | 64 | .controller-friends .profile-list .controll a, |
65 | +.controller-followers .profile-list .controll a, | |
60 | 66 | .profiles-suggestions .profile-list .controll a { |
61 | 67 | display: block; |
62 | 68 | margin-bottom: 2px; |
63 | 69 | } |
64 | 70 | .controller-favorite_enterprises .msie6 .profile-list .controll a, |
65 | 71 | .controller-friends .msie6 .profile-list .controll a, |
72 | +.controller-folloed_people .msie6 .profile-list .controll a, | |
66 | 73 | .profiles-suggestions .msie6 .profile-list .controll a { |
67 | 74 | width: 0px; |
68 | 75 | } |
69 | 76 | .controller-favorite_enterprises .button-bar, |
70 | 77 | .controller-friends .button-bar, |
78 | +.controller-followers .button-bar, | |
71 | 79 | .profiles-suggestions .button-bar { |
72 | 80 | clear: both; |
73 | 81 | padding-top: 20px; |
... | ... | @@ -208,22 +216,35 @@ |
208 | 216 | font-size: 12px; |
209 | 217 | } |
210 | 218 | .action-profile-members .profile_link{ |
211 | - position: relative; | |
219 | + position: relative; | |
212 | 220 | } |
213 | 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 | 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 @@ |
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 @@ |
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 | 771 | assert_equal 15, assigns(:activities).size |
772 | 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 | 775 | p2 = create_user.person |
776 | - refute profile.is_a_friend?(p2) | |
776 | + refute profile.follows?(p2) | |
777 | 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 | 781 | ActionTracker::Record.destroy_all |
781 | 782 | |
782 | 783 | scrap1 = create(Scrap, defaults_for_scrap(:sender => p2, :receiver => p3)) |
... | ... | @@ -964,7 +965,9 @@ class ProfileControllerTest < ActionController::TestCase |
964 | 965 | should 'have activities defined if logged in and is following profile' do |
965 | 966 | login_as(profile.identifier) |
966 | 967 | p1= fast_create(Person) |
967 | - p1.add_friend(profile) | |
968 | + | |
969 | + profile.follow(p1) | |
970 | + | |
968 | 971 | ActionTracker::Record.destroy_all |
969 | 972 | get :index, :profile => p1.identifier |
970 | 973 | assert_equal [], assigns(:activities) |
... | ... | @@ -1932,4 +1935,77 @@ class ProfileControllerTest < ActionController::TestCase |
1932 | 1935 | assert_redirected_to :controller => 'account', :action => 'login' |
1933 | 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 | 2011 | end | ... | ... |
test/unit/article_test.rb
... | ... | @@ -1099,9 +1099,9 @@ class ArticleTest < ActiveSupport::TestCase |
1099 | 1099 | assert_equal 3, ActionTrackerNotification.where(action_tracker_id: second_activity.id).count |
1100 | 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 | 1103 | friend = fast_create(Person) |
1104 | - profile.add_friend(friend) | |
1104 | + friend.follow(profile) | |
1105 | 1105 | Article.destroy_all |
1106 | 1106 | ActionTracker::Record.destroy_all |
1107 | 1107 | ActionTrackerNotification.destroy_all |
... | ... | @@ -1112,9 +1112,9 @@ class ArticleTest < ActiveSupport::TestCase |
1112 | 1112 | assert_equal friend, ActionTrackerNotification.last.profile |
1113 | 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 | 1116 | f1 = fast_create(Person) |
1117 | - profile.add_friend(f1) | |
1117 | + f1.follow(profile) | |
1118 | 1118 | |
1119 | 1119 | User.current = profile.user |
1120 | 1120 | article = create TinyMceArticle, :name => 'Tracked Article 1', :profile_id => profile.id |
... | ... | @@ -1123,16 +1123,17 @@ class ArticleTest < ActiveSupport::TestCase |
1123 | 1123 | assert_equal 2, ActionTrackerNotification.where(action_tracker_id: article.activity.id).count |
1124 | 1124 | |
1125 | 1125 | f2 = fast_create(Person) |
1126 | - profile.add_friend(f2) | |
1126 | + f2.follow(profile) | |
1127 | + | |
1127 | 1128 | article2 = create TinyMceArticle, :name => 'Tracked Article 2', :profile_id => profile.id |
1128 | 1129 | assert_equal 2, ActionTracker::Record.where(verb: 'create_article').count |
1129 | 1130 | process_delayed_job_queue |
1130 | 1131 | assert_equal 3, ActionTrackerNotification.where(action_tracker_id: article2.activity.id).count |
1131 | 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 | 1135 | friend = fast_create(Person) |
1135 | - profile.add_friend(friend) | |
1136 | + friend.follow(profile) | |
1136 | 1137 | Article.destroy_all |
1137 | 1138 | ActionTracker::Record.destroy_all |
1138 | 1139 | ActionTrackerNotification.destroy_all | ... | ... |
test/unit/friendship_test.rb
... | ... | @@ -28,14 +28,14 @@ class FriendshipTest < ActiveSupport::TestCase |
28 | 28 | f.person = a |
29 | 29 | f.friend = b |
30 | 30 | f.save! |
31 | - ta = ActionTracker::Record.last | |
31 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last | |
32 | 32 | assert_equal a, ta.user |
33 | 33 | assert_equal 'b', ta.get_friend_name[0] |
34 | 34 | f = Friendship.new |
35 | 35 | f.person = a |
36 | 36 | f.friend = c |
37 | 37 | f.save! |
38 | - ta = ActionTracker::Record.last | |
38 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last | |
39 | 39 | assert_equal a, ta.user |
40 | 40 | assert_equal 'c', ta.get_friend_name[1] |
41 | 41 | end |
... | ... | @@ -46,14 +46,14 @@ class FriendshipTest < ActiveSupport::TestCase |
46 | 46 | f.person = a |
47 | 47 | f.friend = b |
48 | 48 | f.save! |
49 | - ta = ActionTracker::Record.last | |
49 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last | |
50 | 50 | assert_equal a, ta.user |
51 | 51 | assert_equal ['b'], ta.get_friend_name |
52 | 52 | f = Friendship.new |
53 | 53 | f.person = b |
54 | 54 | f.friend = a |
55 | 55 | f.save! |
56 | - ta = ActionTracker::Record.last | |
56 | + ta = ActionTracker::Record.where(:target_type => "Friendship").last | |
57 | 57 | assert_equal b, ta.user |
58 | 58 | assert_equal ['a'], ta.get_friend_name |
59 | 59 | end |
... | ... | @@ -72,4 +72,53 @@ class FriendshipTest < ActiveSupport::TestCase |
72 | 72 | assert_not_includes p2.friends(true), p1 |
73 | 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 | 124 | end | ... | ... |
test/unit/notify_activity_to_profiles_job_test.rb
... | ... | @@ -24,15 +24,15 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase |
24 | 24 | end |
25 | 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 | 28 | person = fast_create(Person) |
29 | 29 | community = fast_create(Community) |
30 | 30 | action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :verb => 'create_article') |
31 | 31 | refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb) |
32 | 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 | 36 | fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id) |
37 | 37 | ActionTrackerNotification.delete_all |
38 | 38 | job = NotifyActivityToProfilesJob.new(action_tracker.id) |
... | ... | @@ -66,23 +66,21 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase |
66 | 66 | end |
67 | 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 | 70 | person = fast_create(Person) |
71 | 71 | community = fast_create(Community) |
72 | 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 | 73 | refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb) |
74 | 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 | 76 | fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id) |
78 | 77 | fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id) |
79 | 78 | ActionTrackerNotification.delete_all |
80 | 79 | job = NotifyActivityToProfilesJob.new(action_tracker.id) |
81 | 80 | job.perform |
82 | 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 | 84 | notification = ActionTrackerNotification.find_by profile_id: profile.id |
87 | 85 | assert_equal action_tracker, notification.action_tracker |
88 | 86 | end |
... | ... | @@ -119,8 +117,8 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase |
119 | 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 | 118 | refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb) |
121 | 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 | 122 | fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id) |
125 | 123 | fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id) |
126 | 124 | ActionTrackerNotification.delete_all | ... | ... |
test/unit/person_notifier_test.rb
... | ... | @@ -178,6 +178,7 @@ class PersonNotifierTest < ActiveSupport::TestCase |
178 | 178 | update_product: -> { create Product, profile: @profile, product_category: create(ProductCategory, environment: Environment.default) }, |
179 | 179 | remove_product: -> { create Product, profile: @profile, product_category: create(ProductCategory, environment: Environment.default) }, |
180 | 180 | favorite_enterprise: -> { create FavoriteEnterprisePerson, enterprise: create(Enterprise), person: @member }, |
181 | + new_follower: -> { @member } | |
181 | 182 | } |
182 | 183 | |
183 | 184 | ActionTrackerConfig.verb_names.each do |verb| |
... | ... | @@ -197,6 +198,7 @@ class PersonNotifierTest < ActiveSupport::TestCase |
197 | 198 | 'friend_url' => '/', 'friend_profile_custom_icon' => [], 'friend_name' => ['joe'], |
198 | 199 | 'resource_name' => ['resource'], 'resource_profile_custom_icon' => [], 'resource_url' => ['/'], |
199 | 200 | 'enterprise_name' => 'coop', 'enterprise_url' => '/coop', |
201 | + 'follower_url' => '/', 'follower_profile_custom_icon' => [], 'follower_name' => ['joe'], | |
200 | 202 | 'view_url'=> ['/'], 'thumbnail_path' => ['1'], |
201 | 203 | } |
202 | 204 | a.get_url = '' | ... | ... |
test/unit/person_test.rb
... | ... | @@ -728,7 +728,7 @@ class PersonTest < ActiveSupport::TestCase |
728 | 728 | assert_equal [s4], p2.scraps_received.not_replies |
729 | 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 | 732 | p1 = fast_create(Person) |
733 | 733 | p2 = fast_create(Person) |
734 | 734 | p3 = fast_create(Person) |
... | ... | @@ -740,9 +740,9 @@ class PersonTest < ActiveSupport::TestCase |
740 | 740 | assert p1.is_a_friend?(p4) |
741 | 741 | |
742 | 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 | 746 | end |
747 | 747 | |
748 | 748 | should "the person follows her friends and herself by default" do |
... | ... | @@ -757,9 +757,9 @@ class PersonTest < ActiveSupport::TestCase |
757 | 757 | assert p4.is_a_friend?(p1) |
758 | 758 | |
759 | 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 | 763 | end |
764 | 764 | |
765 | 765 | should "a person member of a community follows the community" do |
... | ... | @@ -836,18 +836,18 @@ class PersonTest < ActiveSupport::TestCase |
836 | 836 | assert_nil Scrap.find_by(id: scrap.id) |
837 | 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 | 840 | Person.destroy_all |
841 | 841 | p1 = fast_create(Person) |
842 | 842 | p2 = fast_create(Person) |
843 | 843 | p3 = fast_create(Person) |
844 | 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 | 852 | action_tracker = fast_create(ActionTracker::Record, :user_id => p1.id) |
853 | 853 | ActionTrackerNotification.delete_all |
... | ... | @@ -880,17 +880,17 @@ class PersonTest < ActiveSupport::TestCase |
880 | 880 | end |
881 | 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 | 884 | p1 = fast_create(Person) |
885 | 885 | p2 = fast_create(Person) |
886 | 886 | p3 = fast_create(Person) |
887 | 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 | 895 | action_tracker = fast_create(ActionTracker::Record, :user_id => p1.id) |
896 | 896 | |
... | ... | @@ -1035,11 +1035,13 @@ class PersonTest < ActiveSupport::TestCase |
1035 | 1035 | p2 = create_user('p2').person |
1036 | 1036 | p3 = create_user('p3').person |
1037 | 1037 | c = fast_create(Community, :name => "Foo") |
1038 | + | |
1038 | 1039 | c.add_member(p1) |
1039 | 1040 | process_delayed_job_queue |
1040 | 1041 | c.add_member(p3) |
1041 | 1042 | process_delayed_job_queue |
1042 | - assert_equal 4, ActionTracker::Record.count | |
1043 | + | |
1044 | + assert_equal 5, ActionTracker::Record.count | |
1043 | 1045 | assert_equal 5, ActionTrackerNotification.count |
1044 | 1046 | has_add_member_notification = false |
1045 | 1047 | ActionTrackerNotification.all.map do |notification| | ... | ... |
... | ... | @@ -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 | 125 | assert_equal c, ta.target |
126 | 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 | 129 | User.current = create_user |
130 | 130 | p1 = User.current.person |
131 | 131 | p2 = create_user.person |
132 | - p1.add_friend(p2) | |
132 | + p2.add_friend(p1) | |
133 | 133 | process_delayed_job_queue |
134 | 134 | s = Scrap.new |
135 | 135 | s.sender= p1 |
... | ... | @@ -180,11 +180,11 @@ class ScrapTest < ActiveSupport::TestCase |
180 | 180 | assert_equal p, ta.user |
181 | 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 | 184 | User.current = create_user |
185 | 185 | p1 = User.current.person |
186 | 186 | p2 = create_user.person |
187 | - p1.add_friend(p2) | |
187 | + p2.add_friend(p1) | |
188 | 188 | ActionTrackerNotification.delete_all |
189 | 189 | Delayed::Job.delete_all |
190 | 190 | s = Scrap.new | ... | ... |