]> source.dussan.org Git - redmine.git/commitdiff
More flexible mail notifications settings at user level. A user has now 3 options:
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 20 Oct 2007 12:47:05 +0000 (12:47 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 20 Oct 2007 12:47:05 +0000 (12:47 +0000)
* notification on any event on all his projects
* notification on any event on selected projects only (if the user belongs to more than 1 project)
* notification only for things that he watches or he is involded in (eg. issues that he watches or he is author or assignee)

git-svn-id: http://redmine.rubyforge.org/svn/trunk@855 e93f8b46-1217-0410-a6f0-8f06a7374b81

30 files changed:
app/controllers/my_controller.rb
app/models/issue.rb
app/models/mailer.rb
app/models/project.rb
app/models/user.rb
app/views/my/_sidebar.rhtml [new file with mode: 0644]
app/views/my/account.rhtml
app/views/my/password.rhtml [new file with mode: 0644]
app/views/users/_form.rhtml
db/migrate/001_setup.rb
db/migrate/075_add_members_mail_notification.rb [new file with mode: 0644]
lang/bg.yml
lang/cs.yml
lang/de.yml
lang/en.yml
lang/es.yml
lang/fr.yml
lang/he.yml
lang/it.yml
lang/ja.yml
lang/nl.yml
lang/pl.yml
lang/pt-br.yml
lang/pt.yml
lang/ro.yml
lang/sv.yml
lang/zh.yml
public/stylesheets/application.css
test/functional/my_controller_test.rb
test/unit/user_test.rb

index bbb3a6e227cf60fe4acc78a25878b61f5c3b9784..5a1b128f9d3ede045e773ae9ae65034e0c996eba 100644 (file)
@@ -50,32 +50,44 @@ class MyController < ApplicationController
 
   # Edit user's account
   def account
-    @user = self.logged_in_user
+    @user = User.current
     @pref = @user.pref
-    @user.attributes = params[:user]
-    @user.pref.attributes = params[:pref]
-    if request.post? && @user.save && @user.pref.save
-      flash[:notice] = l(:notice_account_updated)
-      redirect_to :action => 'account'
+    if request.post?
+      @user.attributes = params[:user]
+      @user.mail_notification = (params[:notification_option] == 'all')
+      @user.pref.attributes = params[:pref]
+      if @user.save
+        @user.pref.save
+        @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
+        set_language_if_valid @user.language
+        flash[:notice] = l(:notice_account_updated)
+        redirect_to :action => 'account'
+        return
+      end
     end
+    @notification_options = [[l(:label_user_mail_option_all), 'all'],
+                             [l(:label_user_mail_option_none), 'none']]
+    # Only users that belong to more than 1 project can select projects for which they are notified
+    # Note that @user.membership.size would fail since AR ignores :include association option when doing a count
+    @notification_options.insert 1, [l(:label_user_mail_option_selected), 'selected'] if @user.memberships.length > 1
+    @notification_option = @user.mail_notification? ? 'all' : (@user.notified_projects_ids.empty? ? 'none' : 'selected')    
   end
 
-  # Change user's password
-  def change_password
+  # Manage user's password
+  def password
     @user = self.logged_in_user
     flash[:error] = l(:notice_can_t_change_password) and redirect_to :action => 'account' and return if @user.auth_source_id
-    if @user.check_password?(params[:password])
-      @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
-      if @user.save
-        flash[:notice] = l(:notice_account_password_updated)
+    if request.post?
+      if @user.check_password?(params[:password])
+        @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
+        if @user.save
+          flash[:notice] = l(:notice_account_password_updated)
+          redirect_to :action => 'account'
+        end
       else
-        render :action => 'account'
-        return
+        flash[:error] = l(:notice_account_wrong_password)
       end
-    else
-      flash[:error] = l(:notice_account_wrong_password)
     end
-    redirect_to :action => 'account'
   end
   
   # Create a new feeds key
index 026ce1211e7632be98abb83981c6052b4d55278c..972bf01351a8f2ca4f3d2c39f316a0b29686077c 100644 (file)
@@ -143,6 +143,15 @@ class Issue < ActiveRecord::Base
     project.assignable_users
   end
   
+  # Returns the mail adresses of users that should be notified for the issue
+  def recipients
+    recipients = project.recipients
+    # Author and assignee are always notified
+    recipients << author.mail if author
+    recipients << assigned_to.mail if assigned_to
+    recipients.compact.uniq
+  end
+  
   def spent_hours
     @spent_hours ||= time_entries.sum(:hours) || 0
   end
index 683045715e55616a0bd7cd6b3667d43a827e39fe..da7937404fa1597ad9ac0b29c91ca95d317b207a 100644 (file)
@@ -30,13 +30,7 @@ class Mailer < ActionMailer::Base
 
   def issue_add(issue)
     set_language_if_valid(Setting.default_language)
-    # Sends to all project members
-    @recipients     = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification }.compact
-    # Sends to author and assignee (even if they turned off mail notification)
-    @recipients     << issue.author.mail if issue.author
-    @recipients     << issue.assigned_to.mail if issue.assigned_to
-    @recipients.compact!
-    @recipients.uniq!
+    @recipients     = issue.recipients
     @from           = Setting.mail_from
     @subject        = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] #{issue.status.name} - #{issue.subject}"
     @body['issue']  = issue
@@ -44,14 +38,8 @@ class Mailer < ActionMailer::Base
 
   def issue_edit(journal)
     set_language_if_valid(Setting.default_language)
-    # Sends to all project members
     issue = journal.journalized
-    @recipients     = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification }.compact
-    # Sends to author and assignee (even if they turned off mail notification)
-    @recipients     << issue.author.mail if issue.author
-    @recipients     << issue.assigned_to.mail if issue.assigned_to
-    @recipients.compact!
-    @recipients.uniq!
+    @recipients     = issue.recipients
     # Watchers in cc
     @cc             = issue.watcher_recipients - @recipients
     @from           = Setting.mail_from
@@ -62,7 +50,7 @@ class Mailer < ActionMailer::Base
   
   def document_added(document)
     set_language_if_valid(Setting.default_language)
-    @recipients     = document.project.users.collect { |u| u.mail if u.mail_notification }.compact
+    @recipients     = document.project.recipients
     @from           = Setting.mail_from
     @subject        = "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
     @body['document'] = document
@@ -81,7 +69,7 @@ class Mailer < ActionMailer::Base
       url = {:only_path => false, :host => Setting.host_name, :controller => 'documents', :action => 'show', :id => container.id}
       added_to = "#{l(:label_document)}: #{container.title}"
     end
-    @recipients     = container.project.users.collect { |u| u.mail if u.mail_notification }.compact
+    @recipients     = container.project.recipients
     @from           = Setting.mail_from
     @subject        = "[#{container.project.name}] #{l(:label_attachment_new)}"
     @body['attachments'] = attachments
@@ -91,7 +79,7 @@ class Mailer < ActionMailer::Base
 
   def news_added(news)
     set_language_if_valid(Setting.default_language)
-    @recipients     = news.project.users.collect { |u| u.mail if u.mail_notification }.compact
+    @recipients     = news.project.recipients
     @from           = Setting.mail_from
     @subject        = "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
     @body['news'] = news
index 3e6593f588f9f9ae51c45899fbbbc7b6883d8467..8f7e03a7c470fc1fe16a8bd0aa7c5a3eeecb930b 100644 (file)
@@ -118,6 +118,11 @@ class Project < ActiveRecord::Base
     members.select {|m| m.role.assignable?}.collect {|m| m.user}
   end
   
+  # Returns the mail adresses of users that should be always notified on project events
+  def recipients
+    members.select {|m| m.mail_notification? || m.user.mail_notification?}.collect {|m| m.user.mail}
+  end
+  
   # Returns an array of all custom fields enabled for project issues
   # (explictly associated custom fields and custom fields enabled for all projects)
   def custom_fields_for_issues(tracker)
index e4c397a51cd75912f69fda9a5ff3980ae14e61d6..9c8d1d9a3b1f002a2a51c4275a00bf06858c1556 100644 (file)
@@ -50,6 +50,11 @@ class User < ActiveRecord::Base
   validates_confirmation_of :password, :allow_nil => true
   validates_associated :custom_values, :on => :update
 
+  def before_create
+    self.mail_notification = false
+    true
+  end
+  
   def before_save
     # update hashed_password if password was set
     self.hashed_password = User.hash_password(self.password) if self.password
@@ -131,6 +136,18 @@ class User < ActiveRecord::Base
     token.value
   end
   
+  # Return an array of project ids for which the user has explicitly turned mail notifications on
+  def notified_projects_ids
+    @notified_projects_ids ||= memberships.select {|m| m.mail_notification?}.collect(&:project_id)
+  end
+  
+  def notified_project_ids=(ids)
+    Member.update_all("mail_notification = #{connection.quoted_false}", ['user_id = ?', id])
+    Member.update_all("mail_notification = #{connection.quoted_true}", ['user_id = ? AND project_id IN (?)', id, ids]) if ids && !ids.empty?
+    @notified_projects_ids = nil
+    notified_projects_ids
+  end
+  
   def self.find_by_rss_key(key)
     token = Token.find_by_value(key)
     token && token.user.active? ? token.user : nil
diff --git a/app/views/my/_sidebar.rhtml b/app/views/my/_sidebar.rhtml
new file mode 100644 (file)
index 0000000..d30eacf
--- /dev/null
@@ -0,0 +1,8 @@
+<h3><%=l(:label_my_account)%></h3>
+
+<p><%=l(:field_login)%>: <strong><%= @user.login %></strong><br />
+<%=l(:field_created_on)%>: <%= format_time(@user.created_on) %></p>
+<% if @user.rss_token %>
+<p><%= l(:label_feeds_access_key_created_on, distance_of_time_in_words(Time.now, @user.rss_token.created_on)) %>
+(<%= link_to l(:button_reset), {:action => 'reset_rss_key'}, :method => :post %>)</p>
+<% end %>
index 8250c529804d4154a7fd22ed0002232c7457d5cc..198ef8ffe7e310ee145b7b0ebbc9ee9485051a4e 100644 (file)
@@ -1,55 +1,41 @@
+<div class="contextual">
+<%= link_to(l(:button_change_password), :action => 'password') unless @user.auth_source_id %>
+</div>
 <h2><%=l(:label_my_account)%></h2>
-
 <%= error_messages_for 'user' %>
 
-<div class="box">
+<% form_for :user, @user, :url => { :action => "account" }, :builder => TabularFormBuilder, :lang => current_language do |f| %>
+<div class="splitcontentleft">
 <h3><%=l(:label_information_plural)%></h3>
-  
-<% labelled_tabular_form_for :user, @user, :url => { :action => "account" } do |f| %>
-
+<div class="box tabular">
 <p><%= f.text_field :firstname, :required => true %></p>
 <p><%= f.text_field :lastname, :required => true %></p>
-<p><%= f.text_field :mail, :required => true, :size => 40 %></p>
+<p><%= f.text_field :mail, :required => true %></p>
 <p><%= f.select :language, lang_options_for_select %></p>
-<p><%= f.check_box :mail_notification %></p>
 
 <% fields_for :pref, @user.pref, :builder => TabularFormBuilder, :lang => current_language do |pref_fields| %>
 <p><%= pref_fields.check_box :hide_mail %></p>
 <% end %>
-
-<center><%= submit_tag l(:button_save) %></center>
-<% end %>
 </div>
 
+<%= submit_tag l(:button_save) %>
+</div>
 
-<% unless @user.auth_source_id %>
-  <div class="box">
-  <h3><%=l(:field_password)%></h3>
-
-  <% form_tag({:action => 'change_password'}, :class => "tabular") do %>
-
-  <p><label for="password"><%=l(:field_password)%> <span class="required">*</span></label>
-  <%= password_field_tag 'password', nil, :size => 25 %></p>
-
-  <p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label>
-  <%= password_field_tag 'new_password', nil, :size => 25 %><br />
-  <em><%= l(:text_length_between, 4, 12) %></em></p>
-
-  <p><label for="new_password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
-  <%= password_field_tag 'new_password_confirmation', nil, :size => 25 %></p>
-
-  <center><%= submit_tag l(:button_save) %></center>
-  <% end %>
-  </div>
+<div class="splitcontentright">
+<h3><%=l(:field_mail_notification)%></h3>
+<div class="box">
+<%= select_tag 'notification_option', options_for_select(@notification_options, @notification_option),
+                                      :onchange => 'if ($("notification_option").value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %>
+<% content_tag 'div', :id => 'notified-projects', :style => (@notification_option == 'selected' ? '' : 'display:none;') do %>
+<p><% User.current.projects.each do |project| %>
+    <label><%= check_box_tag 'notified_project_ids[]', project.id, @user.notified_projects_ids.include?(project.id) %> <%= project.name %></label><br />
+<% end %></p>
+<p><em><%= l(:text_user_mail_option) %></em></p>
+<% end %>
+</div>
+</div>
 <% end %>
 
 <% content_for :sidebar do %>
-    <h3><%=l(:label_my_account)%></h3>
-    
-    <p><%=l(:field_login)%>: <strong><%= @user.login %></strong><br />
-    <%=l(:field_created_on)%>: <%= format_time(@user.created_on) %></p>
-    <% if @user.rss_token %>
-    <p><%= l(:label_feeds_access_key_created_on, distance_of_time_in_words(Time.now, @user.rss_token.created_on)) %>
-    (<%= link_to l(:button_reset), {:action => 'reset_rss_key'}, :method => :post %>)</p>
-    <% end %>
+<%= render :partial => 'sidebar' %>
 <% end %>
diff --git a/app/views/my/password.rhtml b/app/views/my/password.rhtml
new file mode 100644 (file)
index 0000000..217a875
--- /dev/null
@@ -0,0 +1,22 @@
+<h2><%=l(:button_change_password)%></h2>
+
+<%= error_messages_for 'user' %>
+
+<% form_tag({}, :class => "tabular") do %>
+<div class="box">
+<p><label for="password"><%=l(:field_password)%> <span class="required">*</span></label>
+<%= password_field_tag 'password', nil, :size => 25 %></p>
+
+<p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label>
+<%= password_field_tag 'new_password', nil, :size => 25 %><br />
+<em><%= l(:text_length_between, 4, 12) %></em></p>
+
+<p><label for="new_password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
+<%= password_field_tag 'new_password_confirmation', nil, :size => 25 %></p>
+</div>
+<%= submit_tag l(:button_apply) %>
+<% end %>
+
+<% content_for :sidebar do %>
+<%= render :partial => 'sidebar' %>
+<% end %>
index 56b15798651ea570ed2542cebd58d2bce3e20a4c..72cf3c95c78365fc97f340163d703071934665cb 100644 (file)
@@ -14,7 +14,6 @@
 <% end if @custom_values%>
 
 <p><%= f.check_box :admin %></p>
-<p><%= f.check_box :mail_notification %></p>
 </div>
 
 <div class="box">
index 8b299eb1eab85689824b45964eefa4a699cb021e..1160dd5efa370659aa9a3e6372e187dcd610c8cc 100644 (file)
@@ -284,7 +284,7 @@ class Setup < ActiveRecord::Migration
     Permission.create :controller => "versions", :action => "destroy_file", :description => "button_delete", :sort => 1322\r
     \r
     # create default administrator account\r
-    user = User.create :firstname => "redMine", :lastname => "Admin", :mail => "admin@somenet.foo", :mail_notification => true, :language => "en"
+    user = User.create :firstname => "Redmine", :lastname => "Admin", :mail => "admin@somenet.foo", :mail_notification => true, :language => "en"
     user.login = "admin"
     user.password = "admin"\r
     user.admin = true\r
diff --git a/db/migrate/075_add_members_mail_notification.rb b/db/migrate/075_add_members_mail_notification.rb
new file mode 100644 (file)
index 0000000..d83ba8d
--- /dev/null
@@ -0,0 +1,9 @@
+class AddMembersMailNotification < ActiveRecord::Migration
+  def self.up
+    add_column :members, :mail_notification, :boolean, :default => false, :null => false
+  end
+
+  def self.down
+    remove_column :members, :mail_notification
+  end
+end
index 15bbb5239485592f0a7560a5aa0586e54fea60ce..d4ef3511e344d922f2fc93ddb4c18f0b91c6a596 100644 (file)
@@ -526,3 +526,8 @@ label_theme: Тема
 label_default: По подразбиране
 label_search_titles_only: Само в заглавията
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index 8e5f91b411876cb8680b1abd1022fe942fd23cd1..b7b88884d4aeba128404d9a148c5bab78c1c2076 100644 (file)
@@ -526,3 +526,8 @@ label_theme: Theme
 label_default: Default
 label_search_titles_only: Search titles only
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index dae960579deb65d7f99169a71b521e3425cdfe34..793876fc355bf17c5df1e3aa07cf85731f122c94 100644 (file)
@@ -526,3 +526,8 @@ label_theme: Theme
 label_default: Default
 label_search_titles_only: Search titles only
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index 7d23e4fbe1f2ee5a1d80da7cbc1290245519e0fd..d0dc646660b35c27c091ac1081d8b26dd532a7b5 100644 (file)
@@ -127,7 +127,7 @@ field_parent: Subproject of
 field_is_in_chlog: Issues displayed in changelog
 field_is_in_roadmap: Issues displayed in roadmap
 field_login: Login
-field_mail_notification: Mail notifications
+field_mail_notification: Email notifications
 field_admin: Administrator
 field_last_login_on: Last connection
 field_language: Language
@@ -174,7 +174,7 @@ setting_login_required: Authent. required
 setting_self_registration: Self-registration enabled
 setting_attachment_max_size: Attachment max. size
 setting_issues_export_limit: Issues export limit
-setting_mail_from: Emission mail address
+setting_mail_from: Emission email address
 setting_host_name: Host name
 setting_text_formatting: Text formatting
 setting_wiki_compression: Wiki history compression
@@ -437,6 +437,9 @@ label_bulk_edit_selected_issues: Bulk edit selected issues
 label_theme: Theme
 label_default: Default
 label_search_titles_only: Search titles only
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
 
 button_login: Login
 button_submit: Submit
@@ -470,12 +473,13 @@ button_archive: Archive
 button_unarchive: Unarchive
 button_reset: Reset
 button_rename: Rename
+button_change_password: Change password
 
 status_active: active
 status_registered: registered
 status_locked: locked
 
-text_select_mail_notifications: Select actions for which mail notifications should be sent.
+text_select_mail_notifications: Select actions for which email notifications should be sent.
 text_regexp_info: eg. ^[A-Z0-9]+$
 text_min_max_length_info: 0 means no restriction
 text_project_destroy_confirmation: Are you sure you want to delete this project and all related data ?
@@ -500,6 +504,7 @@ text_wiki_destroy_confirmation: Are you sure you want to delete this wiki and al
 text_issue_category_destroy_question: Some issues (%d) are assigned to this category. What do you want to do ?
 text_issue_category_destroy_assignments: Remove category assignments
 text_issue_category_reassign_to: Reassign issues to this category
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
 
 default_role_manager: Manager
 default_role_developper: Developer
index c3392b2d43e92bade8a564b36611721922c6ac07..d66220e05c60068408785938a74ccafd0d553455 100644 (file)
@@ -529,3 +529,8 @@ label_theme: Theme
 label_default: Default
 label_search_titles_only: Search titles only
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index 4b46189f54d6b0844c2ac07b90569d8aa9e233ff..ce543b6862bffac6f75120194b4ce1718d12299c 100644 (file)
@@ -437,6 +437,9 @@ label_bulk_edit_selected_issues: Modifier les demandes sélectionnées
 label_theme: Thème
 label_default: Défaut
 label_search_titles_only: Uniquement dans les titres
+label_user_mail_option_all: "Pour tous les événements de tous mes projets"
+label_user_mail_option_selected: "Pour tous les événements des projets sélectionnés..."
+label_user_mail_option_none: "Seulement pour ce que je surveille ou à quoi je participe"
 
 button_login: Connexion
 button_submit: Soumettre
@@ -470,6 +473,7 @@ button_archive: Archiver
 button_unarchive: Désarchiver
 button_reset: Réinitialiser
 button_rename: Renommer
+button_change_password: Changer de mot de passe
 
 status_active: actif
 status_registered: enregistré
@@ -500,6 +504,7 @@ text_wiki_destroy_confirmation: Etes-vous sûr de vouloir supprimer ce wiki et t
 text_issue_category_destroy_question: Des demandes (%d) sont affectées à cette catégories. Que voulez-vous faire ?
 text_issue_category_destroy_assignments: N'affecter les demandes à aucune autre catégorie
 text_issue_category_reassign_to: Réaffecter les demandes à cette catégorie
+text_user_mail_option: "Pour les projets non sélectionnés, vous recevrez seulement des notifications pour ce que vous surveillez ou à quoi vous participez (exemple: demandes dont vous êtes l'auteur ou la personne assignée)."
 
 default_role_manager: Manager
 default_role_developper: Développeur
index 106bc00963af596b94568adfc06ac6931e4bf2af..0a310924a51d920fa74ec48952ea121bc1a9672c 100644 (file)
@@ -526,3 +526,8 @@ enumeration_doc_categories: קטגוריות מסמכים
 enumeration_activities: פעילויות (מעקב אחר זמנים)
 label_search_titles_only: Search titles only
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index 8dad1566ae3adb714b47b570b437c8b44ad664ff..b4888808f97c830a49ed450c9b245edce7d9a05e 100644 (file)
@@ -526,3 +526,8 @@ label_theme: Theme
 label_default: Default
 label_search_titles_only: Search titles only
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index ce70a4c3218dd35b4e76c8b8441b3ef9ea006dc1..3016d385bcbfb0ea861ff5730ea47112e0ddc7e5 100644 (file)
@@ -527,3 +527,8 @@ label_theme: テーマ
 label_default: 既定
 label_search_titles_only: Search titles only
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index c5928c23c4d7f011a12876e0187f19aca112f2e4..9b7d73a9d1698ae963a761ee79c597f3a89fdafb 100644 (file)
@@ -527,3 +527,8 @@ label_theme: Theme
 label_default: Default
 label_search_titles_only: Search titles only
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index 23b028ba6306a0ca65111555a54f8b1d42fafa1c..1b8602abbb31461ddff7011e7fbb921403c89f24 100644 (file)
@@ -526,3 +526,8 @@ label_theme: Temat
 label_default: Domyślne
 label_search_titles_only: Przeszukuj tylko tytuły
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index bb335b0822081ce4d5bfbd98b692e8afd40451c7..da25974ad0ac3febbf2edc7937cf6bea9c9d4610 100644 (file)
@@ -526,3 +526,8 @@ label_theme: Theme
 label_default: Default\r
 label_search_titles_only: Search titles only\r
 label_nobody: nobody\r
+button_change_password: Change password\r
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."\r
+label_user_mail_option_selected: "For any event on the selected projects only..."\r
+label_user_mail_option_all: "For any event on all my projects"\r
+label_user_mail_option_none: "Only for things I watch or I'm involved in"\r
index 2fcfbd334490fd873869a4b739ac9a15c079fa7b..94dace1d9621030e4199c64ea3ec70220c0144e0 100644 (file)
@@ -526,3 +526,8 @@ label_theme: Theme
 label_default: Default
 label_search_titles_only: Search titles only
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index 08eb75b0b159441cbe6b4f3e606e5ea5265f9631..93352c8c9d144d128c53766da9c35a9366ecc271 100644 (file)
@@ -526,3 +526,8 @@ label_theme: Theme
 label_default: Default
 label_search_titles_only: Search titles only
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index 17b57b5dc28f6d5be65c0e3f7225e9ceb8abfd0f..139105ed45660b5b87a7a5b915c16c63114d7057 100644 (file)
@@ -527,3 +527,8 @@ label_theme: Theme
 label_default: Default
 label_search_titles_only: Search titles only
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index 3826be6d40ab5788073474e98f6b73a83138389b..9fda045b8dcb2de38b6d0ce327d1bac85a9d4043 100644 (file)
@@ -529,3 +529,8 @@ label_theme: Theme
 label_default: Default
 label_search_titles_only: Search titles only
 label_nobody: nobody
+button_change_password: Change password
+text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
+label_user_mail_option_selected: "For any event on the selected projects only..."
+label_user_mail_option_all: "For any event on all my projects"
+label_user_mail_option_none: "Only for things I watch or I'm involved in"
index 1ae20416a3f89222826fb22a529d95cd491fc712..b56fa6a3c6636409d2287b6d4868d45def408f75 100644 (file)
@@ -116,6 +116,7 @@ textarea.wiki-edit { width: 99%; }
 li p {margin-top: 0;}
 div.issue {background:#ffffdd; padding:6px; margin-bottom:6px;border: 1px solid #d7d7d7;}
 .autoscroll {overflow-x: auto; padding:1px; width:100%;}
+#user_firstname, #user_lastname, #user_mail, #notification_option { width: 90%; }
 
 /***** Tabular forms ******/
 .tabular p{
index b2389c39b438b2064b82d62bacd4f15970fe4bee..5df2932ed08fba50c16193bf7118f1ef0f2f2098 100644 (file)
@@ -61,29 +61,30 @@ class MyControllerTest < Test::Unit::TestCase
   end
   
   def test_change_password
-    get :account
+    get :password
     assert_response :success
-    assert_template 'account'
+    assert_template 'password'
     
     # non matching password confirmation
-    post :change_password, :password => 'jsmith', 
-                           :new_password => 'hello',
-                           :new_password_confirmation => 'hello2'
+    post :password, :password => 'jsmith', 
+                    :new_password => 'hello',
+                    :new_password_confirmation => 'hello2'
     assert_response :success
-    assert_template 'account'
+    assert_template 'password'
     assert_tag :tag => "div", :attributes => { :class => "errorExplanation" }
     
     # wrong password
-    post :change_password, :password => 'wrongpassword', 
-                           :new_password => 'hello',
-                           :new_password_confirmation => 'hello'
-    assert_redirected_to 'my/account'
+    post :password, :password => 'wrongpassword', 
+                    :new_password => 'hello',
+                    :new_password_confirmation => 'hello'
+    assert_response :success
+    assert_template 'password'
     assert_equal 'Wrong password', flash[:error]
     
     # good password
-    post :change_password, :password => 'jsmith',
-                           :new_password => 'hello',
-                           :new_password_confirmation => 'hello'
+    post :password, :password => 'jsmith',
+                    :new_password => 'hello',
+                    :new_password_confirmation => 'hello'
     assert_redirected_to 'my/account'
     assert User.try_to_login('jsmith', 'hello')
   end
index 52776c62f5c8117d22b16ad3e02a7a60b5c67f7e..397bdf68a7fa6a7ec53ff0a57cfcfefece209adb 100644 (file)
@@ -105,4 +105,28 @@ class UserTest < Test::Unit::TestCase
     # user with no role
     assert !@dlopper.role_for_project(Project.find(2)).member?
   end
+  
+  def test_mail_notification_all
+    @jsmith.mail_notification = true
+    @jsmith.notified_project_ids = []
+    @jsmith.save
+    @jsmith.reload
+    assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
+  end
+  
+  def test_mail_notification_selected
+    @jsmith.mail_notification = false
+    @jsmith.notified_project_ids = [@jsmith.projects.first.id]
+    @jsmith.save
+    @jsmith.reload
+    assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
+  end
+  
+  def test_mail_notification_none
+    @jsmith.mail_notification = false
+    @jsmith.notified_project_ids = []
+    @jsmith.save
+    @jsmith.reload
+    assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
+  end
 end