Commit ca285e1e979f3d756eee29a315ddfb6ef36bcb30
Committed by
Antonio Terceiro
1 parent
f9cb2dd4
Exists in
master
and in
29 other branches
fetching emails for invitation done in background
* Added message if user wants to fetch from hotmail * Added <url> to message if user removed it * Refactored invite_controller * Added ContactList * Added get_email_contacts_job * Added invitation_job (ActionItem1640)
Showing
27 changed files
with
566 additions
and
223 deletions
Show diff stats
app/controllers/public/invite_controller.rb
@@ -2,42 +2,57 @@ class InviteController < PublicController | @@ -2,42 +2,57 @@ class InviteController < PublicController | ||
2 | 2 | ||
3 | needs_profile | 3 | needs_profile |
4 | before_filter :login_required | 4 | before_filter :login_required |
5 | - before_filter :check_permissions_to_invite, :only => 'friends' | 5 | + before_filter :check_permissions_to_invite |
6 | 6 | ||
7 | - def friends | ||
8 | - step = params[:step] | 7 | + def select_address_book |
8 | + @import_from = params[:import_from] || "manual" | ||
9 | if request.post? | 9 | if request.post? |
10 | - if step == '1' | ||
11 | - begin | ||
12 | - @contacts = Invitation.get_contacts(params[:import_from], params[:login], params[:password]) | ||
13 | - rescue | ||
14 | - @login = params[:login] | ||
15 | - flash.now[:notice] = _('There was an error while looking for your contact list. Did you enter correct login and password?') | ||
16 | - end | ||
17 | - elsif step == '2' | ||
18 | - manual_import_addresses = params[:manual_import_addresses] | ||
19 | - webmail_import_addresses = params[:webmail_import_addresses] | ||
20 | - contacts_to_invite = Invitation.join_contacts(manual_import_addresses, webmail_import_addresses) | ||
21 | - if !params[:mail_template].match(/<url>/) | ||
22 | - flash.now[:notice] = _('<url> is needed in invitation mail.') | ||
23 | - elsif !contacts_to_invite.empty? | ||
24 | - Delayed::Job.enqueue InvitationJob.new(user.id, contacts_to_invite, params[:mail_template], profile.id) | ||
25 | - session[:notice] = _('Your invitations are being sent.') | ||
26 | - if profile.person? | ||
27 | - redirect_to :controller => 'friends' | ||
28 | - else | ||
29 | - redirect_to :controller => 'profile_members' | ||
30 | - end | 10 | + contact_list = ContactList.create |
11 | + Delayed::Job.enqueue GetEmailContactsJob.new(@import_from, params[:login], params[:password], contact_list.id) if @import_from != 'manual' | ||
12 | + redirect_to :action => 'select_friends', :contact_list => contact_list.id, :import_from => @import_from | ||
13 | + end | ||
14 | + end | ||
15 | + | ||
16 | + def select_friends | ||
17 | + @contact_list = ContactList.find(params[:contact_list]) | ||
18 | + @mail_template = params[:mail_template] || environment.invitation_mail_template(profile) | ||
19 | + @import_from = params[:import_from] || "manual" | ||
20 | + if request.post? | ||
21 | + manual_import_addresses = params[:manual_import_addresses] | ||
22 | + webmail_import_addresses = params[:webmail_import_addresses] | ||
23 | + contacts_to_invite = Invitation.join_contacts(manual_import_addresses, webmail_import_addresses) | ||
24 | + if !contacts_to_invite.empty? | ||
25 | + Delayed::Job.enqueue InvitationJob.new(current_user.person.id, contacts_to_invite, params[:mail_template], profile.id, @contact_list.id) | ||
26 | + session[:notice] = _('Your invitations are being sent.') | ||
27 | + if profile.person? | ||
28 | + redirect_to :controller => 'profile', :action => 'friends' | ||
31 | else | 29 | else |
32 | - flash.now[:notice] = _('Please enter a valid email address.') | 30 | + redirect_to :controller => 'profile', :action => 'members' |
33 | end | 31 | end |
34 | - @contacts = params[:webmail_friends] ? params[:webmail_friends].map {|e| YAML.load(e)} : [] | ||
35 | - @manual_import_addresses = manual_import_addresses || "" | ||
36 | - @webmail_import_addresses = webmail_import_addresses || [] | 32 | + return |
33 | + else | ||
34 | + session[:notice] = _('Please enter a valid email address.') | ||
37 | end | 35 | end |
36 | + @manual_import_addresses = manual_import_addresses || "" | ||
37 | + @webmail_import_addresses = webmail_import_addresses || [] | ||
38 | end | 38 | end |
39 | - @import_from = params[:import_from] || "manual" | ||
40 | - @mail_template = params[:mail_template] || environment.invitation_mail_template(profile) | 39 | + end |
40 | + | ||
41 | + def invitation_data | ||
42 | + contact_list = ContactList.find(params[:contact_list]) | ||
43 | + render :text => contact_list.data.to_json, :layout => false, :content_type => "application/javascript" | ||
44 | + end | ||
45 | + | ||
46 | + def add_contact_list | ||
47 | + contact_list = ContactList.find(params[:contact_list]) | ||
48 | + contacts = contact_list.list | ||
49 | + render :partial => 'invite/contact_list', :locals => {:contacts => contacts} | ||
50 | + end | ||
51 | + | ||
52 | + def cancel_fetching_emails | ||
53 | + contact_list = ContactList.find(params[:contact_list]) | ||
54 | + contact_list.destroy | ||
55 | + redirect_to :action => 'select_address_book' | ||
41 | end | 56 | end |
42 | 57 | ||
43 | protected | 58 | protected |
@@ -0,0 +1,27 @@ | @@ -0,0 +1,27 @@ | ||
1 | +class ContactList < ActiveRecord::Base | ||
2 | + | ||
3 | + serialize :list, Array | ||
4 | + | ||
5 | + def list | ||
6 | + self[:list] || [] | ||
7 | + end | ||
8 | + | ||
9 | + def data | ||
10 | + if self.fetched | ||
11 | + { "fetched" => true, "contact_list" => self.id, "error" => self.error_fetching } | ||
12 | + else | ||
13 | + {} | ||
14 | + end | ||
15 | + end | ||
16 | + | ||
17 | + def register_auth_error | ||
18 | + msg = _('There was an error while authenticating. Did you enter correct login and password?') | ||
19 | + self.update_attributes(:fetched => true, :error_fetching => msg) | ||
20 | + end | ||
21 | + | ||
22 | + def register_error | ||
23 | + msg = _('There was an error while looking for your contact list. Please, try again') | ||
24 | + self.update_attributes(:fetched => true, :error_fetching => msg) | ||
25 | + end | ||
26 | + | ||
27 | +end |
app/models/invitation.rb
@@ -11,7 +11,6 @@ class Invitation < Task | @@ -11,7 +11,6 @@ class Invitation < Task | ||
11 | validates_format_of :friend_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => Proc.new{|invite| invite.target_id.blank?} | 11 | validates_format_of :friend_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => Proc.new{|invite| invite.target_id.blank?} |
12 | 12 | ||
13 | validates_presence_of :message, :if => Proc.new{|invite| invite.target_id.blank?} | 13 | validates_presence_of :message, :if => Proc.new{|invite| invite.target_id.blank?} |
14 | - validates_format_of :message, :with => /<url>/, :if => Proc.new{|invite| invite.target_id.blank?} | ||
15 | 14 | ||
16 | alias :person :requestor | 15 | alias :person :requestor |
17 | alias :person= :requestor= | 16 | alias :person= :requestor= |
@@ -19,6 +18,12 @@ class Invitation < Task | @@ -19,6 +18,12 @@ class Invitation < Task | ||
19 | alias :friend :target | 18 | alias :friend :target |
20 | alias :friend= :target= | 19 | alias :friend= :target= |
21 | 20 | ||
21 | + before_create do |task| | ||
22 | + if task.message && !task.message.match(/<url>/) | ||
23 | + task.message += task.message_to_accept_invitation | ||
24 | + end | ||
25 | + end | ||
26 | + | ||
22 | after_create do |task| | 27 | after_create do |task| |
23 | TaskMailer.deliver_invitation_notification(task) unless task.friend | 28 | TaskMailer.deliver_invitation_notification(task) unless task.friend |
24 | end | 29 | end |
@@ -72,21 +77,26 @@ class Invitation < Task | @@ -72,21 +77,26 @@ class Invitation < Task | ||
72 | end | 77 | end |
73 | end | 78 | end |
74 | 79 | ||
75 | - def self.get_contacts(source, login, password) | ||
76 | - contacts = [] | 80 | + def self.get_contacts(source, login, password, contact_list_id) |
81 | + contact_list = ContactList.find(contact_list_id) | ||
77 | case source | 82 | case source |
78 | when "gmail" | 83 | when "gmail" |
79 | - contacts = Contacts::Gmail.new(login, password).contacts | 84 | + email_service = Contacts::Gmail.new(login, password) |
80 | when "yahoo" | 85 | when "yahoo" |
81 | - contacts = Contacts::Yahoo.new(login, password).contacts | 86 | + email_service = Contacts::Yahoo.new(login, password) |
82 | when "hotmail" | 87 | when "hotmail" |
83 | - contacts = Contacts::Hotmail.new(login, password).contacts | 88 | + email_service = Contacts::Hotmail.new(login, password) |
84 | when "manual" | 89 | when "manual" |
85 | #do nothing | 90 | #do nothing |
86 | else | 91 | else |
87 | raise NotImplementedError, 'Unknown source to get contacts' | 92 | raise NotImplementedError, 'Unknown source to get contacts' |
88 | end | 93 | end |
89 | - contacts.map { |contact| contact + ["#{contact[0]} <#{contact[1]}>"] } | 94 | + if email_service |
95 | + contact_list.list = email_service.contacts.map { |contact| contact + ["#{contact[0]} <#{contact[1]}>"] } | ||
96 | + contact_list.fetched = true | ||
97 | + contact_list.save | ||
98 | + end | ||
99 | + contact_list.list | ||
90 | end | 100 | end |
91 | 101 | ||
92 | def self.join_contacts(manual_import_addresses, webmail_import_addresses) | 102 | def self.join_contacts(manual_import_addresses, webmail_import_addresses) |
@@ -112,4 +122,7 @@ class Invitation < Task | @@ -112,4 +122,7 @@ class Invitation < Task | ||
112 | raise 'You should implement mail_template in a subclass' | 122 | raise 'You should implement mail_template in a subclass' |
113 | end | 123 | end |
114 | 124 | ||
125 | + def message_to_accept_invitation | ||
126 | + '<p>' + _('To accept invitation, please follow this link: <url>') + '</p>' | ||
127 | + end | ||
115 | end | 128 | end |
app/views/friends/index.rhtml
@@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
14 | <% button_bar do %> | 14 | <% button_bar do %> |
15 | <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> | 15 | <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> |
16 | <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> | 16 | <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> |
17 | - <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'friends') %> | 17 | + <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'select_address_book') %> |
18 | <% end %> | 18 | <% end %> |
19 | <% end %> | 19 | <% end %> |
20 | 20 | ||
@@ -40,11 +40,11 @@ | @@ -40,11 +40,11 @@ | ||
40 | <%= pagination_links @friends, :param_name => 'npage' %> | 40 | <%= pagination_links @friends, :param_name => 'npage' %> |
41 | </div> | 41 | </div> |
42 | 42 | ||
43 | -<% button_bar do %> | ||
44 | - <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> | ||
45 | - <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> | ||
46 | - <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'friends') %> | ||
47 | -<% end %> | 43 | + <% button_bar do %> |
44 | + <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> | ||
45 | + <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> | ||
46 | + <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'select_address_book') %> | ||
47 | + <% end %> | ||
48 | <% end %> | 48 | <% end %> |
49 | 49 | ||
50 | </div><!-- end id="manage_friends" --> | 50 | </div><!-- end id="manage_friends" --> |
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +<% friend_pos = 0 %> | ||
2 | +<% contacts.each do |contact| %> | ||
3 | + <% friend_pos += 1 %> | ||
4 | + <p> | ||
5 | + <%= check_box_tag("webmail_import_addresses[]", contact[2], | ||
6 | + (!@webmail_import_addresses || @webmail_import_addresses.include?(contact[2])), | ||
7 | + :id => "contacts_to_invite_#{friend_pos}", | ||
8 | + :class => "contact_to_invite" ) | ||
9 | + %> | ||
10 | + <label for="<%= "contacts_to_invite_#{friend_pos}" %>"><%= "#{contact[0]} (#{contact[1]})" %></label> | ||
11 | + </p> | ||
12 | +<% end %> |
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +<% javascript_tag do %> | ||
2 | + jQuery(function($) { | ||
3 | + $("#loading-dialog").dialog({ | ||
4 | + height: 160, | ||
5 | + width: 450, | ||
6 | + modal: true, | ||
7 | + resizable: false, | ||
8 | + title: "<%= ui_icon('ui-icon-info') + _('Please, wait...') %>", | ||
9 | + open: check_contact_list('<%= contact_list.to_s %>'), | ||
10 | + }); | ||
11 | + }); | ||
12 | +<% end %> | ||
13 | + | ||
14 | + | ||
15 | +<div id="loading-dialog"> | ||
16 | + <p><%= _('Your e-mails contacts are being fetched') %></p> | ||
17 | + <p><%= _('If it takes too long, you will be redirected to the previous page to try again. Be sure to fill in the fields with your correct login and password.') %> | ||
18 | + <span class='loading-message'/> | ||
19 | + <%= link_to(_('Verify contact list'), {:action => 'invitation_data', :contact_list => @contact_list}, :id => "verify-contact-list", :style => 'display:none') %> | ||
20 | + <%= link_to(_('Add contact list'), {:action => 'add_contact_list', :contact_list => @contact_list}, :id => "add-contact-list", :style => 'display:none') %> | ||
21 | + <%= link_to(_('Cancel fetching e-mails'), {:action => 'cancel_fetching_emails', :contact_list => @contact_list}, :id => "cancel-fetching-emails", :style => 'display:none') %> | ||
22 | +</div> | ||
23 | + |
app/views/invite/friends.rhtml
@@ -1,93 +0,0 @@ | @@ -1,93 +0,0 @@ | ||
1 | -<% if profile.person? %> | ||
2 | - <h1><%= _('Invite your friends') %></h1> | ||
3 | -<% else %> | ||
4 | - <h1><%= _('Invite your friends to join %s') % profile.name %></h1> | ||
5 | -<% end %> | ||
6 | - | ||
7 | -<% unless @contacts %> | ||
8 | - | ||
9 | - <h2><%= _('Step 1 of 2: Select address book') %></h2> | ||
10 | - | ||
11 | - <% form_tag do %> | ||
12 | - <%= hidden_field_tag(:step, 1) %> | ||
13 | - | ||
14 | - <%= [ | ||
15 | - radio_button_tag(:import_from, "manual", @import_from == "manual", :onclick => 'hide_invite_friend_login_password()') + content_tag('label', _('Manually (empty field)'), :for => "import_from_manual"), | ||
16 | - radio_button_tag(:import_from, "gmail", @import_from == "gmail", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Gmail', :for => 'import_from_gmail'), | ||
17 | - radio_button_tag(:import_from, "yahoo", @import_from == "yahoo", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Yahoo', :for => "import_from_yahoo"), | ||
18 | - radio_button_tag(:import_from, "hotmail", @import_from == "hotmail", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Hotmail', :for => "import_from_hotmail") | ||
19 | - ].join("\n<br/>\n") %> | ||
20 | - | ||
21 | - <script type="text/javascript"> | ||
22 | - function hide_invite_friend_login_password() { | ||
23 | - $('invite-friends-login-password').hide(); | ||
24 | - } | ||
25 | - function show_invite_friend_login_password() { | ||
26 | - $('invite-friends-login-password').show(); | ||
27 | - $('login').focus(); | ||
28 | - } | ||
29 | - </script> | ||
30 | - <div id='invite-friends-login-password' <%= "style='display: none;'" if (@import_from == 'manual') %>> | ||
31 | - <%= labelled_form_field(_("Username") + ":", text_field_tag(:login, @login)) %> | ||
32 | - <%= labelled_form_field(_("Password") + ":", password_field_tag(:password)) %> | ||
33 | - </div> | ||
34 | - | ||
35 | - <% button_bar do %> | ||
36 | - <%= submit_button(:forward, _("Next")) %> | ||
37 | - <% end %> | ||
38 | - <p><%= _("We won't store your password or contact anyone without your permission.") %></p> | ||
39 | - <% end %> | ||
40 | - | ||
41 | -<% else %> | ||
42 | - | ||
43 | - <h2><%= _('Step 2 of 2: Selecting Friends') %></h2> | ||
44 | - <p> | ||
45 | - <%= _('Indicate which friends you want to invite.') %> | ||
46 | - </p> | ||
47 | - | ||
48 | - <% form_tag do %> | ||
49 | - <%= hidden_field_tag(:step, 2) %> | ||
50 | - <%= hidden_field_tag(:import_from, @import_from) %> | ||
51 | - | ||
52 | - <div> | ||
53 | - <%= labelled_form_field(_('Enter one e-mail address per line:'), text_area_tag(:manual_import_addresses, (@manual_import_addresses || ''), :cols => 72, :rows => 5)) %> | ||
54 | - </div> | ||
55 | - <% if @import_from != 'manual' %> | ||
56 | - <div> | ||
57 | - <%= link_to_function _('Check all'), "$$('input.contact_to_invite').each(function(checkbox) { checkbox.checked = true; });" %> | ||
58 | - <%= link_to_function _('Uncheck all'), "$$('input.contact_to_invite').each(function(checkbox) { checkbox.checked = false; });" %> | ||
59 | - <% friend_pos = 0 %> | ||
60 | - <div id='contacts-list'> | ||
61 | - <% @contacts.each do |contact| %> | ||
62 | - <% friend_pos += 1 %> | ||
63 | - <p> | ||
64 | - <%= hidden_field_tag("webmail_friends[]", contact.to_yaml) %> | ||
65 | - <%= check_box_tag("webmail_import_addresses[]", contact[2], | ||
66 | - (!@webmail_import_addresses || @webmail_import_addresses.include?(contact[2])), | ||
67 | - :id => "contacts_to_invite_#{friend_pos}", | ||
68 | - :class => "contact_to_invite" ) | ||
69 | - %> | ||
70 | - <label for="<%= "contacts_to_invite_#{friend_pos}" %>"><%= "#{contact[0]} (#{contact[1]})" %></label> | ||
71 | - </p> | ||
72 | - <% end %> | ||
73 | - </div> | ||
74 | - </div> | ||
75 | - <% end -%> | ||
76 | - | ||
77 | - <br/> | ||
78 | - | ||
79 | - <%= link_to_function(_('Personalize invitation mail'), nil) do |page| | ||
80 | - page['invitation-mail_template'].show | ||
81 | - end %> | ||
82 | - | ||
83 | - <div id='invitation-mail_template' style='display:none'> | ||
84 | - <%= h _("Now enter an invitation message. You must keep the <url> code in your invitation text. When your friends receive the invitation e-mail, <url> will be replaced by a link that they need to click to activate their account. <user> and <friend> codes will be replaced by your name and friend name, but they are optional.") %> | ||
85 | - <%= labelled_form_field(_('Invitation text:'), text_area_tag(:mail_template, @mail_template, :cols => 72, :rows => 8)) %> | ||
86 | - </div> | ||
87 | - | ||
88 | - <% button_bar do %> | ||
89 | - <%= submit_button(:ok, _("Invite my friends!")) %> | ||
90 | - <% end %> | ||
91 | - <% end %> | ||
92 | - | ||
93 | -<% end %> |
@@ -0,0 +1,51 @@ | @@ -0,0 +1,51 @@ | ||
1 | +<% if profile.person? %> | ||
2 | + <h1><%= _('Invite your friends') %></h1> | ||
3 | +<% else %> | ||
4 | + <h1><%= _('Invite your friends to join %s') % profile.name %></h1> | ||
5 | +<% end %> | ||
6 | + | ||
7 | +<h2><%= _('Step 1 of 2: Select address book') %></h2> | ||
8 | + | ||
9 | +<% form_tag do %> | ||
10 | + | ||
11 | + <%= [ | ||
12 | + radio_button_tag(:import_from, "manual", @import_from == "manual", :onclick => 'hide_invite_friend_login_password()') + content_tag('label', _('Manually (empty field)'), :for => "import_from_manual"), | ||
13 | + radio_button_tag(:import_from, "gmail", @import_from == "gmail", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Gmail', :for => 'import_from_gmail'), | ||
14 | + radio_button_tag(:import_from, "yahoo", @import_from == "yahoo", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Yahoo', :for => "import_from_yahoo"), | ||
15 | + radio_button_tag(:import_from, "hotmail", @import_from == "hotmail", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Hotmail', :for => "import_from_hotmail") | ||
16 | + ].join("\n<br/>\n") %> | ||
17 | + | ||
18 | + <script type="text/javascript"> | ||
19 | + function hide_invite_friend_login_password() { | ||
20 | + $('invite-friends-login-password').hide(); | ||
21 | + } | ||
22 | + function show_invite_friend_login_password(option) { | ||
23 | + if (option == 'hotmail') { | ||
24 | + $('hotmail_username_tip').show(); | ||
25 | + } else { | ||
26 | + $('hotmail_username_tip').hide(); | ||
27 | + } | ||
28 | + $('invite-friends-login-password').show(); | ||
29 | + $('login').focus(); | ||
30 | + } | ||
31 | + </script> | ||
32 | + <div id='invite-friends-login-password' <%= "style='display: none;'" if (@import_from == 'manual') %>> | ||
33 | + <div id='hotmail_username_tip'> | ||
34 | + <%= ui_icon('ui-icon-alert') %> | ||
35 | + <%= _('Please type your username in the format yourname@example.com') %> | ||
36 | + </div> | ||
37 | + | ||
38 | + <%= labelled_form_field(_("Username") + ":", text_field_tag(:login, @login)) %> | ||
39 | + <%= labelled_form_field(_("Password") + ":", password_field_tag(:password)) %> | ||
40 | + </div> | ||
41 | + | ||
42 | + <% button_bar do %> | ||
43 | + <%= submit_button(:forward, _("Next")) %> | ||
44 | + <% end %> | ||
45 | + <p><%= _("We won't store your password or contact anyone without your permission.") %></p> | ||
46 | +<% end %> | ||
47 | + | ||
48 | +<div id="loadingScreen"></div> | ||
49 | + | ||
50 | + | ||
51 | + |
@@ -0,0 +1,47 @@ | @@ -0,0 +1,47 @@ | ||
1 | +<%= render :partial => 'invite/dialog_wait_loading', :locals => {:contact_list => @contact_list.id } if @import_from != 'manual' %> | ||
2 | + | ||
3 | +<% if profile.person? %> | ||
4 | + <h1><%= _('Invite your friends') %></h1> | ||
5 | +<% else %> | ||
6 | + <h1><%= _('Invite your friends to join %s') % profile.name %></h1> | ||
7 | +<% end %> | ||
8 | + | ||
9 | + | ||
10 | +<h2><%= _('Step 2 of 2: Selecting Friends') %></h2> | ||
11 | + | ||
12 | +<%= button(:back, _('Back'), { :action => 'select_address_book' }, :id => 'invitation_back_button') %> | ||
13 | + | ||
14 | +<p> | ||
15 | +<%= _('Indicate which friends you want to invite.') %> | ||
16 | +</p> | ||
17 | + | ||
18 | +<% form_tag do %> | ||
19 | + <%= hidden_field_tag(:import_from, @import_from) %> | ||
20 | + <%= hidden_field_tag(:contact_list, @contact_list.id) %> | ||
21 | + | ||
22 | + <div> | ||
23 | + <%= labelled_form_field(_('Enter one e-mail address per line:'), text_area_tag(:manual_import_addresses, (@manual_import_addresses || ''), :cols => 72, :rows => 5)) %> | ||
24 | + </div> | ||
25 | + <% if @import_from != 'manual' %> | ||
26 | + <div> | ||
27 | + <%= link_to_function _('Check all'), "$$('input.contact_to_invite').each(function(checkbox) { checkbox.checked = true; });" %> | ||
28 | + <%= link_to_function _('Uncheck all'), "$$('input.contact_to_invite').each(function(checkbox) { checkbox.checked = false; });" %> | ||
29 | + <div id='contacts-list'></div> | ||
30 | + </div> | ||
31 | + <% end -%> | ||
32 | + | ||
33 | + <br/> | ||
34 | + | ||
35 | + <%= link_to_function(_('Personalize invitation mail'), nil) do |page| | ||
36 | + page['invitation-mail_template'].show | ||
37 | + end %> | ||
38 | + | ||
39 | + <div id='invitation-mail_template' style='display:none'> | ||
40 | + <%= h _("Now enter an invitation message. You must keep the <url> code in your invitation text. When your friends receive the invitation e-mail, <url> will be replaced by a link that they need to click to activate their account. <user> and <friend> codes will be replaced by your name and friend name, but they are optional.") %> | ||
41 | + <%= labelled_form_field(_('Invitation text:'), text_area_tag(:mail_template, @mail_template, :cols => 72, :rows => 8)) %> | ||
42 | + </div> | ||
43 | + | ||
44 | + <% button_bar do %> | ||
45 | + <%= submit_button(:ok, _("Invite my friends!")) %> | ||
46 | + <% end %> | ||
47 | +<% end %> |
app/views/profile/friends.rhtml
@@ -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 => 'friends') %> | 21 | + <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'select_address_book') %> |
22 | <% end %> | 22 | <% end %> |
23 | <% end %> | 23 | <% end %> |
24 | 24 |
app/views/profile/members.rhtml
@@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
17 | <% button_bar do %> | 17 | <% button_bar do %> |
18 | <%= button :back, _('Go back'), { :controller => 'profile' } %> | 18 | <%= button :back, _('Go back'), { :controller => 'profile' } %> |
19 | <% if profile.community? and user and user.has_permission?(:invite_members, profile) %> | 19 | <% if profile.community? and user and user.has_permission?(:invite_members, profile) %> |
20 | - <%= button :search, _('Invite your friends to join %s') % profile.name, :controller => 'invite', :action => 'friends' %> | 20 | + <%= button :search, _('Invite your friends to join %s') % profile.name, :controller => 'invite', :action => 'selects_address_book' %> |
21 | <% end %> | 21 | <% end %> |
22 | <% end %> | 22 | <% end %> |
23 | 23 |
app/views/profile_members/index.rhtml
@@ -6,6 +6,6 @@ | @@ -6,6 +6,6 @@ | ||
6 | <%= button :back, _('Back'), :controller => 'profile_editor' %> | 6 | <%= button :back, _('Back'), :controller => 'profile_editor' %> |
7 | <%= button :add, _('Add members'), :action => 'add_members' if profile.enterprise? %> | 7 | <%= button :add, _('Add members'), :action => 'add_members' if profile.enterprise? %> |
8 | <% if profile.community? and user.has_permission?(:invite_members, profile) %> | 8 | <% if profile.community? and user.has_permission?(:invite_members, profile) %> |
9 | - <%= button :search, _('Invite your friends to join %s') % profile.name, :controller => 'invite', :action => 'friends' %> | 9 | + <%= button :search, _('Invite your friends to join %s') % profile.name, :controller => 'invite', :action => 'select_address_book' %> |
10 | <% end %> | 10 | <% end %> |
11 | <% end %> | 11 | <% end %> |
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +class CreateContactLists < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :contact_lists do |t| | ||
4 | + t.text :list | ||
5 | + t.string :error_fetching | ||
6 | + t.boolean :fetched, :default => false | ||
7 | + t.timestamps | ||
8 | + end | ||
9 | + end | ||
10 | + | ||
11 | + def self.down | ||
12 | + drop_table :contact_lists | ||
13 | + end | ||
14 | +end |
db/schema.rb
@@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
9 | # | 9 | # |
10 | # It's strongly recommended to check this file into your version control system. | 10 | # It's strongly recommended to check this file into your version control system. |
11 | 11 | ||
12 | -ActiveRecord::Schema.define(:version => 20100822034415) do | 12 | +ActiveRecord::Schema.define(:version => 20100823190348) do |
13 | 13 | ||
14 | create_table "article_versions", :force => true do |t| | 14 | create_table "article_versions", :force => true do |t| |
15 | t.integer "article_id" | 15 | t.integer "article_id" |
@@ -145,9 +145,9 @@ ActiveRecord::Schema.define(:version => 20100822034415) do | @@ -145,9 +145,9 @@ ActiveRecord::Schema.define(:version => 20100822034415) do | ||
145 | t.string "name", :null => false | 145 | t.string "name", :null => false |
146 | t.string "description" | 146 | t.string "description" |
147 | t.string "link" | 147 | t.string "link" |
148 | + t.integer "environment_id" | ||
148 | t.datetime "created_at" | 149 | t.datetime "created_at" |
149 | t.datetime "updated_at" | 150 | t.datetime "updated_at" |
150 | - t.integer "environment_id" | ||
151 | end | 151 | end |
152 | 152 | ||
153 | create_table "comments", :force => true do |t| | 153 | create_table "comments", :force => true do |t| |
@@ -160,6 +160,14 @@ ActiveRecord::Schema.define(:version => 20100822034415) do | @@ -160,6 +160,14 @@ ActiveRecord::Schema.define(:version => 20100822034415) do | ||
160 | t.datetime "created_at" | 160 | t.datetime "created_at" |
161 | end | 161 | end |
162 | 162 | ||
163 | + create_table "contact_lists", :force => true do |t| | ||
164 | + t.text "list" | ||
165 | + t.string "error_fetching" | ||
166 | + t.boolean "fetched", :default => false | ||
167 | + t.datetime "created_at" | ||
168 | + t.datetime "updated_at" | ||
169 | + end | ||
170 | + | ||
163 | create_table "delayed_jobs", :force => true do |t| | 171 | create_table "delayed_jobs", :force => true do |t| |
164 | t.integer "priority", :default => 0 | 172 | t.integer "priority", :default => 0 |
165 | t.integer "attempts", :default => 0 | 173 | t.integer "attempts", :default => 0 |
@@ -351,9 +359,9 @@ ActiveRecord::Schema.define(:version => 20100822034415) do | @@ -351,9 +359,9 @@ ActiveRecord::Schema.define(:version => 20100822034415) do | ||
351 | 359 | ||
352 | create_table "roles", :force => true do |t| | 360 | create_table "roles", :force => true do |t| |
353 | t.string "name" | 361 | t.string "name" |
362 | + t.text "permissions" | ||
354 | t.string "key" | 363 | t.string "key" |
355 | t.boolean "system", :default => false | 364 | t.boolean "system", :default => false |
356 | - t.text "permissions" | ||
357 | t.integer "environment_id" | 365 | t.integer "environment_id" |
358 | end | 366 | end |
359 | 367 |
features/invitation.feature
@@ -32,15 +32,14 @@ Feature: invitation | @@ -32,15 +32,14 @@ Feature: invitation | ||
32 | When I am on /profile/josesilva/invite/friends | 32 | When I am on /profile/josesilva/invite/friends |
33 | Then I should see "Invite your friends" | 33 | Then I should see "Invite your friends" |
34 | 34 | ||
35 | - # why not work? | ||
36 | - Scenario: back to manage friends after invite friends | 35 | + Scenario: back to friends after invite friends |
37 | Given I am on /myprofile/josesilva/friends | 36 | Given I am on /myprofile/josesilva/friends |
38 | And I follow "Invite people from my e-mail contacts" | 37 | And I follow "Invite people from my e-mail contacts" |
39 | And I press "Next" | 38 | And I press "Next" |
40 | And I fill in "manual_import_addresses" with "misfits@devil.doll" | 39 | And I fill in "manual_import_addresses" with "misfits@devil.doll" |
41 | And I fill in "mail_template" with "Follow this link <url>" | 40 | And I fill in "mail_template" with "Follow this link <url>" |
42 | When I press "Invite my friends!" | 41 | When I press "Invite my friends!" |
43 | - Then I should be on /myprofile/josesilva/friends | 42 | + Then I should be on /profile/josesilva/friends |
44 | 43 | ||
45 | Scenario: see link to invite members to community | 44 | Scenario: see link to invite members to community |
46 | When I am on /profile/26-bsslines/members | 45 | When I am on /profile/26-bsslines/members |
@@ -75,14 +74,14 @@ Feature: invitation | @@ -75,14 +74,14 @@ Feature: invitation | ||
75 | Given I am on Beatles For Sale's members management | 74 | Given I am on Beatles For Sale's members management |
76 | Then I should not see "Invite your friends to join Beatles For Sale" link | 75 | Then I should not see "Invite your friends to join Beatles For Sale" link |
77 | 76 | ||
78 | - Scenario: back to manage members after invite friends | 77 | + Scenario: back to members after invite friends to join a community |
79 | Given I am on 26 Bsslines's members management | 78 | Given I am on 26 Bsslines's members management |
80 | And I follow "Invite your friends to join 26 Bsslines" | 79 | And I follow "Invite your friends to join 26 Bsslines" |
81 | And I press "Next" | 80 | And I press "Next" |
82 | And I fill in "manual_import_addresses" with "misfits@devil.doll" | 81 | And I fill in "manual_import_addresses" with "misfits@devil.doll" |
83 | And I fill in "mail_template" with "Follow this link <url>" | 82 | And I fill in "mail_template" with "Follow this link <url>" |
84 | When I press "Invite my friends!" | 83 | When I press "Invite my friends!" |
85 | - Then I should be on /myprofile/26-bsslines/profile_members | 84 | + Then I should be on /profile/26-bsslines/members |
86 | 85 | ||
87 | Scenario: noosfero user receives a task when a user invites to join a community | 86 | Scenario: noosfero user receives a task when a user invites to join a community |
88 | Given I am on 26 Bsslines's members management | 87 | Given I am on 26 Bsslines's members management |
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +class GetEmailContactsJob < Struct.new(:import_from, :login, :password, :contact_list_id) | ||
2 | + def perform | ||
3 | + begin | ||
4 | + Invitation.get_contacts(import_from, login, password, contact_list_id) | ||
5 | + rescue Contacts::AuthenticationError => ex | ||
6 | + ContactList.find(contact_list_id).register_auth_error | ||
7 | + rescue Exception => ex | ||
8 | + ContactList.find(contact_list_id).register_error | ||
9 | + end | ||
10 | + end | ||
11 | +end |
lib/invitation_job.rb
1 | -class InvitationJob < Struct.new(:person_id, :contacts_to_invite, :message, :profile_id) | 1 | +class InvitationJob < Struct.new(:person_id, :contacts_to_invite, :message, :profile_id, :contact_list_id) |
2 | def perform | 2 | def perform |
3 | begin | 3 | begin |
4 | - person = Person.find(person_id) | ||
5 | - profile = Profile.find(profile_id) | ||
6 | - Invitation.invite(person, contacts_to_invite, message, profile) | 4 | + person = Person.find(person_id) |
5 | + profile = Profile.find(profile_id) | ||
6 | + Invitation.invite(person, contacts_to_invite, message, profile) | ||
7 | + ContactList.find(contact_list_id).destroy | ||
7 | rescue ActiveRecord::NotFound => e | 8 | rescue ActiveRecord::NotFound => e |
8 | - # ... | 9 | + #... |
9 | end | 10 | end |
10 | end | 11 | end |
11 | end | 12 | end |
public/javascripts/application.js
@@ -455,9 +455,46 @@ jQuery(function($) { | @@ -455,9 +455,46 @@ jQuery(function($) { | ||
455 | $('#user .not-logged-in, .login-block .not-logged-user').fadeIn(); | 455 | $('#user .not-logged-in, .login-block .not-logged-user').fadeIn(); |
456 | } | 456 | } |
457 | if (data.notice) { | 457 | if (data.notice) { |
458 | - var $noticeBox = $('<div id="notice"></div>').html(data.notice).appendTo('body').fadeTo('fast', 0.8); | ||
459 | - $noticeBox.click(function() { $(this).hide(); }); | ||
460 | - setTimeout(function() { $noticeBox.fadeOut('fast'); }, 5000); | 458 | + display_notice(data.notice); |
461 | } | 459 | } |
462 | }); | 460 | }); |
463 | }); | 461 | }); |
462 | + | ||
463 | +// controls the display of contact list | ||
464 | +function check_contact_list(contact_list) { | ||
465 | + jQuery(function($) { | ||
466 | + var verify_url = $('#verify-contact-list').attr('href'); | ||
467 | + var add_contacts_url = $('#add-contact-list').attr('href'); | ||
468 | + var cancel_contacts_fetching_url = $('#cancel-fetching-emails').attr('href'); | ||
469 | + var interval = setInterval(function() { | ||
470 | + $.getJSON(verify_url, function(data) { | ||
471 | + if (data.fetched) { | ||
472 | + clearInterval(interval); | ||
473 | + if (data.error) { | ||
474 | + $("#loading-dialog").dialog('close'); | ||
475 | + $.get(cancel_contacts_fetching_url); | ||
476 | + redirect_to($('#invitation_back_button').attr('href')); | ||
477 | + display_notice(data.error); | ||
478 | + } else { | ||
479 | + $.get(add_contacts_url, function(data){ | ||
480 | + $("#contacts-list").html(data); | ||
481 | + }); | ||
482 | + }; | ||
483 | + $("#loading-dialog").dialog('close'); | ||
484 | + } | ||
485 | + }); | ||
486 | + }, 5000); | ||
487 | + setTimeout(function() { | ||
488 | + clearInterval(interval); | ||
489 | + $("#loading-dialog").dialog('close'); | ||
490 | + $.get(cancel_contacts_fetching_url); | ||
491 | + redirect_to($('#invitation_back_button').attr('href')); | ||
492 | + }, 600000); | ||
493 | + }); | ||
494 | +} | ||
495 | + | ||
496 | +function display_notice(message) { | ||
497 | + var $noticeBox = jQuery('<div id="notice"></div>').html(message).appendTo('body').fadeTo('fast', 0.8); | ||
498 | + $noticeBox.click(function() { $(this).hide(); }); | ||
499 | + setTimeout(function() { $noticeBox.fadeOut('fast'); }, 5000); | ||
500 | +} |
public/stylesheets/application.css
@@ -3189,6 +3189,26 @@ h1#agenda-title { | @@ -3189,6 +3189,26 @@ h1#agenda-title { | ||
3189 | margin: 5px 0px; | 3189 | margin: 5px 0px; |
3190 | } | 3190 | } |
3191 | 3191 | ||
3192 | +#loading-dialog .loading-message { | ||
3193 | + height: 32px; | ||
3194 | + width: 32px; | ||
3195 | + left: 209px; | ||
3196 | + bottom: 5px; | ||
3197 | + position: absolute; | ||
3198 | + display: block; | ||
3199 | + background: transparent url(/images/loading-dark.gif) center center no-repeat; | ||
3200 | +} | ||
3201 | + | ||
3202 | +/* hide the close x on the loading screen */ | ||
3203 | +.controller-invite .ui-dialog-titlebar-close { | ||
3204 | + display: none; | ||
3205 | +} | ||
3206 | + | ||
3207 | +#hotmail_username_tip { | ||
3208 | + color: red; | ||
3209 | + margin-top: 10px; | ||
3210 | +} | ||
3211 | + | ||
3192 | /* ==> public/stylesheets/controller_manage_products.css <== */ | 3212 | /* ==> public/stylesheets/controller_manage_products.css <== */ |
3193 | 3213 | ||
3194 | #category_form { | 3214 | #category_form { |
script/delayed_job
@@ -6,28 +6,9 @@ | @@ -6,28 +6,9 @@ | ||
6 | # The role of this script is to just start/stop the daemon, write a PID file, | 6 | # The role of this script is to just start/stop the daemon, write a PID file, |
7 | # etc. The actual feed update logic is DelayedJob plugin. | 7 | # etc. The actual feed update logic is DelayedJob plugin. |
8 | 8 | ||
9 | +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment')) | ||
9 | require 'daemons' | 10 | require 'daemons' |
11 | +require 'delayed/command' | ||
10 | 12 | ||
11 | -NOOSFERO_ROOT = File.expand_path(File.dirname(__FILE__) + '/../') | ||
12 | - | ||
13 | -options = { | ||
14 | - :dir_mode => :normal, | ||
15 | - :dir => File.dirname(__FILE__) + '/../tmp/pids', | ||
16 | - :multiple => false, | ||
17 | - :backtrace => true, | ||
18 | - :monitor => true, | ||
19 | -} | ||
20 | - | ||
21 | -Daemons.run_proc('job_runner', options) do | ||
22 | - if ARGV.include?('--') | ||
23 | - ARGV.slice! 0..ARGV.index('--') | ||
24 | - else | ||
25 | - ARGV.clear | ||
26 | - end | ||
27 | - | ||
28 | - Dir.chdir NOOSFERO_ROOT | ||
29 | - RAILS_ENV = ARGV.first || ENV['RAILS_ENV'] || 'development' | ||
30 | - require NOOSFERO_ROOT + '/config/environment' | ||
31 | - | ||
32 | - Delayed::Worker.new.start | ||
33 | -end | 13 | +ENV['RAILS_ENV'] ||= "production" |
14 | +Delayed::Command.new(ARGV).daemonize |
script/production
@@ -20,14 +20,14 @@ do_start() { | @@ -20,14 +20,14 @@ do_start() { | ||
20 | clear_cache | 20 | clear_cache |
21 | ./script/ferret_server -e $RAILS_ENV start | 21 | ./script/ferret_server -e $RAILS_ENV start |
22 | ./script/feed-updater start | 22 | ./script/feed-updater start |
23 | - ./script/delayed_job start | 23 | +# ./script/delayed_job start -n 4 |
24 | mongrel_rails cluster::start | 24 | mongrel_rails cluster::start |
25 | } | 25 | } |
26 | 26 | ||
27 | do_stop() { | 27 | do_stop() { |
28 | mongrel_rails cluster::stop | 28 | mongrel_rails cluster::stop |
29 | ./script/delayed_job stop | 29 | ./script/delayed_job stop |
30 | - ./script/feed-updater stop | 30 | +# ./script/feed-updater stop |
31 | ./script/ferret_server -e $RAILS_ENV stop | 31 | ./script/ferret_server -e $RAILS_ENV stop |
32 | } | 32 | } |
33 | 33 |
test/functional/invite_controller_test.rb
@@ -11,9 +11,10 @@ class InviteControllerTest < ActionController::TestCase | @@ -11,9 +11,10 @@ class InviteControllerTest < ActionController::TestCase | ||
11 | attr_accessor :profile, :friend, :community | 11 | attr_accessor :profile, :friend, :community |
12 | 12 | ||
13 | should 'add manually invitation of an added address with friend object on a queue and process it later' do | 13 | should 'add manually invitation of an added address with friend object on a queue and process it later' do |
14 | + contact_list = ContactList.create | ||
14 | assert_difference Delayed::Job, :count, 1 do | 15 | assert_difference Delayed::Job, :count, 1 do |
15 | - post :friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :step => 2 | ||
16 | - assert_redirected_to :controller => 'friends' | 16 | + post :select_friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id |
17 | + assert_redirected_to :controller => 'profile', :action => 'friends' | ||
17 | end | 18 | end |
18 | 19 | ||
19 | assert_difference InviteFriend, :count, 1 do | 20 | assert_difference InviteFriend, :count, 1 do |
@@ -22,9 +23,10 @@ class InviteControllerTest < ActionController::TestCase | @@ -22,9 +23,10 @@ class InviteControllerTest < ActionController::TestCase | ||
22 | end | 23 | end |
23 | 24 | ||
24 | should 'add manually invitation of an added address with only email on a queue and process it later' do | 25 | should 'add manually invitation of an added address with only email on a queue and process it later' do |
26 | + contact_list = ContactList.create | ||
25 | assert_difference Delayed::Job, :count, 1 do | 27 | assert_difference Delayed::Job, :count, 1 do |
26 | - post :friends, :profile => profile.identifier, :manual_import_addresses => "test@test.com", :import_from => "manual", :mail_template => "click: <url>", :step => 2 | ||
27 | - assert_redirected_to :controller => 'friends' | 28 | + post :select_friends, :profile => profile.identifier, :manual_import_addresses => "test@test.com", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id |
29 | + assert_redirected_to :controller => 'profile', :action => 'friends' | ||
28 | end | 30 | end |
29 | 31 | ||
30 | assert_difference InviteFriend, :count, 1 do | 32 | assert_difference InviteFriend, :count, 1 do |
@@ -33,9 +35,10 @@ class InviteControllerTest < ActionController::TestCase | @@ -33,9 +35,10 @@ class InviteControllerTest < ActionController::TestCase | ||
33 | end | 35 | end |
34 | 36 | ||
35 | should 'add manually invitation of an added address with email and other format on a queue and process it later' do | 37 | should 'add manually invitation of an added address with email and other format on a queue and process it later' do |
38 | + contact_list = ContactList.create | ||
36 | assert_difference Delayed::Job, :count, 1 do | 39 | assert_difference Delayed::Job, :count, 1 do |
37 | - post :friends, :profile => profile.identifier, :manual_import_addresses => "test@test.cz.com", :import_from => "manual", :mail_template => "click: <url>", :step => 2 | ||
38 | - assert_redirected_to :controller => 'friends' | 40 | + post :select_friends, :profile => profile.identifier, :manual_import_addresses => "test@test.cz.com", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id |
41 | + assert_redirected_to :controller => 'profile', :action => 'friends' | ||
39 | end | 42 | end |
40 | 43 | ||
41 | assert_difference InviteFriend, :count, 1 do | 44 | assert_difference InviteFriend, :count, 1 do |
@@ -44,9 +47,10 @@ class InviteControllerTest < ActionController::TestCase | @@ -44,9 +47,10 @@ class InviteControllerTest < ActionController::TestCase | ||
44 | end | 47 | end |
45 | 48 | ||
46 | should 'add manually invitation of more than one added address on a queue and process it later' do | 49 | should 'add manually invitation of more than one added address on a queue and process it later' do |
50 | + contact_list = ContactList.create | ||
47 | assert_difference Delayed::Job, :count, 1 do | 51 | assert_difference Delayed::Job, :count, 1 do |
48 | - post :friends, :profile => profile.identifier, :manual_import_addresses => "Some Friend <somefriend@email.com>\r\notherperson@bleble.net\r\n", :import_from => "manual", :mail_template => "click: <url>", :step => 2 | ||
49 | - assert_redirected_to :controller => 'friends' | 52 | + post :select_friends, :profile => profile.identifier, :manual_import_addresses => "Some Friend <somefriend@email.com>\r\notherperson@bleble.net\r\n", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id |
53 | + assert_redirected_to :controller => 'profile', :action => 'friends' | ||
50 | end | 54 | end |
51 | 55 | ||
52 | assert_difference InviteFriend, :count, 2 do | 56 | assert_difference InviteFriend, :count, 2 do |
@@ -55,9 +59,10 @@ class InviteControllerTest < ActionController::TestCase | @@ -55,9 +59,10 @@ class InviteControllerTest < ActionController::TestCase | ||
55 | end | 59 | end |
56 | 60 | ||
57 | should 'add manually invitation of an added address with name and e-mail on a queue and process it later' do | 61 | should 'add manually invitation of an added address with name and e-mail on a queue and process it later' do |
62 | + contact_list = ContactList.create | ||
58 | assert_difference Delayed::Job, :count, 1 do | 63 | assert_difference Delayed::Job, :count, 1 do |
59 | - post :friends, :profile => profile.identifier, :manual_import_addresses => "Test Name <test@test.com>", :import_from => "manual", :mail_template => "click: <url>", :step => 2 | ||
60 | - assert_redirected_to :controller => 'friends' | 64 | + post :select_friends, :profile => profile.identifier, :manual_import_addresses => "Test Name <test@test.com>", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id |
65 | + assert_redirected_to :controller => 'profile', :action => 'friends' | ||
61 | end | 66 | end |
62 | 67 | ||
63 | assert_difference InviteFriend, :count, 1 do | 68 | assert_difference InviteFriend, :count, 1 do |
@@ -66,9 +71,10 @@ class InviteControllerTest < ActionController::TestCase | @@ -66,9 +71,10 @@ class InviteControllerTest < ActionController::TestCase | ||
66 | end | 71 | end |
67 | 72 | ||
68 | should 'add invitation of yourself on a queue and not process it later' do | 73 | should 'add invitation of yourself on a queue and not process it later' do |
74 | + contact_list = ContactList.create | ||
69 | assert_difference Delayed::Job, :count, 1 do | 75 | assert_difference Delayed::Job, :count, 1 do |
70 | - post :friends, :profile => profile.identifier, :manual_import_addresses => "#{profile.name} <#{profile.user.email}>", :import_from => "manual", :mail_template => "click: <url>", :step => 2 | ||
71 | - assert_redirected_to :controller => 'friends' | 76 | + post :select_friends, :profile => profile.identifier, :manual_import_addresses => "#{profile.name} <#{profile.user.email}>", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id |
77 | + assert_redirected_to :controller => 'profile', :action => 'friends' | ||
72 | end | 78 | end |
73 | 79 | ||
74 | assert_no_difference InviteFriend, :count do | 80 | assert_no_difference InviteFriend, :count do |
@@ -80,9 +86,10 @@ class InviteControllerTest < ActionController::TestCase | @@ -80,9 +86,10 @@ class InviteControllerTest < ActionController::TestCase | ||
80 | friend = create_user('testfriend', :email => 'friend@noosfero.org') | 86 | friend = create_user('testfriend', :email => 'friend@noosfero.org') |
81 | friend.person.add_friend(profile) | 87 | friend.person.add_friend(profile) |
82 | 88 | ||
89 | + contact_list = ContactList.create | ||
83 | assert_difference Delayed::Job, :count, 1 do | 90 | assert_difference Delayed::Job, :count, 1 do |
84 | - post :friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :step => 2 | ||
85 | - assert_redirected_to :controller => 'friends' | 91 | + post :select_friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id |
92 | + assert_redirected_to :controller => 'profile', :action => 'friends' | ||
86 | end | 93 | end |
87 | 94 | ||
88 | assert_no_difference InviteFriend, :count do | 95 | assert_no_difference InviteFriend, :count do |
@@ -91,42 +98,131 @@ class InviteControllerTest < ActionController::TestCase | @@ -91,42 +98,131 @@ class InviteControllerTest < ActionController::TestCase | ||
91 | end | 98 | end |
92 | 99 | ||
93 | should 'display invitation page' do | 100 | should 'display invitation page' do |
94 | - get :friends, :profile => profile.identifier | 101 | + get :select_address_book, :profile => profile.identifier |
95 | assert_response :success | 102 | assert_response :success |
96 | assert_tag :tag => 'h1', :content => 'Invite your friends' | 103 | assert_tag :tag => 'h1', :content => 'Invite your friends' |
97 | end | 104 | end |
98 | 105 | ||
99 | should 'get mail template to invite members' do | 106 | should 'get mail template to invite members' do |
100 | community.add_admin(profile) | 107 | community.add_admin(profile) |
101 | - get :friends, :profile => community.identifier | 108 | + contact_list = ContactList.create |
109 | + get :select_friends, :profile => community.identifier, :contact_list => contact_list.id | ||
102 | assert_equal InviteMember.mail_template, assigns(:mail_template) | 110 | assert_equal InviteMember.mail_template, assigns(:mail_template) |
103 | end | 111 | end |
104 | 112 | ||
105 | should 'get mail template to invite friends' do | 113 | should 'get mail template to invite friends' do |
106 | community.add_admin(profile) | 114 | community.add_admin(profile) |
107 | - get :friends, :profile => profile.identifier | 115 | + contact_list = ContactList.create |
116 | + get :select_friends, :profile => profile.identifier, :contact_list => contact_list.id | ||
108 | assert_equal InviteFriend.mail_template, assigns(:mail_template) | 117 | assert_equal InviteFriend.mail_template, assigns(:mail_template) |
109 | end | 118 | end |
110 | 119 | ||
111 | - should 'deny if user has no rights to invite members' do | ||
112 | - get :friends, :profile => community.identifier | 120 | + should 'deny select_address_book f user has no rights to invite members' do |
121 | + get :select_address_book, :profile => community.identifier | ||
113 | assert_response 403 # forbidden | 122 | assert_response 403 # forbidden |
114 | end | 123 | end |
115 | 124 | ||
116 | - should 'deny access when trying to invite friends to another user' do | ||
117 | - get :friends, :profile => friend.identifier | 125 | + should 'deny select_friends if user has no rights to invite members' do |
126 | + get :select_friends, :profile => community.identifier | ||
118 | assert_response 403 # forbidden | 127 | assert_response 403 # forbidden |
119 | end | 128 | end |
120 | 129 | ||
121 | - should 'redirect to friends after invitation if profile is a person' do | ||
122 | - post :friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :step => 2 | ||
123 | - assert_redirected_to :controller => 'friends' | 130 | + should 'deny select_address_book access when trying to invite friends to another user' do |
131 | + get :select_address_book, :profile => friend.identifier | ||
132 | + assert_response 403 # forbidden | ||
133 | + end | ||
134 | + | ||
135 | + should 'deny select_friends access when trying to invite friends to another user' do | ||
136 | + get :select_address_book, :profile => friend.identifier | ||
137 | + assert_response 403 # forbidden | ||
138 | + end | ||
139 | + | ||
140 | + should 'redirect to profile after invitation if profile is a person' do | ||
141 | + contact_list = ContactList.create | ||
142 | + post :select_friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id | ||
143 | + assert_redirected_to :controller => 'profile', :action => 'friends' | ||
124 | end | 144 | end |
125 | 145 | ||
126 | - should 'redirect to friends after invitation if profile is not a person' do | 146 | + should 'redirect to profile after invitation if profile is not a person' do |
127 | community.add_admin(profile) | 147 | community.add_admin(profile) |
128 | - post :friends, :profile => community.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :step => 2 | ||
129 | - assert_redirected_to :controller => 'profile_members' | 148 | + contact_list = ContactList.create |
149 | + post :select_friends, :profile => community.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id | ||
150 | + assert_redirected_to :controller => 'profile', :action => 'members' | ||
151 | + end | ||
152 | + | ||
153 | + should 'create a job to get emails after choose address book' do | ||
154 | + community.add_admin(profile) | ||
155 | + contact_list = ContactList.create | ||
156 | + assert_difference Delayed::Job, :count, 1 do | ||
157 | + post :select_address_book, :profile => community.identifier, :contact_list => contact_list.id, :import_from => 'gmail' | ||
158 | + assert_redirected_to :action => 'select_friends' | ||
159 | + end | ||
160 | + end | ||
161 | + | ||
162 | + should 'destroy contact_list after invitation when import is manual' do | ||
163 | + contact_list = ContactList.create | ||
164 | + post :select_friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id | ||
165 | + | ||
166 | + assert ContactList.exists?(contact_list.id) | ||
167 | + Delayed::Worker.new.work_off | ||
168 | + assert !ContactList.exists?(contact_list.id) | ||
169 | + end | ||
170 | + | ||
171 | + should 'destroy contact_list after invitation when import is not manual' do | ||
172 | + contact_list = ContactList.create | ||
173 | + post :select_friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "not_manual", :mail_template => "click: <url>", :contact_list => contact_list.id | ||
174 | + | ||
175 | + assert ContactList.exists?(contact_list.id) | ||
176 | + Delayed::Worker.new.work_off | ||
177 | + assert !ContactList.exists?(contact_list.id) | ||
178 | + end | ||
179 | + | ||
180 | + should 'return empty hash as invitation data if contact list was not fetched' do | ||
181 | + contact_list = ContactList.create | ||
182 | + get :invitation_data, :profile => profile.identifier, :contact_list => contact_list.id | ||
183 | + | ||
184 | + assert_equal 'application/javascript', @response.content_type | ||
185 | + assert_equal '{}', @response.body | ||
186 | + end | ||
187 | + | ||
188 | + should 'return hash as invitation data if contact list was fetched' do | ||
189 | + contact_list = ContactList.create(:fetched => true) | ||
190 | + get :invitation_data, :profile => profile.identifier, :contact_list => contact_list.id | ||
191 | + | ||
192 | + assert_equal 'application/javascript', @response.content_type | ||
193 | + assert_equal "{\"fetched\": true, \"contact_list\": #{contact_list.id}, \"error\": null}", @response.body | ||
194 | + end | ||
195 | + | ||
196 | + should 'render empty list of contacts' do | ||
197 | + contact_list = ContactList.create(:fetched => true) | ||
198 | + get :add_contact_list, :profile => profile.identifier, :contact_list => contact_list.id | ||
199 | + | ||
200 | + assert_response :success | ||
201 | + assert_template '_contact_list' | ||
202 | + assert_no_tag(:tag => 'input', :attributes => { :type => 'checkbox', :name => 'webmail_import_addresses[]'}) | ||
203 | + end | ||
204 | + | ||
205 | + should 'render list of contacts' do | ||
206 | + contact_list = ContactList.create(:fetched => true, :list => ['email1@noosfero.org', 'email2@noosfero.org']) | ||
207 | + get :add_contact_list, :profile => profile.identifier, :contact_list => contact_list.id | ||
208 | + | ||
209 | + assert_response :success | ||
210 | + assert_template '_contact_list' | ||
211 | + | ||
212 | + i = 0 | ||
213 | + contact_list.list.each do |contact| | ||
214 | + i += 1 | ||
215 | + assert_tag(:tag => 'input', :attributes => { :type => 'checkbox', :name => 'webmail_import_addresses[]', :id => "contacts_to_invite_#{i}", :value => contact[2]}) | ||
216 | + end | ||
217 | + end | ||
218 | + | ||
219 | + should 'destroy contact_list when cancel_fetching_emails' do | ||
220 | + contact_list = ContactList.create | ||
221 | + | ||
222 | + assert_difference ContactList, :count, -1 do | ||
223 | + get :cancel_fetching_emails, :profile => profile.identifier, :contact_list => contact_list.id | ||
224 | + end | ||
225 | + assert_redirected_to :action => 'select_address_book' | ||
130 | end | 226 | end |
131 | 227 | ||
132 | end | 228 | end |
@@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class ContactListTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'have list as an array' do | ||
6 | + assert_equal [], ContactList.create.list | ||
7 | + end | ||
8 | + | ||
9 | + should 'display list' do | ||
10 | + contact_list = ContactList.create(:list => ['email1@noosfero.org', 'email2@noosfero.org']) | ||
11 | + | ||
12 | + assert_equal ['email1@noosfero.org', 'email2@noosfero.org'], contact_list.list | ||
13 | + end | ||
14 | + | ||
15 | + should 'return empty hash if contact list was not fetched' do | ||
16 | + contact_list = ContactList.create | ||
17 | + assert_equal({}, contact_list.data) | ||
18 | + end | ||
19 | + | ||
20 | + should 'return hash if contact list was fetched' do | ||
21 | + contact_list = ContactList.create(:fetched => true) | ||
22 | + assert_equal({"fetched" => true, "contact_list" => contact_list.id, "error" => contact_list.error_fetching}, contact_list.data) | ||
23 | + end | ||
24 | + | ||
25 | + should 'update fetched and error_fetching when register auth error' do | ||
26 | + contact_list = ContactList.create | ||
27 | + assert_equal({}, contact_list.data) | ||
28 | + | ||
29 | + contact_list.register_error | ||
30 | + assert_equal({"fetched" => true, "contact_list" => contact_list.id, "error" => 'There was an error while looking for your contact list. Please, try again'}, contact_list.data) | ||
31 | + end | ||
32 | + | ||
33 | + should 'update fetched and error_fetching when register error' do | ||
34 | + contact_list = ContactList.create | ||
35 | + assert_equal({}, contact_list.data) | ||
36 | + | ||
37 | + contact_list.register_auth_error | ||
38 | + assert_equal({"fetched" => true, "contact_list" => contact_list.id, "error" => 'There was an error while authenticating. Did you enter correct login and password?'}, contact_list.data) | ||
39 | + end | ||
40 | + | ||
41 | +end |
@@ -0,0 +1,27 @@ | @@ -0,0 +1,27 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class GetEmailContactsJobTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'register error' do | ||
6 | + contact_list = ContactList.create | ||
7 | + Invitation.expects(:get_contacts).with('from-email', 'mylogin', 'mypassword', contact_list.id).raises(Exception.new("crash")) | ||
8 | + | ||
9 | + job = GetEmailContactsJob.new('from-email', 'mylogin', 'mypassword', contact_list.id) | ||
10 | + job.perform | ||
11 | + | ||
12 | + assert ContactList.find(contact_list).fetched | ||
13 | + assert_equal 'There was an error while looking for your contact list. Please, try again', ContactList.find(contact_list).error_fetching | ||
14 | + end | ||
15 | + | ||
16 | + should 'register auth error' do | ||
17 | + contact_list = ContactList.create | ||
18 | + Invitation.expects(:get_contacts).with('from-email', 'mylogin', 'wrongpassword', contact_list.id).raises(Contacts::AuthenticationError) | ||
19 | + | ||
20 | + job = GetEmailContactsJob.new('from-email', 'mylogin', 'wrongpassword', contact_list.id) | ||
21 | + job.perform | ||
22 | + | ||
23 | + assert ContactList.find(contact_list).fetched | ||
24 | + assert_equal 'There was an error while authenticating. Did you enter correct login and password?', ContactList.find(contact_list).error_fetching | ||
25 | + end | ||
26 | + | ||
27 | +end |
test/unit/invitation_test.rb
@@ -26,8 +26,9 @@ class InvitationTest < ActiveSupport::TestCase | @@ -26,8 +26,9 @@ class InvitationTest < ActiveSupport::TestCase | ||
26 | end | 26 | end |
27 | 27 | ||
28 | should 'raises when try get contacts from unknown source' do | 28 | should 'raises when try get contacts from unknown source' do |
29 | + contact_list = ContactList.create | ||
29 | assert_raise NotImplementedError do | 30 | assert_raise NotImplementedError do |
30 | - Invitation.get_contacts('ze', 'ze12', 'bli-mail') | 31 | + Invitation.get_contacts('ze', 'ze12', 'bli-mail', contact_list.id) |
31 | end | 32 | end |
32 | end | 33 | end |
33 | 34 | ||
@@ -71,4 +72,29 @@ class InvitationTest < ActiveSupport::TestCase | @@ -71,4 +72,29 @@ class InvitationTest < ActiveSupport::TestCase | ||
71 | end | 72 | end |
72 | end | 73 | end |
73 | 74 | ||
75 | + should 'add url on message if user removed it' do | ||
76 | + person = create_user('testuser1').person | ||
77 | + friend = create_user('testuser2').person | ||
78 | + invitation = Invitation.create!( | ||
79 | + :person => person, | ||
80 | + :friend => friend, | ||
81 | + :message => 'Hi <friend>, <user> is inviting you!' | ||
82 | + ) | ||
83 | + assert_equal "Hi <friend>, <user> is inviting you!#{invitation.message_to_accept_invitation}", invitation.message | ||
84 | + end | ||
85 | + | ||
86 | + should 'do nothing with message if user added url' do | ||
87 | + person = create_user('testuser1').person | ||
88 | + friend = create_user('testuser2').person | ||
89 | + invitation = Invitation.create!( | ||
90 | + :person => person, | ||
91 | + :friend => friend, | ||
92 | + :message => 'Hi <friend>, <user> is inviting you to be his friend on <url>!' | ||
93 | + ) | ||
94 | + assert_equal "Hi <friend>, <user> is inviting you to be his friend on <url>!", invitation.message | ||
95 | + end | ||
96 | + | ||
97 | + should 'have a message with url' do | ||
98 | + assert_equal "<p>To accept invitation, please follow this link: <url></p>", Invitation.new.message_to_accept_invitation | ||
99 | + end | ||
74 | end | 100 | end |
test/unit/invite_friend_test.rb
@@ -70,21 +70,6 @@ class InviteFriendTest < ActiveSupport::TestCase | @@ -70,21 +70,6 @@ class InviteFriendTest < ActiveSupport::TestCase | ||
70 | ok('must validate with no target') { !task.errors.invalid?(:target_id) } | 70 | ok('must validate with no target') { !task.errors.invalid?(:target_id) } |
71 | end | 71 | end |
72 | 72 | ||
73 | - should 'require message with <url> tag if no target given' do | ||
74 | - task = InviteFriend.new | ||
75 | - task.valid? | ||
76 | - | ||
77 | - ok('must not validate with no message') { task.errors.invalid?(:message) } | ||
78 | - | ||
79 | - task.message = 'a simple message' | ||
80 | - task.valid? | ||
81 | - ok('must not validate with no <url> tag in message') { task.errors.invalid?(:message) } | ||
82 | - | ||
83 | - task.message = 'a simple message with <url>' | ||
84 | - task.valid? | ||
85 | - ok('must validate when message is given with <url> tag') { !task.errors.invalid?(:message)} | ||
86 | - end | ||
87 | - | ||
88 | should 'dont require message if target given (person being invited)' do | 73 | should 'dont require message if target given (person being invited)' do |
89 | task = InviteFriend.new(:target => create_user('testuser2').person) | 74 | task = InviteFriend.new(:target => create_user('testuser2').person) |
90 | task.valid? | 75 | task.valid? |