From 90d33c3e518f9e05d9e2893907ebd157062d33de Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sat, 20 Oct 2007 12:47:05 +0000 Subject: [PATCH] More flexible mail notifications settings at user level. A user has now 3 options: * 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 --- app/controllers/my_controller.rb | 46 ++++++++------ app/models/issue.rb | 9 +++ app/models/mailer.rb | 22 ++----- app/models/project.rb | 5 ++ app/models/user.rb | 17 ++++++ app/views/my/_sidebar.rhtml | 8 +++ app/views/my/account.rhtml | 60 +++++++------------ app/views/my/password.rhtml | 22 +++++++ app/views/users/_form.rhtml | 1 - db/migrate/001_setup.rb | 2 +- .../075_add_members_mail_notification.rb | 9 +++ lang/bg.yml | 5 ++ lang/cs.yml | 5 ++ lang/de.yml | 5 ++ lang/en.yml | 11 +++- lang/es.yml | 5 ++ lang/fr.yml | 5 ++ lang/he.yml | 5 ++ lang/it.yml | 5 ++ lang/ja.yml | 5 ++ lang/nl.yml | 5 ++ lang/pl.yml | 5 ++ lang/pt-br.yml | 5 ++ lang/pt.yml | 5 ++ lang/ro.yml | 5 ++ lang/sv.yml | 5 ++ lang/zh.yml | 5 ++ public/stylesheets/application.css | 1 + test/functional/my_controller_test.rb | 27 +++++---- test/unit/user_test.rb | 24 ++++++++ 30 files changed, 250 insertions(+), 89 deletions(-) create mode 100644 app/views/my/_sidebar.rhtml create mode 100644 app/views/my/password.rhtml create mode 100644 db/migrate/075_add_members_mail_notification.rb diff --git a/app/controllers/my_controller.rb b/app/controllers/my_controller.rb index bbb3a6e22..5a1b128f9 100644 --- a/app/controllers/my_controller.rb +++ b/app/controllers/my_controller.rb @@ -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 diff --git a/app/models/issue.rb b/app/models/issue.rb index 026ce1211..972bf0135 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -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 diff --git a/app/models/mailer.rb b/app/models/mailer.rb index 683045715..da7937404 100644 --- a/app/models/mailer.rb +++ b/app/models/mailer.rb @@ -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 diff --git a/app/models/project.rb b/app/models/project.rb index 3e6593f58..8f7e03a7c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -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) diff --git a/app/models/user.rb b/app/models/user.rb index e4c397a51..9c8d1d9a3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -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 index 000000000..d30eacf90 --- /dev/null +++ b/app/views/my/_sidebar.rhtml @@ -0,0 +1,8 @@ +

<%=l(:label_my_account)%>

+ +

<%=l(:field_login)%>: <%= @user.login %>
+<%=l(:field_created_on)%>: <%= format_time(@user.created_on) %>

+<% if @user.rss_token %> +

<%= 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 %>)

+<% end %> diff --git a/app/views/my/account.rhtml b/app/views/my/account.rhtml index 8250c5298..198ef8ffe 100644 --- a/app/views/my/account.rhtml +++ b/app/views/my/account.rhtml @@ -1,55 +1,41 @@ +
+<%= link_to(l(:button_change_password), :action => 'password') unless @user.auth_source_id %> +

<%=l(:label_my_account)%>

- <%= error_messages_for 'user' %> -
+<% form_for :user, @user, :url => { :action => "account" }, :builder => TabularFormBuilder, :lang => current_language do |f| %> +

<%=l(:label_information_plural)%>

- -<% labelled_tabular_form_for :user, @user, :url => { :action => "account" } do |f| %> - +

<%= f.text_field :firstname, :required => true %>

<%= f.text_field :lastname, :required => true %>

-

<%= f.text_field :mail, :required => true, :size => 40 %>

+

<%= f.text_field :mail, :required => true %>

<%= f.select :language, lang_options_for_select %>

-

<%= f.check_box :mail_notification %>

<% fields_for :pref, @user.pref, :builder => TabularFormBuilder, :lang => current_language do |pref_fields| %>

<%= pref_fields.check_box :hide_mail %>

<% end %> - -
<%= submit_tag l(:button_save) %>
-<% end %>
+<%= submit_tag l(:button_save) %> +
-<% unless @user.auth_source_id %> -
-

<%=l(:field_password)%>

- - <% form_tag({:action => 'change_password'}, :class => "tabular") do %> - -

- <%= password_field_tag 'password', nil, :size => 25 %>

- -

- <%= password_field_tag 'new_password', nil, :size => 25 %>
- <%= l(:text_length_between, 4, 12) %>

- -

- <%= password_field_tag 'new_password_confirmation', nil, :size => 25 %>

- -
<%= submit_tag l(:button_save) %>
- <% end %> -
+
+

<%=l(:field_mail_notification)%>

+
+<%= 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 %> +

<% User.current.projects.each do |project| %> +
+<% end %>

+

<%= l(:text_user_mail_option) %>

+<% end %> +
+
<% end %> <% content_for :sidebar do %> -

<%=l(:label_my_account)%>

- -

<%=l(:field_login)%>: <%= @user.login %>
- <%=l(:field_created_on)%>: <%= format_time(@user.created_on) %>

- <% if @user.rss_token %> -

<%= 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 %>)

- <% end %> +<%= render :partial => 'sidebar' %> <% end %> diff --git a/app/views/my/password.rhtml b/app/views/my/password.rhtml new file mode 100644 index 000000000..217a8758e --- /dev/null +++ b/app/views/my/password.rhtml @@ -0,0 +1,22 @@ +

<%=l(:button_change_password)%>

+ +<%= error_messages_for 'user' %> + +<% form_tag({}, :class => "tabular") do %> +
+

+<%= password_field_tag 'password', nil, :size => 25 %>

+ +

+<%= password_field_tag 'new_password', nil, :size => 25 %>
+<%= l(:text_length_between, 4, 12) %>

+ +

+<%= password_field_tag 'new_password_confirmation', nil, :size => 25 %>

+
+<%= submit_tag l(:button_apply) %> +<% end %> + +<% content_for :sidebar do %> +<%= render :partial => 'sidebar' %> +<% end %> diff --git a/app/views/users/_form.rhtml b/app/views/users/_form.rhtml index 56b157986..72cf3c95c 100644 --- a/app/views/users/_form.rhtml +++ b/app/views/users/_form.rhtml @@ -14,7 +14,6 @@ <% end if @custom_values%>

<%= f.check_box :admin %>

-

<%= f.check_box :mail_notification %>

diff --git a/db/migrate/001_setup.rb b/db/migrate/001_setup.rb index 8b299eb1e..1160dd5ef 100644 --- a/db/migrate/001_setup.rb +++ b/db/migrate/001_setup.rb @@ -284,7 +284,7 @@ class Setup < ActiveRecord::Migration Permission.create :controller => "versions", :action => "destroy_file", :description => "button_delete", :sort => 1322 # create default administrator account - 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" user.admin = true diff --git a/db/migrate/075_add_members_mail_notification.rb b/db/migrate/075_add_members_mail_notification.rb new file mode 100644 index 000000000..d83ba8dd0 --- /dev/null +++ b/db/migrate/075_add_members_mail_notification.rb @@ -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 diff --git a/lang/bg.yml b/lang/bg.yml index 15bbb5239..d4ef3511e 100644 --- a/lang/bg.yml +++ b/lang/bg.yml @@ -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" diff --git a/lang/cs.yml b/lang/cs.yml index 8e5f91b41..b7b88884d 100644 --- a/lang/cs.yml +++ b/lang/cs.yml @@ -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" diff --git a/lang/de.yml b/lang/de.yml index dae960579..793876fc3 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -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" diff --git a/lang/en.yml b/lang/en.yml index 7d23e4fbe..d0dc64666 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -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 diff --git a/lang/es.yml b/lang/es.yml index c3392b2d4..d66220e05 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -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" diff --git a/lang/fr.yml b/lang/fr.yml index 4b46189f5..ce543b686 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -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 diff --git a/lang/he.yml b/lang/he.yml index 106bc0096..0a310924a 100644 --- a/lang/he.yml +++ b/lang/he.yml @@ -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" diff --git a/lang/it.yml b/lang/it.yml index 8dad1566a..b4888808f 100644 --- a/lang/it.yml +++ b/lang/it.yml @@ -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" diff --git a/lang/ja.yml b/lang/ja.yml index ce70a4c32..3016d385b 100644 --- a/lang/ja.yml +++ b/lang/ja.yml @@ -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" diff --git a/lang/nl.yml b/lang/nl.yml index c5928c23c..9b7d73a9d 100644 --- a/lang/nl.yml +++ b/lang/nl.yml @@ -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" diff --git a/lang/pl.yml b/lang/pl.yml index 23b028ba6..1b8602abb 100644 --- a/lang/pl.yml +++ b/lang/pl.yml @@ -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" diff --git a/lang/pt-br.yml b/lang/pt-br.yml index bb335b082..da25974ad 100644 --- a/lang/pt-br.yml +++ b/lang/pt-br.yml @@ -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" diff --git a/lang/pt.yml b/lang/pt.yml index 2fcfbd334..94dace1d9 100644 --- a/lang/pt.yml +++ b/lang/pt.yml @@ -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" diff --git a/lang/ro.yml b/lang/ro.yml index 08eb75b0b..93352c8c9 100644 --- a/lang/ro.yml +++ b/lang/ro.yml @@ -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" diff --git a/lang/sv.yml b/lang/sv.yml index 17b57b5dc..139105ed4 100644 --- a/lang/sv.yml +++ b/lang/sv.yml @@ -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" diff --git a/lang/zh.yml b/lang/zh.yml index 3826be6d4..9fda045b8 100644 --- a/lang/zh.yml +++ b/lang/zh.yml @@ -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" diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 1ae20416a..b56fa6a3c 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -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{ diff --git a/test/functional/my_controller_test.rb b/test/functional/my_controller_test.rb index b2389c39b..5df2932ed 100644 --- a/test/functional/my_controller_test.rb +++ b/test/functional/my_controller_test.rb @@ -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 diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index 52776c62f..397bdf68a 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -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 -- 2.39.5