Commit ad29f61a1c2b2cbba9c6be601d5a3533c71fc472
1 parent
495f736d
Exists in
master
and in
29 other branches
[suggestions] Displays categories in common
(ActionItem3234)
Showing
15 changed files
with
176 additions
and
62 deletions
Show diff stats
app/controllers/my_profile/friends_controller.rb
... | ... | @@ -3,7 +3,7 @@ class FriendsController < MyProfileController |
3 | 3 | protect 'manage_friends', :profile |
4 | 4 | |
5 | 5 | def index |
6 | - @suggestions = profile.suggested_people.limit(per_page/2) | |
6 | + @suggestions = profile.profile_suggestions.of_person.includes(:suggestion).limit(per_page) | |
7 | 7 | if is_cache_expired?(profile.manage_friends_cache_key(params)) |
8 | 8 | @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage]) |
9 | 9 | end |
... | ... | @@ -18,17 +18,15 @@ class FriendsController < MyProfileController |
18 | 18 | end |
19 | 19 | |
20 | 20 | def suggest |
21 | - @suggestions = profile.suggested_people.paginate(:per_page => per_page, :page => params[:npage]) | |
21 | + @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | |
22 | 22 | end |
23 | 23 | |
24 | 24 | def remove_suggestion |
25 | 25 | @person = profile.suggested_people.find_by_identifier(params[:id]) |
26 | 26 | redirect_to :action => 'suggest' unless @person |
27 | 27 | if @person && request.post? |
28 | - suggestion = profile.profile_suggestions.find_by_suggestion_id @person.id | |
29 | - suggestion.disable | |
28 | + profile.remove_suggestion(@person) | |
30 | 29 | session[:notice] = _('Suggestion removed') |
31 | - redirect_to :action => 'suggest' | |
32 | 30 | end |
33 | 31 | end |
34 | 32 | ... | ... |
app/controllers/my_profile/memberships_controller.rb
... | ... | @@ -40,7 +40,7 @@ class MembershipsController < MyProfileController |
40 | 40 | end |
41 | 41 | |
42 | 42 | def suggest |
43 | - @suggestions = profile.suggested_communities.paginate(:per_page => 8, :page => params[:npage]) | |
43 | + @suggestions = profile.profile_suggestions.of_community.includes(:suggestion).limit(per_page) | |
44 | 44 | end |
45 | 45 | |
46 | 46 | def remove_suggestion |
... | ... | @@ -53,4 +53,10 @@ class MembershipsController < MyProfileController |
53 | 53 | end |
54 | 54 | end |
55 | 55 | |
56 | + protected | |
57 | + | |
58 | + def per_page | |
59 | + 10 | |
60 | + end | |
61 | + | |
56 | 62 | end | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -1419,4 +1419,9 @@ module ApplicationHelper |
1419 | 1419 | text_field_tag name, default, options.merge({:id => 'search-input', 'data-asset' => asset}) |
1420 | 1420 | end |
1421 | 1421 | |
1422 | + def profile_suggestion_categories(suggestion) | |
1423 | + suggestion.categories.map do |cat| | |
1424 | + content_tag(:p, content_tag(:span, "#{suggestion.category_label(cat[0])}: #{cat[1]}", :class => suggestion.category_icon(cat[0]))) | |
1425 | + end.join | |
1426 | + end | |
1422 | 1427 | end | ... | ... |
app/mailers/user_mailer.rb
... | ... | @@ -54,7 +54,7 @@ class UserMailer < ActionMailer::Base |
54 | 54 | content_type: 'text/html', |
55 | 55 | to: user.email, |
56 | 56 | from: "#{user.environment.name} <#{user.environment.contact_email}>", |
57 | - subject: _("[%s] We have suggestions for your network") % user.environment.name | |
57 | + subject: _("[%s] What about grow up your network?") % user.environment.name | |
58 | 58 | ) |
59 | 59 | end |
60 | 60 | ... | ... |
app/models/person.rb
... | ... | @@ -66,7 +66,7 @@ class Person < Profile |
66 | 66 | has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people' |
67 | 67 | has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions' |
68 | 68 | |
69 | - has_many :profile_suggestions, :foreign_key => :person_id, :dependent => :destroy | |
69 | + has_many :profile_suggestions, :foreign_key => :person_id, :order => 'id ASC', :dependent => :destroy | |
70 | 70 | has_many :suggested_people, :through => :profile_suggestions, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Person', true] |
71 | 71 | has_many :suggested_communities, :through => :profile_suggestions, :source => :suggestion, :conditions => ['profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Community', true] |
72 | 72 | |
... | ... | @@ -498,6 +498,11 @@ class Person < Profile |
498 | 498 | person.notifier.reschedule_next_notification_mail |
499 | 499 | end |
500 | 500 | |
501 | + def remove_suggestion(profile) | |
502 | + suggestion = profile_suggestions.find_by_suggestion_id profile.id | |
503 | + suggestion.disable if suggestion | |
504 | + end | |
505 | + | |
501 | 506 | protected |
502 | 507 | |
503 | 508 | def followed_by?(profile) | ... | ... |
app/models/profile_suggestion.rb
... | ... | @@ -2,7 +2,7 @@ class ProfileSuggestion < ActiveRecord::Base |
2 | 2 | belongs_to :person |
3 | 3 | belongs_to :suggestion, :class_name => 'Profile', :foreign_key => :suggestion_id |
4 | 4 | |
5 | - attr_accessible :person, :suggestion, :suggestion_type, :categories, :similarity, :enabled | |
5 | + attr_accessible :person, :suggestion, :suggestion_type, :categories, :enabled | |
6 | 6 | |
7 | 7 | before_create do |profile_suggestion| |
8 | 8 | profile_suggestion.suggestion_type = self.suggestion.class.to_s |
... | ... | @@ -18,11 +18,15 @@ class ProfileSuggestion < ActiveRecord::Base |
18 | 18 | end |
19 | 19 | |
20 | 20 | validates_uniqueness_of :suggestion_id, :scope => [ :person_id ] |
21 | + scope :of_person, :conditions => { :suggestion_type => 'Person' } | |
22 | + scope :of_community, :conditions => { :suggestion_type => 'Community' } | |
23 | + scope :enabled, :conditions => { :enabled => true } | |
21 | 24 | |
25 | + # {:category_type => ['category-icon', 'category-label']} | |
22 | 26 | CATEGORIES = { |
23 | - :common_friends => _('Friends in common'), | |
24 | - :common_communities => _('Communities in common'), | |
25 | - :common_tags => _('Tags in common') | |
27 | + :common_friends => ['menu-people', _('Friends in common')], | |
28 | + :common_communities => ['menu-community',_('Communities in common')], | |
29 | + :common_tags => ['edit', _('Tags in common')] | |
26 | 30 | } |
27 | 31 | |
28 | 32 | CATEGORIES.keys.each do |category| |
... | ... | @@ -30,6 +34,14 @@ class ProfileSuggestion < ActiveRecord::Base |
30 | 34 | attr_accessible category.to_sym |
31 | 35 | end |
32 | 36 | |
37 | + def category_icon(category) | |
38 | + 'icon-' + ProfileSuggestion::CATEGORIES[category][0] | |
39 | + end | |
40 | + | |
41 | + def category_label(category) | |
42 | + ProfileSuggestion::CATEGORIES[category][1] | |
43 | + end | |
44 | + | |
33 | 45 | RULES = %w[ |
34 | 46 | friends_of_friends |
35 | 47 | people_with_common_communities | ... | ... |
... | ... | @@ -0,0 +1,16 @@ |
1 | +<ul class="profile-list"> | |
2 | + <% profiles.each do |profile| %> | |
3 | + <li> | |
4 | + <%= link_to_profile profile_image(profile) + '<br/>' + profile.short_name, | |
5 | + profile.identifier, :class => 'profile-link' %> | |
6 | + <div class="controll"> | |
7 | + <%= button_without_text :remove, content_tag('span',_('remove')), | |
8 | + { :action => 'remove', :id => profile.id }, | |
9 | + :title => _('remove') %> | |
10 | + <%= button_without_text 'menu-mail', content_tag('span',_('contact')), | |
11 | + profile.url.merge(:controller => 'contact', :action => 'new', :profile => profile.identifier), | |
12 | + :title => _('contact') %> | |
13 | + </div><!-- end class="controll" --> | |
14 | + </li> | |
15 | + <% end %> | |
16 | +</ul> | ... | ... |
app/views/friends/index.html.erb
... | ... | @@ -20,22 +20,23 @@ |
20 | 20 | <% end %> |
21 | 21 | <% end %> |
22 | 22 | |
23 | - <%= render :partial => 'shared/profile_list', :locals => { :profiles => @friends, :collection => :friends } %> | |
24 | - <div id='pagination-friends'> | |
25 | - <%= pagination_links @friends, :param_name => 'npage' %> | |
26 | - </div> | |
23 | + <%= render :partial => 'profile_list', :locals => { :profiles => @friends } %> | |
27 | 24 | |
25 | + <br style="clear:both" /> | |
26 | + <%= pagination_links @friends, :param_name => 'npage' %> | |
28 | 27 | <% end %> |
29 | 28 | |
30 | 29 | <% unless @suggestions.empty? %> |
31 | 30 | <br style="clear:both" /> |
32 | - <h2><%= _("Friends suggestions") %></h2> | |
31 | + <div class="profiles-suggestions"> | |
32 | + <h2><%= _("Friends suggestions") %></h2> | |
33 | 33 | |
34 | - <%= render :partial => 'shared/profile_list', :locals => { :profiles => @suggestions, :collection => :friends_suggestions } %> | |
34 | + <%= render :partial => 'shared/profile_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions } %> | |
35 | 35 | |
36 | - <% button_bar do %> | |
37 | - <%= link_to _('See more suggestions...'), :action => 'suggest' %> | |
38 | - <% end %> | |
36 | + <% button_bar do %> | |
37 | + <%= link_to _('See more suggestions...'), :action => 'suggest' %> | |
38 | + <% end %> | |
39 | + </div> | |
39 | 40 | <% end %> |
40 | 41 | |
41 | 42 | </div><!-- end id="manage_friends" --> | ... | ... |
app/views/friends/suggest.html.erb
... | ... | @@ -13,9 +13,7 @@ |
13 | 13 | </em> |
14 | 14 | </p> |
15 | 15 | <% else %> |
16 | - <%= render :partial => 'shared/profile_list', :locals => { :profiles => @suggestions, :collection => :friends_suggestions } %> | |
17 | - | |
18 | - <%= pagination_links @suggestions, :param_name => 'npage' %> | |
16 | + <%= render :partial => 'shared/profile_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions } %> | |
19 | 17 | <% end %> |
20 | 18 | <br style="clear:both" /> |
21 | 19 | </div> | ... | ... |
app/views/memberships/suggest.html.erb
... | ... | @@ -13,9 +13,7 @@ |
13 | 13 | </em> |
14 | 14 | </p> |
15 | 15 | <% else %> |
16 | - <%= render :partial => 'shared/profile_list', :locals => { :profiles => @suggestions, :collection => :communities_suggestions } %> | |
16 | + <%= render :partial => 'shared/profile_list', :locals => { :suggestions => @suggestions, :collection => :communities_suggestions } %> | |
17 | 17 | <% end %> |
18 | - | |
19 | - <%= pagination_links @suggestions, :param_name => 'npage' %> | |
20 | 18 | <br style="clear:both" /> |
21 | 19 | </div> | ... | ... |
app/views/shared/_profile_list.html.erb
1 | 1 | <ul class="profile-list"> |
2 | - <% profiles.each do |profile| %> | |
2 | + <% suggestions.each do |s| %> | |
3 | 3 | <li> |
4 | - <%= link_to_profile profile_image(profile) + '<br/>' + profile.short_name, | |
5 | - profile.identifier, :class => 'profile-link' %> | |
6 | - <div class="controll"> | |
7 | - <% if collection == :friends %> | |
8 | - <%= button_without_text :remove, content_tag('span',_('remove')), | |
9 | - { :action => 'remove', :id => profile.id }, | |
10 | - :title => _('remove') %> | |
11 | - <%= button_without_text 'menu-mail', content_tag('span',_('contact')), | |
12 | - profile.url.merge(:controller => 'contact', :action => 'new', :profile => profile.identifier), | |
13 | - :title => _('contact') %> | |
14 | - <% elsif collection == :friends_suggestions %> | |
15 | - <%= button_without_text :add, content_tag('span',_('add')), | |
16 | - profile.add_url, | |
17 | - :class => 'add-friend', | |
18 | - :title => _('Add friend') %> | |
19 | - <%= button_without_text :remove, content_tag('span',_('remove')), | |
20 | - { :action => 'remove_suggestion', :id => profile.identifier }, | |
21 | - :title => _('Remove suggestion'), | |
22 | - :method => 'post', | |
23 | - :confirm => _('Are you sure you want to remove this suggestion?') %> | |
24 | - <% elsif collection == :communities_suggestions %> | |
25 | - <%= button_without_text :add, content_tag('span',_('join')), | |
26 | - profile.join_url, | |
27 | - :class => 'join-community', | |
28 | - :title => _("Join %s") % profile.name %> | |
4 | + <%= link_to_profile profile_image(s.suggestion, :minor) + '<br/>' + s.suggestion.short_name, | |
5 | + s.suggestion.identifier, :class => 'profile-link' %> | |
6 | + <%= button_without_text :help, content_tag('span',_('info about suggestion')), | |
7 | + { :action => '#' }, | |
8 | + :class => 'explain-suggestion', | |
9 | + :title => _('Why this suggestion?') %> | |
10 | + <div class='extra_info' style='display:none'> | |
11 | + <%= profile_suggestion_categories(s) %> | |
12 | + </div> | |
13 | + <div class="controll"> | |
14 | + <% if collection == :friends_suggestions %> | |
15 | + <%= button_without_text :add, content_tag('span',_('add')), | |
16 | + s.suggestion.add_url, | |
17 | + :class => 'add-friend', | |
18 | + :title => _('Add friend') %> | |
29 | 19 | <%= button_without_text :remove, content_tag('span',_('remove')), |
30 | - { :action => 'remove_suggestion', :id => profile.identifier }, | |
20 | + { :action => 'remove_suggestion', :id => s.suggestion.identifier }, | |
31 | 21 | :title => _('Remove suggestion'), |
32 | 22 | :method => 'post', |
33 | 23 | :confirm => _('Are you sure you want to remove this suggestion?') %> |
34 | - <% end %> | |
35 | - </div><!-- end class="controll" --> | |
24 | + <% elsif collection == :communities_suggestions %> | |
25 | + <%= button_without_text :add, content_tag('span',_('join')), | |
26 | + s.suggestion.join_url, | |
27 | + :class => 'join-community', | |
28 | + :title => _("Join %s") % s.suggestion.name %> | |
29 | + <%= button_without_text :remove, content_tag('span',_('remove')), | |
30 | + { :action => 'remove_suggestion', :id => s.suggestion.identifier }, | |
31 | + :title => _('Remove suggestion'), | |
32 | + :method => 'post', | |
33 | + :confirm => _('Are you sure you want to remove this suggestion?') %> | |
34 | + <% end %> | |
35 | + </div><!-- end class="controll" --> | |
36 | 36 | </li> |
37 | 37 | <% end %> |
38 | 38 | </ul> | ... | ... |
app/views/user_mailer/profiles_suggestions_email.html.erb
1 | 1 | <%= _('Hi, %{recipient}!') % { :recipient => @recipient } %> |
2 | 2 | |
3 | -<p><%= _('We want to give you some suggestions to grow up your network. Check it out!') %></p> | |
3 | +<p><%= _('We want to give you some suggestions to grow up your network.') %> | |
4 | +<p><%= _('Check it out!') %></p> | |
4 | 5 | |
5 | 6 | <% unless @people_suggestions.empty? %> |
6 | 7 | <p><%= _('Friends suggestions:') %></p> | ... | ... |
public/javascripts/application.js
... | ... | @@ -1053,6 +1053,14 @@ function showHideTermsOfUse() { |
1053 | 1053 | } |
1054 | 1054 | } |
1055 | 1055 | |
1056 | +jQuery('.profiles-suggestions .explain-suggestion').live('click', function() { | |
1057 | + var clicked = jQuery(this); | |
1058 | + jQuery('.profiles-suggestions .extra_info').hide(); | |
1059 | + clicked.toggleClass('active'); | |
1060 | + clicked.next('.extra_info').toggle(); | |
1061 | + return false; | |
1062 | +}); | |
1063 | + | |
1056 | 1064 | jQuery(document).ready(function(){ |
1057 | 1065 | showHideTermsOfUse(); |
1058 | 1066 | ... | ... |
public/stylesheets/application.css
... | ... | @@ -2131,7 +2131,8 @@ a.button.disabled, input.disabled { |
2131 | 2131 | #content .common-profile-list-block .sex-male span, #content .common-profile-list-block .sex-female span, #content .common-profile-list-block .sex-undef span { |
2132 | 2132 | display: none; |
2133 | 2133 | } |
2134 | -.common-profile-list-block .extra_info { | |
2134 | +.common-profile-list-block .extra_info, | |
2135 | +.profile-list .extra_info { | |
2135 | 2136 | font-size: 9px; |
2136 | 2137 | opacity: 0.5; |
2137 | 2138 | filter: alpha(opacity=50); |
... | ... | @@ -3955,16 +3956,24 @@ h1#agenda-title { |
3955 | 3956 | .controller-friends .profile-list li, |
3956 | 3957 | .profiles-suggestions .profile-list li { |
3957 | 3958 | float: left; |
3958 | - width: 90px; | |
3959 | + margin: 5px; | |
3959 | 3960 | height: 90px; |
3960 | - max-width: 80px; | |
3961 | 3961 | max-height: 80px; |
3962 | - margin: 5px; | |
3963 | 3962 | padding: 5px; |
3964 | 3963 | border: 2px solid transparent; |
3965 | 3964 | list-style: none; |
3966 | 3965 | position: relative; |
3967 | 3966 | } |
3967 | +.controller-favorite_enterprises .profile-list li, | |
3968 | +.controller-friends .profile-list li { | |
3969 | + width: 90px; | |
3970 | + max-width: 80px; | |
3971 | +} | |
3972 | +.profiles-suggestions .profile-list li { | |
3973 | + width: 76px; | |
3974 | + max-width: 76px; | |
3975 | +} | |
3976 | + | |
3968 | 3977 | .controller-favorite_enterprises .profile-list li:hover, |
3969 | 3978 | .controller-friends .profile-list li:hover, |
3970 | 3979 | .profiles-suggestions .profile-list li:hover { |
... | ... | @@ -4000,12 +4009,22 @@ h1#agenda-title { |
4000 | 4009 | .profiles-suggestions .profile-list { |
4001 | 4010 | position: relative; |
4002 | 4011 | } |
4012 | +.profiles-suggestions .profile-list .explain-suggestion { | |
4013 | + position: absolute; | |
4014 | + top: 7px; | |
4015 | + left: -5px; | |
4016 | + z-index: 10; | |
4017 | +} | |
4018 | +#content .profiles-suggestions .profile-list .explain-suggestion.active { | |
4019 | + border-bottom-color: transparent; | |
4020 | +} | |
4021 | + | |
4003 | 4022 | .controller-favorite_enterprises .profile-list .controll, |
4004 | 4023 | .controller-friends .profile-list .controll, |
4005 | 4024 | .profiles-suggestions .profile-list .controll { |
4006 | 4025 | position: absolute; |
4007 | 4026 | top: 7px; |
4008 | - right: -10px; | |
4027 | + right: -5px; | |
4009 | 4028 | } |
4010 | 4029 | .controller-favorite_enterprises .profile-list .controll a, |
4011 | 4030 | .controller-friends .profile-list .controll a, |
... | ... | @@ -4024,6 +4043,31 @@ h1#agenda-title { |
4024 | 4043 | clear: both; |
4025 | 4044 | padding-top: 20px; |
4026 | 4045 | } |
4046 | + | |
4047 | +.profiles-suggestions .profile-list .extra_info { | |
4048 | + background: url("/images/down-arrow.png") no-repeat scroll center top #eee; | |
4049 | + border: 1px solid #ccc; | |
4050 | + left: -66px; | |
4051 | + min-width: 135px; | |
4052 | + padding: 5px; | |
4053 | + position: absolute; | |
4054 | + top: 29px; | |
4055 | + opacity: 0.9; | |
4056 | + z-index: 5; | |
4057 | +} | |
4058 | + | |
4059 | +.profiles-suggestions .profile-list .extra_info p { | |
4060 | + margin: 0px; | |
4061 | +} | |
4062 | + | |
4063 | +.profiles-suggestions .profile-list .extra_info span { | |
4064 | + background-position: 4px 50%; | |
4065 | + background-repeat: no-repeat; | |
4066 | + display: block; | |
4067 | + line-height: 20px; | |
4068 | + padding: 0 0 0 25px; | |
4069 | +} | |
4070 | + | |
4027 | 4071 | /* ==> public/stylesheets/controller_friends.css <== */ |
4028 | 4072 | |
4029 | 4073 | .controller-friends #remove_friend .friend_picture, | ... | ... |
test/unit/person_test.rb
... | ... | @@ -1544,6 +1544,28 @@ class PersonTest < ActiveSupport::TestCase |
1544 | 1544 | assert_equal [suggested_community], person.suggested_communities |
1545 | 1545 | end |
1546 | 1546 | |
1547 | + should 'disable friend suggestion' do | |
1548 | + person = create_user('person').person | |
1549 | + suggested_person = fast_create(Person) | |
1550 | + | |
1551 | + suggestion = ProfileSuggestion.create(:person => person, :suggestion => suggested_person) | |
1552 | + | |
1553 | + assert_difference 'person.suggested_people.count', -1 do | |
1554 | + person.remove_suggestion(suggested_person) | |
1555 | + end | |
1556 | + end | |
1557 | + | |
1558 | + should 'disable community suggestion' do | |
1559 | + person = create_user('person').person | |
1560 | + suggested_community = fast_create(Community) | |
1561 | + | |
1562 | + suggestion = ProfileSuggestion.create(:person => person, :suggestion => suggested_community) | |
1563 | + | |
1564 | + assert_difference 'person.suggested_communities.count', -1 do | |
1565 | + person.remove_suggestion(suggested_community) | |
1566 | + end | |
1567 | + end | |
1568 | + | |
1547 | 1569 | should 'return url to people suggestions for a person' do |
1548 | 1570 | environment = create_environment('mycolivre.net') |
1549 | 1571 | profile = build(Person, :identifier => 'testprofile', :environment_id => create_environment('mycolivre.net').id) | ... | ... |