Commit 23f8a40ad66b3578db9c70948734741303bdf926
Committed by
Rodrigo Souto
1 parent
d1f72816
Exists in
master
and in
22 other branches
invite: allow network member/friend invitation
This feature allows organizations to invite people and users to request friendship from other users from the network instead of only through email. Signed-off-by: Rodrigo Souto <rodrigo@colivre.coop.br> Signed-off-by: Andre Bernardes <andrebsguedes@gmail.com> Signed-off-by: Fabio Teixeira <fabio1079@gmail.com> Signed-off-by: Pedro de Lyra <pedrodelyra@gmail.com>
Showing
8 changed files
with
117 additions
and
34 deletions
Show diff stats
app/controllers/public/invite_controller.rb
@@ -11,7 +11,7 @@ class InviteController < PublicController | @@ -11,7 +11,7 @@ class InviteController < PublicController | ||
11 | labels = Profile::SEARCHABLE_FIELDS.except(:nickname).merge(User::SEARCHABLE_FIELDS).map { |name,info| info[:label].downcase } | 11 | labels = Profile::SEARCHABLE_FIELDS.except(:nickname).merge(User::SEARCHABLE_FIELDS).map { |name,info| info[:label].downcase } |
12 | last = labels.pop | 12 | last = labels.pop |
13 | label = labels.join(', ') | 13 | label = labels.join(', ') |
14 | - @search_friend_fields = "#{label} #{_('or')} #{last}" | 14 | + @search_fields = "#{label} #{_('or')} #{last}" |
15 | 15 | ||
16 | if request.post? | 16 | if request.post? |
17 | contact_list = ContactList.create | 17 | contact_list = ContactList.create |
@@ -78,8 +78,12 @@ class InviteController < PublicController | @@ -78,8 +78,12 @@ class InviteController < PublicController | ||
78 | end | 78 | end |
79 | end | 79 | end |
80 | 80 | ||
81 | - def search_friend | ||
82 | - render :text => find_by_contents(:people, environment, environment.people.not_members_of(profile), params['q'], {:page => 1}, {:joins => :user})[:results].map {|person| {:id => person.id, :name => person.name} }.to_json | 81 | + def search |
82 | + scope = profile.invite_friends_only ? user.friends : environment.people | ||
83 | + scope = scope.not_members_of(profile) if profile.organization? | ||
84 | + scope = scope.not_friends_of(profile) if profile.person? | ||
85 | + results = find_by_contents(:people, environment, scope, params['q'], {:page => 1}, {:joins => :user})[:results] | ||
86 | + render :text => prepare_to_token_input(results).to_json | ||
83 | end | 87 | end |
84 | 88 | ||
85 | protected | 89 | protected |
app/views/friends/index.html.erb
@@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
16 | <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> | 16 | <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> |
17 | <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> | 17 | <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> |
18 | <% unless @plugins.dispatch(:remove_invite_friends_button).include?(true) %> | 18 | <% unless @plugins.dispatch(:remove_invite_friends_button).include?(true) %> |
19 | - <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'invite_friends') %> | 19 | + <%= button(:search, _('Invite people'), :controller => 'invite', :action => 'invite_friends') %> |
20 | <% end %> | 20 | <% end %> |
21 | <% end %> | 21 | <% end %> |
22 | 22 |
app/views/invite/invite_friends.html.erb
1 | <% if profile.person? %> | 1 | <% if profile.person? %> |
2 | - <h1><%= _('Invite your friends') %></h1> | 2 | + <h1><%= _('Ask for friendship') %></h1> |
3 | + <% description = _('You can search for user profiles and ask them to become your friends.') %> | ||
3 | <% else %> | 4 | <% else %> |
4 | <h1><%= _('Invite your friends to join %s') % profile.name %></h1> | 5 | <h1><%= _('Invite your friends to join %s') % profile.name %></h1> |
6 | + <% description = _('You can search for user profiles and invite them to join this group.') %> | ||
5 | <% end %> | 7 | <% end %> |
6 | 8 | ||
7 | -<% if profile.community? %> | ||
8 | - <h2><%= _('Invite registered users') %></h2> | ||
9 | - <p><%= _('You can search for user profiles and invite them to join this community.') %></p> | 9 | +<h3> |
10 | + <%= _("Choose person by:") %> | ||
11 | +</h3> | ||
12 | + | ||
13 | +<p> | ||
14 | + <%= labelled_radio_button _("Name"), :invite_friend_by, 1, true, :id => "invite_friend_by_name", :class => "invite_friend_by" %> | ||
15 | + <%= labelled_radio_button _("Email"), :invite_friend_by, 2, false, :id => "invite_friend_by_email", :class => "invite_friend_by" %> | ||
16 | +</p> | ||
17 | + | ||
18 | +<div class='invite_by_name'> | ||
19 | + <p><%= description %></p> | ||
10 | <%= form_tag :action => 'invite_registered_friend' do %> | 20 | <%= form_tag :action => 'invite_registered_friend' do %> |
11 | - <% search_action = url_for(:action => 'search_friend') %> | ||
12 | - <%= token_input_field_tag(:q, 'search-friends', search_action, | ||
13 | - { :hint_text => _('Type in your friend\'s %{search_fields}') % {:search_fields => @search_friend_fields}, | ||
14 | - :focus => false }) %> | 21 | + <% search_action = url_for(:action => 'search') %> |
22 | + <%= token_input_field_tag( | ||
23 | + :q, 'search-people', search_action, | ||
24 | + { :hint_text => _('Type in the person\'s %{search_fields}') % {:search_fields => @search_fields}, | ||
25 | + :focus => false }) %> | ||
15 | 26 | ||
16 | <% button_bar do %> | 27 | <% button_bar do %> |
17 | <%= submit_button('save', _('Invite'))%> | 28 | <%= submit_button('save', _('Invite'))%> |
18 | <%= button('cancel', _('Cancel'), profile.url)%> | 29 | <%= button('cancel', _('Cancel'), profile.url)%> |
19 | <% end %> | 30 | <% end %> |
20 | <% end %> | 31 | <% end %> |
32 | +</div> | ||
21 | 33 | ||
22 | - <br /> | 34 | +<div class='invite_by_email' style="display: none;"> |
23 | <h2><%= _('Invite people from my e-mail contacts') %></h2> | 35 | <h2><%= _('Invite people from my e-mail contacts') %></h2> |
24 | <% header = 'h3' %> | 36 | <% header = 'h3' %> |
25 | 37 | ||
26 | -<% end %> | ||
27 | - | ||
28 | <%= render :partial => 'invite/select_address_book', :locals => {:header => header} %> | 38 | <%= render :partial => 'invite/select_address_book', :locals => {:header => header} %> |
39 | +</div> | ||
29 | 40 | ||
30 | <div id="loadingScreen"></div> | 41 | <div id="loadingScreen"></div> |
42 | +<%= javascript_include_tag 'invite' %> |
app/views/profile/friends.html.erb
@@ -18,7 +18,7 @@ | @@ -18,7 +18,7 @@ | ||
18 | <%= button :back, _('Go back'), { :controller => 'profile' } %> | 18 | <%= button :back, _('Go back'), { :controller => 'profile' } %> |
19 | <% if user == profile %> | 19 | <% if user == profile %> |
20 | <%= button :edit, _('Manage my friends'), :controller => 'friends', :action => 'index', :profile => profile.identifier %> | 20 | <%= button :edit, _('Manage my friends'), :controller => 'friends', :action => 'index', :profile => profile.identifier %> |
21 | - <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'invite_friends') %> | 21 | + <%= button(:search, _('Invite people'), :controller => 'invite', :action => 'invite_friends') %> |
22 | <% end %> | 22 | <% end %> |
23 | <% end %> | 23 | <% end %> |
24 | 24 |
features/invitation.feature
@@ -17,25 +17,22 @@ Feature: invitation | @@ -17,25 +17,22 @@ Feature: invitation | ||
17 | 17 | ||
18 | Scenario: see link to invite friends | 18 | Scenario: see link to invite friends |
19 | When I am on /profile/josesilva/friends | 19 | When I am on /profile/josesilva/friends |
20 | - Then I should see "Invite people from my e-mail contacts" link | 20 | + Then I should see "Invite people" link |
21 | 21 | ||
22 | Scenario: see link to invite friends in myprofile | 22 | Scenario: see link to invite friends in myprofile |
23 | When I am on /myprofile/josesilva/friends | 23 | When I am on /myprofile/josesilva/friends |
24 | - Then I should see "Invite people from my e-mail contacts" link | 24 | + Then I should see "Invite people" link |
25 | 25 | ||
26 | Scenario: go to invitation screen when follow link to invite friends | 26 | Scenario: go to invitation screen when follow link to invite friends |
27 | Given I am on /myprofile/josesilva/friends | 27 | Given I am on /myprofile/josesilva/friends |
28 | - When I follow "Invite people from my e-mail contacts" | 28 | + When I follow "Invite people" |
29 | Then I am on /profile/josesilva/invite/friends | 29 | Then I am on /profile/josesilva/invite/friends |
30 | 30 | ||
31 | - Scenario: see title when invite friends | ||
32 | - When I am on /profile/josesilva/invite/friends | ||
33 | - Then I should see "Invite your friends" | ||
34 | - | ||
35 | @selenium | 31 | @selenium |
36 | Scenario: back to friends after invite friends | 32 | Scenario: back to friends after invite friends |
37 | Given I am on /myprofile/josesilva/friends | 33 | Given I am on /myprofile/josesilva/friends |
38 | - And I follow "Invite people from my e-mail contacts" | 34 | + And I follow "Invite people" |
35 | + And I choose "Email" | ||
39 | And I press "Next" | 36 | And I press "Next" |
40 | And I fill in "manual_import_addresses" with "misfits@devil.doll" | 37 | And I fill in "manual_import_addresses" with "misfits@devil.doll" |
41 | And I follow "Personalize invitation mail" | 38 | And I follow "Personalize invitation mail" |
@@ -77,7 +74,8 @@ Feature: invitation | @@ -77,7 +74,8 @@ Feature: invitation | ||
77 | @selenium | 74 | @selenium |
78 | Scenario: back to members after invite friends to join a community | 75 | Scenario: back to members after invite friends to join a community |
79 | Given I am on 26 Bsslines's members management | 76 | Given I am on 26 Bsslines's members management |
80 | - And I follow "Invite your friends to join 26 Bsslines" | 77 | + And I follow "Invite people" |
78 | + And I choose "Email" | ||
81 | And I press "Next" | 79 | And I press "Next" |
82 | And I fill in "manual_import_addresses" with "misfits@devil.doll" | 80 | And I fill in "manual_import_addresses" with "misfits@devil.doll" |
83 | And I follow "Personalize invitation mail" | 81 | And I follow "Personalize invitation mail" |
@@ -88,7 +86,8 @@ Feature: invitation | @@ -88,7 +86,8 @@ Feature: invitation | ||
88 | @selenium | 86 | @selenium |
89 | Scenario: noosfero user receives a task when a user invites to join a community | 87 | Scenario: noosfero user receives a task when a user invites to join a community |
90 | Given I am on 26 Bsslines's members management | 88 | Given I am on 26 Bsslines's members management |
91 | - And I follow "Invite your friends to join 26 Bsslines" | 89 | + And I follow "Invite people" |
90 | + And I choose "Email" | ||
92 | And I press "Next" | 91 | And I press "Next" |
93 | And I fill in "manual_import_addresses" with "santos@invalid.br" | 92 | And I fill in "manual_import_addresses" with "santos@invalid.br" |
94 | And I follow "Personalize invitation mail" | 93 | And I follow "Personalize invitation mail" |
@@ -133,7 +132,8 @@ Feature: invitation | @@ -133,7 +132,8 @@ Feature: invitation | ||
133 | Scenario: noosfero user receives a task when a user invites to be friend | 132 | Scenario: noosfero user receives a task when a user invites to be friend |
134 | Given I am on josesilva's control panel | 133 | Given I am on josesilva's control panel |
135 | And I follow "Manage friends" | 134 | And I follow "Manage friends" |
136 | - And I follow "Invite people from my e-mail contacts" | 135 | + And I follow "Invite people" |
136 | + And I choose "Email" | ||
137 | And I press "Next" | 137 | And I press "Next" |
138 | And I fill in "manual_import_addresses" with "santos@invalid.br" | 138 | And I fill in "manual_import_addresses" with "santos@invalid.br" |
139 | And I follow "Personalize invitation mail" | 139 | And I follow "Personalize invitation mail" |
features/step_definitions/invitation_steps.rb
@@ -2,6 +2,7 @@ Given /^I invite email "(.+)" to join community "(.+)"$/ do |email, community| | @@ -2,6 +2,7 @@ Given /^I invite email "(.+)" to join community "(.+)"$/ do |email, community| | ||
2 | identifier = Community.find_by_name(community).identifier | 2 | identifier = Community.find_by_name(community).identifier |
3 | visit("/myprofile/#{identifier}/profile_members") | 3 | visit("/myprofile/#{identifier}/profile_members") |
4 | first(:link, "Invite your friends to join #{community}").click | 4 | first(:link, "Invite your friends to join #{community}").click |
5 | + choose("Email") | ||
5 | click_button('Next') | 6 | click_button('Next') |
6 | fill_in('manual_import_addresses', :with => "#{email}") | 7 | fill_in('manual_import_addresses', :with => "#{email}") |
7 | click_link('Personalize invitation mail') | 8 | click_link('Personalize invitation mail') |
@@ -11,7 +12,8 @@ end | @@ -11,7 +12,8 @@ end | ||
11 | 12 | ||
12 | Given /^I invite email "(.+)" to be my friend$/ do |email| | 13 | Given /^I invite email "(.+)" to be my friend$/ do |email| |
13 | click_link('Manage friends') | 14 | click_link('Manage friends') |
14 | - click_link('Invite people from my e-mail contacts') | 15 | + click_link('Invite people') |
16 | + choose("Email") | ||
15 | click_button('Next') | 17 | click_button('Next') |
16 | fill_in('manual_import_addresses', :with => "#{email}") | 18 | fill_in('manual_import_addresses', :with => "#{email}") |
17 | click_link('Personalize invitation mail') | 19 | click_link('Personalize invitation mail') |
@@ -0,0 +1,52 @@ | @@ -0,0 +1,52 @@ | ||
1 | +(function($){ | ||
2 | + 'use strict'; | ||
3 | + | ||
4 | + function toggle_invitation_method() { | ||
5 | + if (+(this.value) === 1) { | ||
6 | + $('.invite_by_email').hide(); | ||
7 | + $('.invite_by_name').show(); | ||
8 | + } else { | ||
9 | + $('.invite_by_name').hide(); | ||
10 | + $('.invite_by_email').show(); | ||
11 | + } | ||
12 | + } | ||
13 | + | ||
14 | + function manage_members_moderation() { | ||
15 | + var checked = $('#profile_data_allow_members_to_invite').is(':checked'); | ||
16 | + | ||
17 | + if (checked) { | ||
18 | + $('.invite_friends_only').show(); | ||
19 | + } else { | ||
20 | + $('.invite_friends_only').hide(); | ||
21 | + } | ||
22 | + } | ||
23 | + | ||
24 | + function hide_invite_friend_login_password() { | ||
25 | + $('#invite-friends-login-password').hide(); | ||
26 | + } | ||
27 | + | ||
28 | + function show_invite_friend_login_password() { | ||
29 | + if (this.value === 'hotmail') { | ||
30 | + $('#hotmail_username_tip').show(); | ||
31 | + } else { | ||
32 | + $('#hotmail_username_tip').hide(); | ||
33 | + } | ||
34 | + | ||
35 | + $('#invite-friends-login-password').show(); | ||
36 | + $('#login').focus(); | ||
37 | + } | ||
38 | + | ||
39 | + $(document).ready(function() { | ||
40 | + $('.invite_by_email').hide(); | ||
41 | + manage_members_moderation(); | ||
42 | + | ||
43 | + // Event triggers | ||
44 | + $('.invite_friend_by').click(toggle_invitation_method); | ||
45 | + | ||
46 | + $("#import_from_manual").click(hide_invite_friend_login_password); | ||
47 | + | ||
48 | + $('.invite_by_this_email').click(show_invite_friend_login_password); | ||
49 | + | ||
50 | + $('#profile_data_allow_members_to_invite').click(manage_members_moderation); | ||
51 | + }); | ||
52 | +})(jQuery); |
test/functional/invite_controller_test.rb
@@ -101,7 +101,6 @@ class InviteControllerTest < ActionController::TestCase | @@ -101,7 +101,6 @@ class InviteControllerTest < ActionController::TestCase | ||
101 | should 'display invitation page' do | 101 | should 'display invitation page' do |
102 | get :invite_friends, :profile => profile.identifier | 102 | get :invite_friends, :profile => profile.identifier |
103 | assert_response :success | 103 | assert_response :success |
104 | - assert_tag :tag => 'h1', :content => 'Invite your friends' | ||
105 | end | 104 | end |
106 | 105 | ||
107 | should 'get mail template to invite members' do | 106 | should 'get mail template to invite members' do |
@@ -243,18 +242,18 @@ class InviteControllerTest < ActionController::TestCase | @@ -243,18 +242,18 @@ class InviteControllerTest < ActionController::TestCase | ||
243 | friend1.save | 242 | friend1.save |
244 | friend2.save | 243 | friend2.save |
245 | 244 | ||
246 | - get :search_friend, :profile => profile.identifier, :q => 'me@' | 245 | + get :search, :profile => profile.identifier, :q => 'me@' |
247 | 246 | ||
248 | assert_equal 'text/html', @response.content_type | 247 | assert_equal 'text/html', @response.content_type |
249 | assert_equal [{"id" => friend2.id, "name" => friend2.name}].to_json, @response.body | 248 | assert_equal [{"id" => friend2.id, "name" => friend2.name}].to_json, @response.body |
250 | 249 | ||
251 | - get :search_friend, :profile => profile.identifier, :q => 'cri' | 250 | + get :search, :profile => profile.identifier, :q => 'cri' |
252 | 251 | ||
253 | assert_equal [{"id" => friend1.id, "name" => friend1.name}].to_json, @response.body | 252 | assert_equal [{"id" => friend1.id, "name" => friend1.name}].to_json, @response.body |
254 | 253 | ||
255 | - get :search_friend, :profile => profile.identifier, :q => 'will' | 254 | + get :search, :profile => profile.identifier, :q => 'will' |
256 | 255 | ||
257 | - assert_equal [{"id" => friend1.id, "name" => friend1.name}, {"id" => friend2.id, "name" => friend2.name}].to_json, @response.body | 256 | + assert_equivalent [{"id" => friend1.id, "name" => friend1.name}, {"id" => friend2.id, "name" => friend2.name}], json_response |
258 | end | 257 | end |
259 | 258 | ||
260 | should 'not include members in search friends profiles' do | 259 | should 'not include members in search friends profiles' do |
@@ -266,11 +265,25 @@ class InviteControllerTest < ActionController::TestCase | @@ -266,11 +265,25 @@ class InviteControllerTest < ActionController::TestCase | ||
266 | 265 | ||
267 | community.add_member(friend2) | 266 | community.add_member(friend2) |
268 | 267 | ||
269 | - get :search_friend, :profile => community.identifier, :q => 'will' | 268 | + get :search, :profile => community.identifier, :q => 'will' |
270 | 269 | ||
271 | assert_equivalent [{"name" => friend1.name, "id" => friend1.id}], json_response | 270 | assert_equivalent [{"name" => friend1.name, "id" => friend1.id}], json_response |
272 | end | 271 | end |
273 | 272 | ||
273 | + should 'not include friends in search for people to request friendship' do | ||
274 | + friend1 = create_user('willy').person | ||
275 | + friend2 = create_user('william').person | ||
276 | + | ||
277 | + profile.add_friend friend1 | ||
278 | + friend1.add_friend profile | ||
279 | + profile.add_friend friend2 | ||
280 | + friend2.add_friend profile | ||
281 | + | ||
282 | + get :search, :profile => profile.identifier, :q => 'will' | ||
283 | + | ||
284 | + assert_empty json_response | ||
285 | + end | ||
286 | + | ||
274 | should 'invite registered users through profile id' do | 287 | should 'invite registered users through profile id' do |
275 | friend1 = create_user('testuser1').person | 288 | friend1 = create_user('testuser1').person |
276 | friend2 = create_user('testuser2').person | 289 | friend2 = create_user('testuser2').person |