Commit 601cc6bae9f52ea09ac952fee0d14b6492d62e2e

Authored by Gabriel Silva
1 parent e697a141

Follow feature views and controller actions

- Follow and Unfollow profile options
- Followed profiles categorization
- Manage followed profiles page

Signed-off-by: Artur Bersan de Faria <arturbersan@gmail.com>
Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com>
app/controllers/my_profile/followers_controller.rb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +class FollowersController < MyProfileController
  2 +
  3 + def index
  4 + @followed_people = current_person.following_profiles.paginate(:per_page => 5, :page => params[:npage])
  5 + end
  6 +
  7 + def set_category
  8 + if request.method == "GET"
  9 + render :partial => "set_category_modal", :locals => { :followed_profile_id => params[:followed_profile_id] }
  10 + elsif request.method == "POST"
  11 + follower = ProfileFollower.find_by(follower_id: current_person.id, profile_id: params[:followed_profile_id])
  12 + follower.update_attributes(:group => params[:category_name]) if follower
  13 + redirect_to url_for(:controller => "followers", :action => "index")
  14 + end
  15 + end
  16 +end
... ...
app/controllers/public/profile_controller.rb
... ... @@ -3,7 +3,7 @@ class ProfileController &lt; 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 7  
8 8 helper TagsHelper
9 9 helper ActionTrackerHelper
... ... @@ -65,6 +65,10 @@ class ProfileController &lt; PublicController
65 65 end
66 66 end
67 67  
  68 + def following
  69 + @followed_people = [].paginate(:per_page => per_page, :page => params[:npage], :total_entries => profile.friends.count)
  70 + end
  71 +
68 72 def members
69 73 if is_cache_expired?(profile.members_cache_key(params))
70 74 sort = (params[:sort] == 'desc') ? params[:sort] : 'asc'
... ... @@ -151,6 +155,22 @@ class ProfileController &lt; PublicController
151 155 end
152 156 end
153 157  
  158 + def follow
  159 + if !current_person.follows?(profile)
  160 + group = params['follow'] ? params['follow']['category'] : ''
  161 + current_person.follow(profile, group)
  162 + end
  163 + redirect_to profile.url
  164 + end
  165 +
  166 + def unfollow
  167 + if current_person.follows?(profile)
  168 + current_person.unfollow(profile)
  169 + end
  170 + redirect_url = params["redirect_to"] ? params["redirect_to"] : profile.url
  171 + redirect_to redirect_url
  172 + end
  173 +
154 174 def check_friendship
155 175 unless logged_in?
156 176 render :text => ''
... ...
app/models/person.rb
... ... @@ -200,7 +200,7 @@ class Person &lt; Profile
200 200 end
201 201 end
202 202  
203   - def follow(profile, group = nil)
  203 + def follow(profile, group = "")
204 204 unless self.following_profiles.include?(profile)
205 205 profile_follower = ProfileFollower.new
206 206 profile_follower.profile = profile
... ... @@ -601,7 +601,7 @@ class Person &lt; Profile
601 601 protected
602 602  
603 603 def followed_by?(profile)
604   - self == profile || self.is_a_friend?(profile) || self.followers.include(profile)
  604 + self == profile || self.followers.include?(profile)
605 605 end
606 606  
607 607 end
... ...
app/models/profile.rb
... ... @@ -204,7 +204,7 @@ class Profile &lt; ApplicationRecord
204 204 scope :more_recent, -> { order "created_at DESC" }
205 205  
206 206 scope :following_profiles, -> person {
207   - distinct.select('profiles.*').
  207 + distinct.select('profiles.*, profile_followers.group').
208 208 joins('join profile_followers ON profile_followers.profile_id = profiles.id').
209 209 where('profile_followers.follower_id = ?', person.id)
210 210 }
... ...
app/models/profile_follower.rb
1 1 class ProfileFollower < ApplicationRecord
2 2 track_actions :new_follower, :after_create, :keep_params => ["follower.name", "follower.url", "follower.profile_custom_icon"], :custom_user => :profile
  3 + attr_accessible :group
3 4  
4 5 belongs_to :profile, :foreign_key => :profile_id
5 6 belongs_to :follower, :class_name => 'Person', :foreign_key => :follower_id
... ...
app/views/blocks/profile_info_actions/_person.html.erb
... ... @@ -7,6 +7,20 @@
7 7 </li>
8 8 <% end %>
9 9  
  10 + <li>
  11 + <% if user.follows?(profile) %>
  12 + <%= button(:unfollow, content_tag('span', _('Unfollow')), {:profile => profile.identifier, :controller => 'profile', :action => 'unfollow'}) %>
  13 + <% else %>
  14 + <form id="follower-container" action="<%= url_for({:profile => profile.identifier, :controller => 'profile', :action => 'follow'}) %>">
  15 + <div id="category-form" style="display: none;">
  16 + <%= labelled_text_field _("Choose a category: "), "follow[category]" %>
  17 + </div>
  18 + <%= submit_button('follow', _('Follow')) %>
  19 + </form>
  20 + <% end %>
  21 + </li>
  22 +
  23 +
10 24 <% if user.is_a_friend?(profile) && profile.enable_contact? %>
11 25 <li><%= button(:back, _('Send an e-mail'), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}) %></li>
12 26 <% end %>
... ...
app/views/followers/_profile_list.html.erb 0 → 100644
... ... @@ -0,0 +1,18 @@
  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.group %>
  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', :followed_profile_id => profile.id) %>
  15 + </div><!-- end class="controll" -->
  16 + </li>
  17 + <% end %>
  18 +</ul>
... ...
app/views/followers/_set_category_modal.html.erb 0 → 100644
... ... @@ -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>
... ...
app/views/followers/index.html.erb 0 → 100644
... ... @@ -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>
... ...
app/views/profile/following.html.erb 0 → 100644
... ... @@ -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
... ... @@ -26,6 +26,11 @@
26 26  
27 27 <% if profile.person? %>
28 28 <div>
  29 + <!-- TODO: chagen to correct attributes after finishing the backend-->
  30 + <%= labelled_check_box _("Allow other users to follow me"), 'profile_data[can_be_followed]', true, profile.secret, :class => "person-can-be-followed" %>
  31 + </div>
  32 + <br>
  33 + <div>
29 34 <%= labelled_radio_button _('Public &mdash; show my contents to all internet users').html_safe, 'profile_data[public_profile]', true, @profile.public_profile? %>
30 35 </div>
31 36 <div>
... ...
app/views/profile_editor/index.html.erb
... ... @@ -72,6 +72,8 @@
72 72  
73 73 <%= control_panel_button(_('Email Templates'), 'email-templates', :controller => :profile_email_templates) if profile.organization? %>
74 74  
  75 + <%= control_panel_button(_('Manage followed people'), 'manage-followed-people', :controller => :followers) %>
  76 +
75 77 <% @plugins.dispatch(:control_panel_buttons).each do |button| %>
76 78 <%= control_panel_button(button[:title], button[:icon], button[:url], button[:html_options]) %>
77 79 <% end %>
... ...
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
... ...
public/javascripts/followers.js 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +$("#follower-container").live("mouseenter", function() {
  2 + $("#category-form").fadeIn();
  3 +}).live("mouseleave", function() {
  4 + $("#category-form").fadeOut();
  5 +});
... ...
public/stylesheets/blocks/profile-info.scss
... ... @@ -99,3 +99,16 @@
99 99 margin: 0px 0px 5px 0px;
100 100 padding: 2px;
101 101 }
  102 +#follower-container:hover {
  103 + background-color: #eee;
  104 + -o-transition:.5s;
  105 + -ms-transition:.5s;
  106 + -moz-transition:.5s;
  107 + -webkit-transition:.5s;
  108 + transition:.5s;
  109 + padding-top: 5px;
  110 + padding-bottom: 5px;
  111 +}
  112 +#follower-container #category-form {
  113 + margin-bottom: 5px;
  114 +}
... ...
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 }
... ...
test/functional/followers_controller_test.rb 0 → 100644
... ... @@ -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 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
... ... @@ -1932,4 +1932,76 @@ class ProfileControllerTest &lt; ActionController::TestCase
1932 1932 assert_redirected_to :controller => 'account', :action => 'login'
1933 1933 end
1934 1934  
  1935 + should 'follow a user without defining a group' do
  1936 + login_as(@profile.identifier)
  1937 + person = fast_create(Person)
  1938 + get :follow, :profile => person.identifier
  1939 +
  1940 + follower = ProfileFollower.find_by(:profile_id => person.id, :follower_id => @profile.id)
  1941 + assert_not_nil follower
  1942 + end
  1943 +
  1944 + should "not follow user if not logged" do
  1945 + person = fast_create(Person)
  1946 + get :follow, :profile => person.identifier
  1947 +
  1948 + assert_redirected_to :controller => 'account', :action => 'login'
  1949 + end
  1950 +
  1951 + should 'follow a user with a group' do
  1952 + login_as(@profile.identifier)
  1953 + person = fast_create(Person)
  1954 + get :follow, :profile => person.identifier, :follow => { :category => "A Group" }
  1955 +
  1956 + follower = ProfileFollower.find_by(:profile_id => person.id, :follower_id => @profile.id)
  1957 + assert_not_nil follower
  1958 + assert_equal "A Group", follower.group
  1959 + end
  1960 +
  1961 + should 'not follow if current_person already follows the person' do
  1962 + login_as(@profile.identifier)
  1963 + person = fast_create(Person)
  1964 + fast_create(ProfileFollower, :profile_id => person.id, :follower_id => @profile.id)
  1965 +
  1966 + assert_no_difference 'ProfileFollower.count' do
  1967 + get :follow, :profile => person.identifier, :follow => { :category => "A Group" }
  1968 + end
  1969 + end
  1970 +
  1971 + should "not unfollow user if not logged" do
  1972 + person = fast_create(Person)
  1973 + get :unfollow, :profile => person.identifier
  1974 +
  1975 + assert_redirected_to :controller => 'account', :action => 'login'
  1976 + end
  1977 +
  1978 + should "unfollow a followed person" do
  1979 + login_as(@profile.identifier)
  1980 + person = fast_create(Person)
  1981 + follower = fast_create(ProfileFollower, :profile_id => person.id, :follower_id => @profile.id)
  1982 + assert_not_nil follower
  1983 +
  1984 + get :unfollow, :profile => person.identifier
  1985 + follower = ProfileFollower.find_by(:profile_id => person.id, :follower_id => @profile.id)
  1986 + assert_nil follower
  1987 + end
  1988 +
  1989 + should "not unfollow a not followed person" do
  1990 + login_as(@profile.identifier)
  1991 + person = fast_create(Person)
  1992 +
  1993 + assert_no_difference 'ProfileFollower.count' do
  1994 + get :unfollow, :profile => person.identifier
  1995 + end
  1996 + end
  1997 +
  1998 + should "redirect to page after unfollow" do
  1999 + login_as(@profile.identifier)
  2000 + person = fast_create(Person)
  2001 + fast_create(ProfileFollower, :profile_id => person.id, :follower_id => @profile.id)
  2002 +
  2003 + get :unfollow, :profile => person.identifier, :redirect_to => "/some/url"
  2004 + assert_redirected_to "/some/url"
  2005 + end
  2006 +
1935 2007 end
... ...