Commit 28c193d4053eceaa19d147b8bc3124484d61b442

Authored by Rodrigo Souto
Committed by Antonio Terceiro
1 parent 5bf571f1

Join community and add member through ajax

  Also:
    * Adding links to the profile-image balloon.
    * Removing add-friend and join-community confirmation steps.
app/controllers/my_profile/friends_controller.rb
@@ -8,18 +8,6 @@ class FriendsController < MyProfileController @@ -8,18 +8,6 @@ class FriendsController < MyProfileController
8 end 8 end
9 end 9 end
10 10
11 - def add  
12 - @friend = Person.find(params[:id])  
13 - if request.post? && params[:confirmation]  
14 - # FIXME this shouldn't be in Person model?  
15 - AddFriend.create!(:person => profile, :friend => @friend, :group_for_person => params[:group])  
16 -  
17 - session[:notice] = _('%s still needs to accept being your friend.') % @friend.name  
18 - # FIXME shouldn't redirect to the friend's page?  
19 - redirect_to :action => 'index'  
20 - end  
21 - end  
22 -  
23 def remove 11 def remove
24 @friend = profile.friends.find(params[:id]) 12 @friend = profile.friends.find(params[:id])
25 if request.post? && params[:confirmation] 13 if request.post? && params[:confirmation]
app/controllers/public/profile_controller.rb
1 class ProfileController < PublicController 1 class ProfileController < PublicController
2 2
3 needs_profile 3 needs_profile
4 - before_filter :check_access_to_profile, :except => [:join, :index]  
5 - before_filter :store_before_join, :only => [:join]  
6 - before_filter :login_required, :only => [:join, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_scraps, :view_more_activities, :view_more_network_activities] 4 + before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index]
  5 + before_filter :store_before_join, :only => [:join, :join_not_logged]
  6 + before_filter :login_required, :only => [:join, :join_not_logged, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_scraps, :view_more_activities, :view_more_network_activities]
7 7
8 helper TagsHelper 8 helper TagsHelper
9 9
@@ -82,18 +82,26 @@ class ProfileController &lt; PublicController @@ -82,18 +82,26 @@ class ProfileController &lt; PublicController
82 end 82 end
83 83
84 def join 84 def join
85 - @wizard = params[:wizard]  
86 - if request.post? && params[:confirmation]  
87 - profile.add_member(current_user.person)  
88 - session[:notice] = _('%s administrator still needs to accept you as member.') % profile.name if profile.closed?  
89 - if @wizard  
90 - redirect_to :controller => 'search', :action => 'assets', :asset => 'communities', :wizard => true 85 + if !user.memberships.include?(profile)
  86 + profile.add_member(user)
  87 + if profile.closed?
  88 + render :text => _('%s administrator still needs to accept you as member.') % profile.name
91 else 89 else
92 - redirect_to_before_join 90 + render :text => _('You just became a member of %s.') % profile.name
93 end 91 end
94 else 92 else
95 - if current_user.person.memberships.include?(profile)  
96 - session[:notice] = _('You are already a member of "%s"') % profile.name 93 + render :text => _('You are already a member of %s.') % profile.name
  94 + end
  95 + end
  96 +
  97 + def join_not_logged
  98 + if request.post?
  99 + profile.add_member(user)
  100 + session[:notice] = _('%s administrator still needs to accept you as member.') % profile.name if profile.closed?
  101 + redirect_to_before_join
  102 + else
  103 + if user.memberships.include?(profile)
  104 + session[:notice] = _('You are already a member of %s') % profile.name
97 redirect_to profile.url 105 redirect_to profile.url
98 return 106 return
99 end 107 end
@@ -104,20 +112,37 @@ class ProfileController &lt; PublicController @@ -104,20 +112,37 @@ class ProfileController &lt; PublicController
104 end 112 end
105 113
106 def leave 114 def leave
107 - @wizard = params[:wizard]  
108 - @back_to = params[:back_to] || request.referer  
109 - if request.post? && params[:confirmation] 115 + if user.memberships.include?(profile)
110 profile.remove_member(current_user.person) 116 profile.remove_member(current_user.person)
111 - if @wizard  
112 - redirect_to :controller => 'search', :action => 'assets', :asset => 'communities', :wizard => true  
113 - else  
114 - back = @back_to || profile.url  
115 - redirect_to back  
116 - end 117 + render :text => _('You just left %s.') % profile.name
117 else 118 else
118 - if request.xhr?  
119 - render :layout => false  
120 - end 119 + render :text => _('You are already a member of %s.') % profile.name
  120 + end
  121 + end
  122 +
  123 + def check_membership
  124 + if user.memberships.include?(profile)
  125 + render :text => 'true'
  126 + else
  127 + render :text => 'false'
  128 + end
  129 + end
  130 +
  131 + def add
  132 + # FIXME this shouldn't be in Person model?
  133 + if !user.memberships.include?(profile)
  134 + AddFriend.create!(:person => user, :friend => profile)
  135 + render :text => _('%s still needs to accept being your friend.') % profile.name
  136 + else
  137 + render :text => _('You are already a friend of %s.') % profile.name
  138 + end
  139 + end
  140 +
  141 + def check_friendship
  142 + if user == profile || user.already_request_friendship?(profile) || user.is_a_friend?(profile)
  143 + render :text => 'true'
  144 + else
  145 + render :text => 'false'
121 end 146 end
122 end 147 end
123 148
app/helpers/application_helper.rb
@@ -515,24 +515,27 @@ module ApplicationHelper @@ -515,24 +515,27 @@ module ApplicationHelper
515 if environment.enabled?(:show_balloon_with_profile_links_when_clicked) 515 if environment.enabled?(:show_balloon_with_profile_links_when_clicked)
516 if profile.kind_of?(Person) 516 if profile.kind_of?(Person)
517 [ 517 [
518 - {_('Home Page') => url_for(profile.url)},  
519 - {_('Wall') => url_for(profile.public_profile_url)},  
520 - {_('Friends') => url_for(:controller => :profile, :action => :friends, :profile => profile.identifier)},  
521 - {_('Communities') => url_for(:controller => :profile, :action => :communities, :profile => profile.identifier)} 518 + {_('Wall') => {:href => url_for(profile.public_profile_url)}},
  519 + {_('Friends') => {:href => url_for(:controller => :profile, :action => :friends, :profile => profile.identifier)}},
  520 + {_('Communities') => {:href => url_for(:controller => :profile, :action => :communities, :profile => profile.identifier)}},
  521 + {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email'}},
  522 + {_('Add') => {:href => url_for(profile.add_url), :class => 'add-friend'}}
522 ] 523 ]
523 elsif profile.kind_of?(Community) 524 elsif profile.kind_of?(Community)
524 [ 525 [
525 - {_('Home Page') => url_for(profile.url)},  
526 - {_('Wall') => url_for(profile.public_profile_url)},  
527 - {_('Members') => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)},  
528 - {_('Agenda') => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)} 526 + {_('Wall') => {:href => url_for(profile.public_profile_url)}},
  527 + {_('Members') => {:href => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)}},
  528 + {_('Agenda') => {:href => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)}},
  529 + {_('Join') => {:href => url_for(profile.join_url), :class => 'join-community'}},
  530 + {_('Leave') => {:href => url_for(profile.leave_url), :class => 'leave-community'}},
  531 + {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email'}}
529 ] 532 ]
530 elsif profile.kind_of?(Enterprise) 533 elsif profile.kind_of?(Enterprise)
531 [ 534 [
532 - {_('Home Page') => url_for(profile.url)},  
533 - {_('Products') => catalog_path(profile.identifier)},  
534 - {_('Members') => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)},  
535 - {_('Agenda') => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)} 535 + {_('Products') => {:href => catalog_path(profile.identifier)}},
  536 + {_('Members') => {:href => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)}},
  537 + {_('Agenda') => {:href => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)}},
  538 + {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email'}},
536 ] 539 ]
537 else 540 else
538 [] 541 []
@@ -543,17 +546,24 @@ module ApplicationHelper @@ -543,17 +546,24 @@ module ApplicationHelper
543 # displays a link to the profile homepage with its image (as generated by 546 # displays a link to the profile homepage with its image (as generated by
544 # #profile_image) and its name below it. 547 # #profile_image) and its name below it.
545 def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil ) 548 def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil )
546 - if profile.class == Person  
547 - name = profile.short_name 549 + name = profile.short_name
  550 + if profile.person?
548 city = content_tag 'span', content_tag( 'span', profile.city, :class => 'locality' ), :class => 'adr' 551 city = content_tag 'span', content_tag( 'span', profile.city, :class => 'locality' ), :class => 'adr'
  552 + url = url_for(profile.check_friendship_url)
  553 + trigger_class = 'person-trigger'
549 else 554 else
550 - name = profile.short_name  
551 city = '' 555 city = ''
  556 + url = url_for(profile.check_membership_url)
  557 + if profile.community?
  558 + trigger_class = 'community-trigger'
  559 + elsif profile.enterprise?
  560 + trigger_class = 'enterprise-trigger'
  561 + end
552 end 562 end
553 extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' ) 563 extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' )
554 links = links_for_balloon(profile) 564 links = links_for_balloon(profile)
555 content_tag tag, 565 content_tag tag,
556 - (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => 'menu-submenu-trigger' ) : "") + 566 + (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => "menu-submenu-trigger #{trigger_class}", :url => url) : "") +
557 link_to( 567 link_to(
558 content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + 568 content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) +
559 content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + 569 content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) +
@@ -571,8 +581,9 @@ module ApplicationHelper @@ -571,8 +581,9 @@ module ApplicationHelper
571 def community_image_link( profile, size=:portrait, tag='li' ) 581 def community_image_link( profile, size=:portrait, tag='li' )
572 name = h(profile.name) 582 name = h(profile.name)
573 links = links_for_balloon(profile) 583 links = links_for_balloon(profile)
  584 + url = url_for(profile.check_membership_url)
574 content_tag tag, 585 content_tag tag,
575 - (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => 'menu-submenu-trigger' ) : "") + 586 + (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => 'menu-submenu-trigger community-trigger', :url => url) : "") +
576 link_to( 587 link_to(
577 content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + 588 content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) +
578 content_tag( 'span', name, :class => 'org' ) + 589 content_tag( 'span', name, :class => 'org' ) +
app/models/profile.rb
@@ -426,6 +426,22 @@ class Profile &lt; ActiveRecord::Base @@ -426,6 +426,22 @@ class Profile &lt; ActiveRecord::Base
426 { :profile => identifier, :controller => 'profile', :action => 'join' } 426 { :profile => identifier, :controller => 'profile', :action => 'join' }
427 end 427 end
428 428
  429 + def join_not_logged_url
  430 + { :profile => identifier, :controller => 'profile', :action => 'join_not_logged' }
  431 + end
  432 +
  433 + def check_membership_url
  434 + { :profile => identifier, :controller => 'profile', :action => 'check_membership' }
  435 + end
  436 +
  437 + def add_url
  438 + { :profile => identifier, :controller => 'profile', :action => 'add' }
  439 + end
  440 +
  441 + def check_friendship_url
  442 + { :profile => identifier, :controller => 'profile', :action => 'check_friendship' }
  443 + end
  444 +
429 def public_profile_url 445 def public_profile_url
430 generate_url(:profile => identifier, :controller => 'profile', :action => 'index') 446 generate_url(:profile => identifier, :controller => 'profile', :action => 'index')
431 end 447 end
app/views/blocks/profile_info_actions/community.rhtml
@@ -3,12 +3,14 @@ @@ -3,12 +3,14 @@
3 3
4 <% if profile.members.include?(user) %> 4 <% if profile.members.include?(user) %>
5 <li> 5 <li>
6 - <%= lightbox_link_to content_tag('span', _('Leave')), profile.leave_url, :class => 'button with-text icon-delete', :title => _('Leave this community') %> 6 + <%= button(:delete, content_tag('span', __('Leave')), profile.leave_url, :class => 'leave-community', :title => _("Leave community"), :style => 'position: relative;') %>
  7 + <%= button(:add, content_tag('span', __('Join')), profile.join_url, :class => 'join-community', :title => _("Join community"), :style => 'position: relative; display: none;') %>
7 </li> 8 </li>
8 <% else %> 9 <% else %>
9 <% unless profile.already_request_membership?(user) %> 10 <% unless profile.already_request_membership?(user) %>
10 <li> 11 <li>
11 - <%= lightbox_link_to content_tag('span', _('Join')), profile.join_url, :class => 'button with-text icon-add', :title => _('Join this community') %> 12 + <%= button(:delete, content_tag('span', __('Leave')), profile.leave_url, :class => 'leave-community', :title => _("Leave community"), :style => 'position: relative; display: none;') %>
  13 + <%= button(:add, content_tag('span', __('Join')), profile.join_url, :class => 'join-community', :title => _("Join community"), :style => 'position: relative;') %>
12 </li> 14 </li>
13 <% end %> 15 <% end %>
14 <% end %> 16 <% end %>
@@ -22,7 +24,7 @@ @@ -22,7 +24,7 @@
22 <% else %> 24 <% else %>
23 25
24 <li> 26 <li>
25 - <%= link_to content_tag('span', _('Join')), profile.join_url, :class => 'button with-text icon-add', :title => _('Join this community') %> 27 + <%= link_to content_tag('span', _('Join')), profile.join_not_logged_url, :class => 'button with-text icon-add', :title => _('Join this community') %>
26 </li> 28 </li>
27 29
28 <% end %> 30 <% end %>
app/views/blocks/profile_info_actions/person.rhtml
@@ -2,7 +2,9 @@ @@ -2,7 +2,9 @@
2 <%if logged_in? && (user != profile) %> 2 <%if logged_in? && (user != profile) %>
3 3
4 <% if !user.already_request_friendship?(profile) and !user.is_a_friend?(profile) %> 4 <% if !user.already_request_friendship?(profile) and !user.is_a_friend?(profile) %>
5 - <li><%= link_to content_tag('span', __('Add friend')), user.url.merge(:controller => 'friends', :action => 'add', :id => profile.id), :class => 'button with-text icon-add' %></li> 5 + <li>
  6 + <%= button(:add, content_tag('span', __('Add friend')), profile.add_url, :class => 'add-friend', :title => _("Add friend"), :style => 'position: relative;') %>
  7 + </li>
6 <% end %> 8 <% end %>
7 9
8 <% if user.is_a_friend?(profile) && profile.enable_contact? %> 10 <% if user.is_a_friend?(profile) && profile.enable_contact? %>
app/views/friends/add.rhtml
@@ -1,26 +0,0 @@ @@ -1,26 +0,0 @@
1 -<h1><%= __('Adding %s as a friend') % @friend.name %></h1>  
2 -  
3 -<p>  
4 -<%= __('Are you sure you want to add %s as your friend?') % @friend.name %>  
5 -</p>  
6 -  
7 -<p>  
8 -<em>  
9 -<%= __('Note that %s will need to accept being added as your friend.') % @friend.name %>  
10 -</em>  
11 -</p>  
12 -  
13 -<% form_tag do %>  
14 - <%= hidden_field_tag(:confirmation, 1) %>  
15 -  
16 - <div class="add-friend-tags">  
17 - <%= __('Classify your new friend %s: ') % @friend.name %>  
18 - <%= text_field_with_local_autocomplete('group', profile.suggested_friend_groups, :maxlength => 150) %>  
19 - <p>  
20 - <%= _('Suggestions: %s') % profile.suggested_friend_groups.join(', ') %>  
21 - </p>  
22 - </div>  
23 -  
24 - <%= submit_button(:ok, __("Yes, I want to add %s as my friend") % @friend.name) %>  
25 - <%= button(:cancel, _("No, I don't want"), :action => 'index') %>  
26 -<% end %>  
app/views/layouts/_javascript.rhtml
1 -<%= javascript_include_tag :defaults, 'jquery-latest.js', 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery.cookie', 'reflection', :cache => 'cache-general' %> 1 +<%= javascript_include_tag :defaults, 'jquery-latest.js', 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery.cookie', 'reflection', 'add-and-join', :cache => 'cache-general' %>
app/views/profile/_private_profile.rhtml
@@ -7,10 +7,10 @@ @@ -7,10 +7,10 @@
7 7
8 <% button_bar do %> 8 <% button_bar do %>
9 <% if @action == :join && logged_in? %> 9 <% if @action == :join && logged_in? %>
10 - <%= lightbox_link_to content_tag('span', _('Join')), profile.join_url, :class => 'button with-text icon-add', :title => _('Join this community') %> 10 + <%= button(:add, content_tag('span', __('Join')), profile.join_url, :class => 'join-community', :title => _("Join community"), :style => 'position: relative;') %>
11 <% end %> 11 <% end %>
12 <% if @action == :add_friend && logged_in? && !user.already_request_friendship?(profile) %> 12 <% if @action == :add_friend && logged_in? && !user.already_request_friendship?(profile) %>
13 - <%= link_to content_tag('span', __('Add friend')), user.url.merge(:controller => 'friends', :action => 'add', :id => profile.id), :class => 'button with-text icon-add' %> 13 + <%= button(:add, content_tag('span', __('Add friend')), profile.add_url, :class => 'add-friend', :title => _("Add friend"), :style => 'position: relative;') %>
14 <% end %> 14 <% end %>
15 <%= button :back, _('Go back'), :back %> 15 <%= button :back, _('Go back'), :back %>
16 <%= button :home, _("Go to %s home page") % environment.name, :controller => 'home' %> 16 <%= button :home, _("Go to %s home page") % environment.name, :controller => 'home' %>
features/balloon.feature
@@ -38,7 +38,6 @@ Feature: balloon @@ -38,7 +38,6 @@ Feature: balloon
38 When I click ".menu-submenu-trigger" 38 When I click ".menu-submenu-trigger"
39 Then I should see "Profile" 39 Then I should see "Profile"
40 And I should see "Friends" 40 And I should see "Friends"
41 - And I should see "Home Page"  
42 41
43 @selenium 42 @selenium
44 Scenario: I should see balloon when clicked on community block trigger 43 Scenario: I should see balloon when clicked on community block trigger
@@ -71,4 +70,3 @@ Feature: balloon @@ -71,4 +70,3 @@ Feature: balloon
71 When I click ".menu-submenu-trigger" 70 When I click ".menu-submenu-trigger"
72 Then I should see "Members" 71 Then I should see "Members"
73 And I should see "Agenda" 72 And I should see "Agenda"
74 - And I should see "Home Page"  
features/join_community.feature
@@ -1,24 +0,0 @@ @@ -1,24 +0,0 @@
1 -Feature: join a community  
2 - As a user  
3 - I want to join a community  
4 - In order to interact with other people  
5 -  
6 - Background:  
7 - Given the following users  
8 - | login | name |  
9 - | joaosilva | Joao Silva |  
10 - Given the following communities  
11 - | identifier | name |  
12 - | sample-community | Sample Community |  
13 -  
14 - Scenario: ask confirmation before join community  
15 - Given I am logged in as "joaosilva"  
16 - And I am on Sample Community's homepage  
17 - When I follow "Join"  
18 - Then I should see "Are you sure you want to join Sample Community"  
19 -  
20 - Scenario: dont ask confirmation before join community if already member  
21 - Given joaosilva is member of sample-community  
22 - And I am logged in as "joaosilva"  
23 - When I go to /profile/sample-community  
24 - Then I should not see "Are you sure you want to join Community to join"  
features/my_network_block.feature
@@ -23,7 +23,6 @@ Feature: my_network_block @@ -23,7 +23,6 @@ Feature: my_network_block
23 Then I should see "2 communities" 23 Then I should see "2 communities"
24 When I go to Public Community's homepage 24 When I go to Public Community's homepage
25 And I follow "Join" 25 And I follow "Join"
26 - And I press "Yes, I want to join."  
27 When I go to Joao Silva's homepage 26 When I go to Joao Silva's homepage
28 Then I should see "3 communities" 27 Then I should see "3 communities"
29 28
@@ -37,7 +36,6 @@ Feature: my_network_block @@ -37,7 +36,6 @@ Feature: my_network_block
37 Then I should see "One community" 36 Then I should see "One community"
38 When I go to Public Community's homepage 37 When I go to Public Community's homepage
39 And I follow "Join" 38 And I follow "Join"
40 - And I press "Yes, I want to join."  
41 When I go to Joao Silva's homepage 39 When I go to Joao Silva's homepage
42 Then I should see "2 communities" 40 Then I should see "2 communities"
43 41
features/private_profile.feature
@@ -17,7 +17,6 @@ Feature: private profiles @@ -17,7 +17,6 @@ Feature: private profiles
17 When I go to Safernet's homepage 17 When I go to Safernet's homepage
18 Then I should see "members only" 18 Then I should see "members only"
19 When I follow "Join" 19 When I follow "Join"
20 - And I press "Yes, I want to join"  
21 And "joao" is accepted on community "Safernet" 20 And "joao" is accepted on community "Safernet"
22 Then "joao" should be a member of "Safernet" 21 Then "joao" should be a member of "Safernet"
23 When I go to Safernet's homepage 22 When I go to Safernet's homepage
@@ -27,5 +26,4 @@ Feature: private profiles @@ -27,5 +26,4 @@ Feature: private profiles
27 Given I am logged in as "joao" 26 Given I am logged in as "joao"
28 When I go to shygirl's homepage 27 When I go to shygirl's homepage
29 Then I should see "friends only" 28 Then I should see "friends only"
30 - When I follow "Add friend"  
31 - And I press "Yes, I want" 29 + And I follow "Add friend"
public/javascripts/add-and-join.js 0 → 100644
@@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
  1 +jQuery(function($) {
  2 +
  3 + $(".add-friend").live('click', function(){
  4 + clicked = $(this)
  5 + url = clicked.attr("href");
  6 + loading_for_button(this);
  7 + $.post(url, function(data){
  8 + clicked.fadeOut();
  9 + display_notice(data);
  10 + });
  11 + return false;
  12 + })
  13 +
  14 + $(".join-community").live('click', function(){
  15 + clicked = $(this)
  16 + url = clicked.attr("href");
  17 + loading_for_button(this);
  18 + $.post(url, function(data){
  19 + clicked.fadeOut(function(){
  20 + clicked.css("display","none");
  21 + clicked.parent().parent().find(".leave-community").fadeIn();
  22 + clicked.parent().parent().find(".leave-community").css("display", "");
  23 + });
  24 + clicked.css("cursor","");
  25 + $(".small-loading").remove();
  26 + display_notice(data);
  27 + });
  28 + return false;
  29 + })
  30 +
  31 + $(".leave-community").live('click', function(){
  32 + clicked = $(this)
  33 + url = clicked.attr("href");
  34 + loading_for_button(this);
  35 + $.post(url, function(data){
  36 + clicked.fadeOut(function(){
  37 + clicked.css("display","none");
  38 + clicked.parent().parent().find(".join-community").fadeIn();
  39 + clicked.parent().parent().find(".join-community").css("display", "");
  40 + });
  41 + clicked.css("cursor","");
  42 + $(".small-loading").remove();
  43 + display_notice(data);
  44 + });
  45 + return false;
  46 + })
  47 +
  48 + $(".person-trigger").click(function(){
  49 + clicked = $(this);
  50 + url = clicked.attr("url");
  51 + $.get(url, function(data){
  52 + if(data == "true"){
  53 + clicked.parent().find(".add-friend").fadeOut(function(){
  54 + clicked.parent().find(".send-an-email").fadeIn();
  55 + })
  56 + }
  57 + else if(data == "false"){
  58 + clicked.parent().find(".send-an-email").fadeOut(function(){
  59 + clicked.parent().find(".add-friend").fadeIn();
  60 + });
  61 + }
  62 + })
  63 + })
  64 +
  65 + $(".community-trigger").click(function(){
  66 + clicked = $(this);
  67 + url = clicked.attr("url");
  68 + $.get(url, function(data){
  69 + if(data == "true"){
  70 + clicked.parent().find(".join-community").fadeOut(function(){
  71 + clicked.parent().find(".leave-community").fadeIn();
  72 + clicked.parent().find(".send-an-email").fadeIn();
  73 + });
  74 + }
  75 + else if(data == "false"){
  76 + clicked.parent().find(".send-an-email").fadeOut();
  77 + clicked.parent().find(".leave-community").fadeOut(function(){
  78 + clicked.parent().find(".join-community").fadeIn();
  79 + });
  80 + }
  81 + })
  82 + })
  83 +
  84 + $(".enterprise-trigger").click(function(){
  85 + clicked = $(this);
  86 + url = clicked.attr("url");
  87 + $.get(url, function(data){
  88 + if(data == "true")
  89 + clicked.parent().find(".send-an-email").fadeIn();
  90 + else if(data == "false")
  91 + clicked.parent().find(".send-an-email").fadeOut();
  92 + })
  93 + })
  94 +});
public/javascripts/application.js
@@ -263,7 +263,11 @@ function toggleSubmenu(trigger, title, link_list) { @@ -263,7 +263,11 @@ function toggleSubmenu(trigger, title, link_list) {
263 content.append('<h4>' + title + '</h4>'); 263 content.append('<h4>' + title + '</h4>');
264 jQuery.each(link_list, function(index, link_hash) { 264 jQuery.each(link_list, function(index, link_hash) {
265 for (label in link_hash) { 265 for (label in link_hash) {
266 - list.append('<li><a href="' + link_hash[label] + '">' + label + '</a></li>'); 266 + options = "";
  267 + jQuery.each(link_hash[label], function(option, value){
  268 + options += option +'="'+ value + '" ';
  269 + })
  270 + list.append('<li><a '+ options +'">' + label + '</a></li>');
267 } 271 }
268 }); 272 });
269 content.append(list); 273 content.append(list);
public/stylesheets/application.css
@@ -2036,7 +2036,7 @@ div#activation_enterprise div { @@ -2036,7 +2036,7 @@ div#activation_enterprise div {
2036 .profile-info-options { 2036 .profile-info-options {
2037 padding-top: 20px; 2037 padding-top: 20px;
2038 text-align: right; 2038 text-align: right;
2039 - padding-right: 5px; 2039 + padding-right: 20px;
2040 } 2040 }
2041 2041
2042 .profile-info-block { 2042 .profile-info-block {
test/functional/friends_controller_test.rb
@@ -34,23 +34,6 @@ class FriendsControllerTest &lt; Test::Unit::TestCase @@ -34,23 +34,6 @@ class FriendsControllerTest &lt; Test::Unit::TestCase
34 assert_kind_of Array, assigns(:friends) 34 assert_kind_of Array, assigns(:friends)
35 end 35 end
36 36
37 - should 'confirm addition of new friend' do  
38 - get :add, :id => friend.id  
39 -  
40 - assert_response :success  
41 - assert_template 'add'  
42 -  
43 - ok("must load the friend being added to display") { friend == assigns(:friend) }  
44 -  
45 - end  
46 -  
47 - should 'actually add friend' do  
48 - assert_difference AddFriend, :count do  
49 - post :add, :id => friend.id, :confirmation => '1'  
50 - assert_response :redirect  
51 - end  
52 - end  
53 -  
54 should 'confirm removal of friend' do 37 should 'confirm removal of friend' do
55 profile.add_friend(friend) 38 profile.add_friend(friend)
56 39
test/functional/profile_controller_test.rb
@@ -76,49 +76,22 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -76,49 +76,22 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
76 assert_kind_of Array, assigns(:favorite_enterprises) 76 assert_kind_of Array, assigns(:favorite_enterprises)
77 end 77 end
78 78
79 - should 'render join template without layout when called with AJAX' do 79 + should 'not render any template when joining community due to Ajax request' do
80 community = Community.create!(:name => 'my test community') 80 community = Community.create!(:name => 'my test community')
81 login_as(@profile.identifier) 81 login_as(@profile.identifier)
82 - @request.expects(:xhr?).returns(true).at_least_once  
83 82
84 get :join, :profile => community.identifier 83 get :join, :profile => community.identifier
85 assert_response :success 84 assert_response :success
86 - assert_template 'join' 85 + assert_template nil
87 assert_no_tag :tag => 'html' 86 assert_no_tag :tag => 'html'
88 end 87 end
89 88
90 - should 'render join template with layout in general' do  
91 - community = Community.create!(:name => 'my test community')  
92 - login_as(@profile.identifier)  
93 - @request.expects(:xhr?).returns(false).at_least_once  
94 -  
95 - get :join, :profile => community.identifier  
96 - assert_response :success  
97 - assert_template 'join'  
98 - assert_tag :tag => 'html'  
99 - end  
100 -  
101 - should 'show Join This Community button for non-member users' do  
102 - login_as(@profile.identifier)  
103 - community = Community.create!(:name => 'my test community')  
104 - get :index, :profile => community.identifier  
105 - assert_tag :tag => 'a', :attributes => { :href => "/profile/#{community.identifier}/join" }  
106 - end  
107 -  
108 - should 'not show Join This Community button for member users' do 89 + should 'actually add friend' do
109 login_as(@profile.identifier) 90 login_as(@profile.identifier)
110 - community = Community.create!(:name => 'my test community')  
111 - community.add_member(@profile)  
112 - get :index, :profile => community.identifier  
113 - assert_no_tag :tag => 'a', :attributes => { :href => "/myprofile/#{@profile.identifier}/memberships/join/#{community.id}" }  
114 -  
115 - end  
116 -  
117 - should 'not show Join This Community button for non-registered users' do  
118 - community = Community.create!(:name => 'my test community')  
119 - get :index, :profile => community.identifier  
120 - assert_no_tag :tag => 'a', :attributes => { :href => "/myprofile/#{@profile.identifier}/memberships/leave/#{community.id}" }  
121 - 91 + person = fast_create(Person)
  92 + assert_difference AddFriend, :count do
  93 + post :add, :profile => person.identifier
  94 + end
122 end 95 end
123 96
124 should 'not show enterprises link to enterprise' do 97 should 'not show enterprises link to enterprise' do
@@ -199,26 +172,10 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -199,26 +172,10 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
199 assert_no_tag :tag => 'a', :child => { :tag => 'span', :content => 'Create a new community' } 172 assert_no_tag :tag => 'a', :child => { :tag => 'span', :content => 'Create a new community' }
200 end 173 end
201 174
202 - should 'not show Leave This Community button for non-member users' do  
203 - login_as(@profile.identifier)  
204 - community = Community.create!(:name => 'my test community')  
205 - get :index, :profile => community.identifier  
206 - assert_no_tag :tag => 'a', :attributes => { :href => "/myprofile/#{@profile.identifier}/memberships/leave/#{community.id}" }  
207 - end  
208 -  
209 - should 'show Leave This Community button for member users' do  
210 - login_as(@profile.identifier)  
211 - community = Community.create!(:name => 'my test community')  
212 - community.add_member(@profile)  
213 - get :index, :profile => community.identifier  
214 - assert_tag :tag => 'a',  
215 - :attributes => { :href => "/profile/#{community.identifier}/leave" }  
216 - end  
217 -  
218 should 'not show Leave This Community button for non-registered users' do 175 should 'not show Leave This Community button for non-registered users' do
219 community = Community.create!(:name => 'my test community') 176 community = Community.create!(:name => 'my test community')
220 get :index, :profile => community.identifier 177 get :index, :profile => community.identifier
221 - assert_no_tag :tag => 'a', :attributes => { :href => "/myprofile/#{@profile.identifier}/memberships/leave/#{community.id}" } 178 + assert_no_tag :tag => 'a', :attributes => { :href => "/profile/#{@profile.identifier}/leave" }
222 end 179 end
223 180
224 should 'check access before displaying profile' do 181 should 'check access before displaying profile' do
@@ -414,34 +371,13 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -414,34 +371,13 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
414 assert_no_tag :tag => 'a', :attributes => { :href => "/contact/#{community.identifier}/new" } 371 assert_no_tag :tag => 'a', :attributes => { :href => "/contact/#{community.identifier}/new" }
415 end 372 end
416 373
417 - should 'present confirmation before joining a profile' do  
418 - community = Community.create!(:name => 'my test community')  
419 - login_as @profile.identifier  
420 - get :join, :profile => community.identifier  
421 -  
422 - assert_response :success  
423 - assert_template 'join'  
424 - end  
425 -  
426 should 'actually join profile' do 374 should 'actually join profile' do
427 community = Community.create!(:name => 'my test community') 375 community = Community.create!(:name => 'my test community')
428 login_as @profile.identifier 376 login_as @profile.identifier
429 - post :join, :profile => community.identifier, :confirmation => '1'  
430 -  
431 - assert_response :redirect  
432 - assert_redirected_to community.url  
433 -  
434 - profile = Profile.find(@profile.id)  
435 - assert profile.memberships.include?(community), 'profile should be actually added to the community'  
436 - end 377 + post :join, :profile => community.identifier
437 378
438 - should 'join profile from wizard' do  
439 - community = Community.create!(:name => 'my test community')  
440 - login_as @profile.identifier  
441 - post :join, :profile => community.identifier, :confirmation => '1', :wizard => true  
442 -  
443 - assert_response :redirect  
444 - assert_redirected_to :controller => 'search', :action => 'assets', :asset => 'communities', :wizard => true 379 + assert_response :success
  380 + assert_template nil
445 381
446 profile = Profile.find(@profile.id) 382 profile = Profile.find(@profile.id)
447 assert profile.memberships.include?(community), 'profile should be actually added to the community' 383 assert profile.memberships.include?(community), 'profile should be actually added to the community'
@@ -451,7 +387,7 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -451,7 +387,7 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
451 community = Community.create!(:name => 'my test community', :closed => true) 387 community = Community.create!(:name => 'my test community', :closed => true)
452 login_as @profile.identifier 388 login_as @profile.identifier
453 assert_difference AddMember, :count do 389 assert_difference AddMember, :count do
454 - post :join, :profile => community.identifier, :confirmation => '1' 390 + post :join, :profile => community.identifier
455 end 391 end
456 end 392 end
457 393
@@ -462,74 +398,18 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -462,74 +398,18 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
462 assert_redirected_to :controller => 'account', :action => 'login' 398 assert_redirected_to :controller => 'account', :action => 'login'
463 end 399 end
464 400
465 - should 'present confirmation before leaving a profile' do  
466 - community = Community.create!(:name => 'my test community')  
467 - community.add_member(profile)  
468 -  
469 - login_as(profile.identifier)  
470 - get :leave, :profile => community.identifier  
471 -  
472 - assert_template 'leave'  
473 - assert_tag :tag => 'input', :attributes => {:value => 'Yes, I want to leave.', :type => 'submit'}  
474 - end  
475 -  
476 should 'actually leave profile' do 401 should 'actually leave profile' do
477 community = Community.create!(:name => 'my test community') 402 community = Community.create!(:name => 'my test community')
478 community.add_member(profile) 403 community.add_member(profile)
479 assert_includes profile.memberships, community 404 assert_includes profile.memberships, community
480 405
481 login_as(profile.identifier) 406 login_as(profile.identifier)
482 - post :leave, :profile => community.identifier, :confirmation => '1'  
483 -  
484 - profile = Profile.find(@profile.id)  
485 - assert_not_includes profile.memberships, community  
486 - end  
487 -  
488 - should 'leave profile when on wizard' do  
489 - community = Community.create!(:name => 'my test community')  
490 - community.add_member(profile)  
491 -  
492 - login_as(profile.identifier)  
493 - post :leave, :profile => community.identifier, :confirmation => '1', :wizard => true  
494 -  
495 - assert_response :redirect  
496 - assert_redirected_to :controller => 'search', :action => 'assets', :asset => 'communities', :wizard => true 407 + post :leave, :profile => community.identifier
497 408
498 profile = Profile.find(@profile.id) 409 profile = Profile.find(@profile.id)
499 assert_not_includes profile.memberships, community 410 assert_not_includes profile.memberships, community
500 end 411 end
501 412
502 - should "offer button to close 'leave community' lightbox" do  
503 - community = Community.create!(:name => 'my test community')  
504 - community.add_member(profile)  
505 -  
506 - login_as(profile.identifier)  
507 - get :index, :profile => community.identifier  
508 -  
509 - assert_tag :tag => 'a', :content => 'Leave', :attributes => { :href => "/profile/#{community.identifier}/leave", :class => /^lbOn/ }  
510 - end  
511 -  
512 - should 'offer button to cancel leaving community' do  
513 - community = Community.create!(:name => 'my test community')  
514 - community.add_member(profile)  
515 -  
516 - login_as(profile.identifier)  
517 - get :leave, :profile => community.identifier  
518 -  
519 - assert_tag :tag => 'a', :content => "No, I don't want."  
520 - end  
521 -  
522 - should 'render without layout when use lightbox to leave community' do  
523 - community = Community.create!(:name => 'my test community')  
524 - community.add_member(profile)  
525 -  
526 - @request.stubs(:xhr?).returns(true)  
527 - login_as(profile.identifier)  
528 - get :leave, :profile => community.identifier  
529 -  
530 - assert_no_tag :tag => 'body' # e.g. no layout  
531 - end  
532 -  
533 should 'require login to leave community' do 413 should 'require login to leave community' do
534 community = Community.create!(:name => 'my test community') 414 community = Community.create!(:name => 'my test community')
535 get :leave, :profile => community.identifier 415 get :leave, :profile => community.identifier
@@ -537,51 +417,6 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -537,51 +417,6 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
537 assert_redirected_to :controller => 'account', :action => 'login' 417 assert_redirected_to :controller => 'account', :action => 'login'
538 end 418 end
539 419
540 - should 'redirect to stored location after leave community' do  
541 - community = Community.create!(:name => 'my test community')  
542 - community.add_member(profile)  
543 -  
544 - @request.expects(:referer).returns("/profile/#{community.identifier}/to_go").at_least_once  
545 - login_as(profile.identifier)  
546 -  
547 - post :leave, :profile => community.identifier, :confirmation => '1', :back_to => @request.referer  
548 -  
549 - assert_redirected_to "/profile/#{community.identifier}/to_go"  
550 - end  
551 -  
552 - should 'store referer location when request leave via get' do  
553 - community = Community.create!(:name => 'my test community')  
554 - login_as(profile.identifier)  
555 -  
556 - @request.expects(:referer).returns("/profile/redirect_to").at_least_once  
557 -  
558 - get :leave, :profile => community.identifier  
559 -  
560 - assert_tag :tag => 'input', :attributes => { :type => 'hidden', :name => 'back_to', :value => @request.referer }  
561 - end  
562 -  
563 - should 'store referer location when request join via get' do  
564 - community = Community.create!(:name => 'my test community')  
565 - login_as(profile.identifier)  
566 -  
567 - @request.session[:before_join] = "/profile/redirect_to"  
568 -  
569 - get :join, :profile => community.identifier  
570 -  
571 - assert_equal '/profile/redirect_to', @request.session[:before_join]  
572 - end  
573 -  
574 - should 'redirect to stored location after join community' do  
575 - community = Community.create!(:name => 'my test community')  
576 -  
577 - @request.expects(:referer).returns("/profile/#{community.identifier}/to_go")  
578 - login_as(profile.identifier)  
579 -  
580 - post :join, :profile => community.identifier, :confirmation => '1'  
581 -  
582 - assert_redirected_to "/profile/#{community.identifier}/to_go"  
583 - end  
584 -  
585 should 'store location before login when request join via get not logged' do 420 should 'store location before login when request join via get not logged' do
586 community = Community.create!(:name => 'my test community') 421 community = Community.create!(:name => 'my test community')
587 422
@@ -598,7 +433,7 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -598,7 +433,7 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
598 @request.expects(:referer).returns("/profile/#{community.identifier}/to_go") 433 @request.expects(:referer).returns("/profile/#{community.identifier}/to_go")
599 login_as(profile.identifier) 434 login_as(profile.identifier)
600 435
601 - post :join, :profile => community.identifier, :confirmation => '1' 436 + post :join_not_logged, :profile => community.identifier
602 437
603 assert_redirected_to "/profile/#{community.identifier}/to_go" 438 assert_redirected_to "/profile/#{community.identifier}/to_go"
604 439
test/unit/application_helper_test.rb
@@ -484,7 +484,7 @@ class ApplicationHelperTest &lt; Test::Unit::TestCase @@ -484,7 +484,7 @@ class ApplicationHelperTest &lt; Test::Unit::TestCase
484 person.stubs(:url).returns('url for person') 484 person.stubs(:url).returns('url for person')
485 person.stubs(:public_profile_url).returns('url for person') 485 person.stubs(:public_profile_url).returns('url for person')
486 links = links_for_balloon(person) 486 links = links_for_balloon(person)
487 - assert_equal ['Home Page', 'Wall', 'Friends', 'Communities'], links.map{|i| i.keys.first} 487 + assert_equal ['Wall', 'Friends', 'Communities', 'Send an e-mail', 'Add'], links.map{|i| i.keys.first}
488 end 488 end
489 489
490 should 'return ordered list of links to balloon to Community' do 490 should 'return ordered list of links to balloon to Community' do
@@ -495,7 +495,7 @@ class ApplicationHelperTest &lt; Test::Unit::TestCase @@ -495,7 +495,7 @@ class ApplicationHelperTest &lt; Test::Unit::TestCase
495 community.stubs(:url).returns('url for community') 495 community.stubs(:url).returns('url for community')
496 community.stubs(:public_profile_url).returns('url for community') 496 community.stubs(:public_profile_url).returns('url for community')
497 links = links_for_balloon(community) 497 links = links_for_balloon(community)
498 - assert_equal ['Home Page', 'Wall', 'Members', 'Agenda'], links.map{|i| i.keys.first} 498 + assert_equal ['Wall', 'Members', 'Agenda', 'Join', 'Leave', 'Send an e-mail'], links.map{|i| i.keys.first}
499 end 499 end
500 500
501 should 'return ordered list of links to balloon to Enterprise' do 501 should 'return ordered list of links to balloon to Enterprise' do
@@ -507,7 +507,7 @@ class ApplicationHelperTest &lt; Test::Unit::TestCase @@ -507,7 +507,7 @@ class ApplicationHelperTest &lt; Test::Unit::TestCase
507 enterprise.stubs(:public_profile_url).returns('url for enterprise') 507 enterprise.stubs(:public_profile_url).returns('url for enterprise')
508 stubs(:catalog_path) 508 stubs(:catalog_path)
509 links = links_for_balloon(enterprise) 509 links = links_for_balloon(enterprise)
510 - assert_equal ['Home Page', 'Products', 'Members', 'Agenda'], links.map{|i| i.keys.first} 510 + assert_equal ['Products', 'Members', 'Agenda', 'Send an e-mail'], links.map{|i| i.keys.first}
511 end 511 end
512 512
513 should 'use favicon from environment theme if does not have profile' do 513 should 'use favicon from environment theme if does not have profile' do