From a332e0a4febeb36aac41f8d5762d18f4cbbf115c Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 3 Aug 2008 09:14:43 +0000 Subject: [PATCH] Adds permissions for viewing the watcher list and adding new watchers on the issue detail view (#398). git-svn-id: http://redmine.rubyforge.org/svn/trunk@1712 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/watchers_controller.rb | 52 +++++++++----- app/helpers/watchers_helper.rb | 7 +- app/models/watcher.rb | 7 ++ app/views/issues/show.rhtml | 8 +++ app/views/watchers/_watchers.rhtml | 25 +++++++ lang/bg.yml | 1 + lang/cs.yml | 1 + lang/da.yml | 1 + lang/de.yml | 1 + lang/en.yml | 1 + lang/es.yml | 1 + lang/fi.yml | 1 + lang/fr.yml | 1 + lang/he.yml | 1 + lang/hu.yml | 1 + lang/it.yml | 1 + lang/ja.yml | 1 + lang/ko.yml | 1 + lang/lt.yml | 1 + lang/nl.yml | 1 + lang/no.yml | 1 + lang/pl.yml | 1 + lang/pt-br.yml | 1 + lang/pt.yml | 1 + lang/ro.yml | 1 + lang/ru.yml | 1 + lang/sr.yml | 1 + lang/sv.yml | 1 + lang/th.yml | 1 + lang/uk.yml | 1 + lang/zh-tw.yml | 1 + lang/zh.yml | 1 + lib/redmine.rb | 3 + test/fixtures/roles.yml | 4 ++ test/fixtures/watchers.yml | 6 ++ test/functional/watchers_controller_test.rb | 70 +++++++++++++++++++ .../lib/acts_as_watchable.rb | 18 ++++- .../plugins/gloc-1.1.0/lib/gloc-rails-text.rb | 4 +- 38 files changed, 210 insertions(+), 21 deletions(-) create mode 100644 app/views/watchers/_watchers.rhtml create mode 100644 test/fixtures/watchers.yml create mode 100644 test/functional/watchers_controller_test.rb diff --git a/app/controllers/watchers_controller.rb b/app/controllers/watchers_controller.rb index 014779b7ff..a44686d3fd 100644 --- a/app/controllers/watchers_controller.rb +++ b/app/controllers/watchers_controller.rb @@ -17,30 +17,38 @@ class WatchersController < ApplicationController layout 'base' - before_filter :require_login, :find_project, :check_project_privacy + before_filter :find_project + before_filter :require_login, :check_project_privacy, :only => [:watch, :unwatch] + before_filter :authorize, :only => :new - def add - user = User.current - @watched.add_watcher(user) - respond_to do |format| - format.html { redirect_to :back } - format.js { render(:update) {|page| page.replace_html 'watcher', watcher_link(@watched, user)} } - end - rescue RedirectBackError - render :text => 'Watcher added.', :layout => true + verify :method => :post, + :only => [ :watch, :unwatch ], + :render => { :nothing => true, :status => :method_not_allowed } + + def watch + set_watcher(User.current, true) + end + + def unwatch + set_watcher(User.current, false) end - def remove - user = User.current - @watched.remove_watcher(user) + def new + @watcher = Watcher.new(params[:watcher]) + @watcher.watchable = @watched + @watcher.save if request.post? respond_to do |format| format.html { redirect_to :back } - format.js { render(:update) {|page| page.replace_html 'watcher', watcher_link(@watched, user)} } + format.js do + render :update do |page| + page.replace_html 'watchers', :partial => 'watchers/watchers', :locals => {:watched => @watched} + end + end end - rescue RedirectBackError - render :text => 'Watcher removed.', :layout => true + rescue ::ActionController::RedirectBackError + render :text => 'Watcher added.', :layout => true end - + private def find_project klass = Object.const_get(params[:object_type].camelcase) @@ -50,4 +58,14 @@ private rescue render_404 end + + def set_watcher(user, watching) + @watched.set_watcher(user, watching) + respond_to do |format| + format.html { redirect_to :back } + format.js { render(:update) {|page| page.replace_html 'watcher', watcher_link(@watched, user)} } + end + rescue ::ActionController::RedirectBackError + render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true + end end diff --git a/app/helpers/watchers_helper.rb b/app/helpers/watchers_helper.rb index c83c785fc7..f4767ebed2 100644 --- a/app/helpers/watchers_helper.rb +++ b/app/helpers/watchers_helper.rb @@ -24,7 +24,7 @@ module WatchersHelper return '' unless user && user.logged? && object.respond_to?('watched_by?') watched = object.watched_by?(user) url = {:controller => 'watchers', - :action => (watched ? 'remove' : 'add'), + :action => (watched ? 'unwatch' : 'watch'), :object_type => object.class.to_s.underscore, :object_id => object.id} link_to_remote((watched ? l(:button_unwatch) : l(:button_watch)), @@ -33,4 +33,9 @@ module WatchersHelper :class => (watched ? 'icon icon-fav' : 'icon icon-fav-off')) end + + # Returns a comma separated list of users watching the given object + def watchers_list(object) + object.watcher_users.collect {|u| content_tag('span', link_to_user(u), :class => 'user') }.join(",\n") + end end diff --git a/app/models/watcher.rb b/app/models/watcher.rb index cb6ff52eaa..38110c584b 100644 --- a/app/models/watcher.rb +++ b/app/models/watcher.rb @@ -19,5 +19,12 @@ class Watcher < ActiveRecord::Base belongs_to :watchable, :polymorphic => true belongs_to :user + validates_presence_of :user validates_uniqueness_of :user_id, :scope => [:watchable_type, :watchable_id] + + protected + + def validate + errors.add :user_id, :activerecord_error_invalid unless user.nil? || user.active? + end end diff --git a/app/views/issues/show.rhtml b/app/views/issues/show.rhtml index b71a02ee72..df8fc372ae 100644 --- a/app/views/issues/show.rhtml +++ b/app/views/issues/show.rhtml @@ -78,6 +78,14 @@ end %> <% end %> +<% if User.current.allowed_to?(:add_issue_watchers, @project) || + (@issue.watchers.any? && User.current.allowed_to?(:view_issue_watchers, @project)) %> +
+
+<%= render :partial => 'watchers/watchers', :locals => {:watched => @issue} %> +
+<% end %> + <% if @issue.changesets.any? && User.current.allowed_to?(:view_changesets, @project) %> diff --git a/app/views/watchers/_watchers.rhtml b/app/views/watchers/_watchers.rhtml new file mode 100644 index 0000000000..14bb5fc6b2 --- /dev/null +++ b/app/views/watchers/_watchers.rhtml @@ -0,0 +1,25 @@ +
+<%= link_to_remote l(:button_add), + :url => {:controller => 'watchers', + :action => 'new', + :object_type => watched.class.name.underscore, + :object_id => watched} if User.current.allowed_to?(:add_issue_watchers, @project) %> +
+ +

<%= l(:label_issue_watchers) %>

+<%= watchers_list(watched) %> + +<% unless @watcher.nil? %> +<% remote_form_for(:watcher, @watcher, + :url => {:controller => 'watchers', + :action => 'new', + :object_type => watched.class.name.underscore, + :object_id => watched}, + :method => :post, + :html => {:id => 'new-watcher-form'}) do |f| %> +

<%= f.select :user_id, (watched.addable_watcher_users.collect {|m| [m.name, m.id]}), :prompt => true %> + +<%= submit_tag l(:button_add) %> +<%= toggle_link l(:button_cancel), 'new-watcher-form'%>

+<% end %> +<% end %> diff --git a/lang/bg.yml b/lang/bg.yml index e8191dc20e..6a9676119e 100644 --- a/lang/bg.yml +++ b/lang/bg.yml @@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/cs.yml b/lang/cs.yml index 68273191ab..cc5847ee4e 100644 --- a/lang/cs.yml +++ b/lang/cs.yml @@ -638,3 +638,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/da.yml b/lang/da.yml index 1b5aba69ce..1cb55cc486 100644 --- a/lang/da.yml +++ b/lang/da.yml @@ -635,3 +635,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/de.yml b/lang/de.yml index dc2960c9cc..f0be844906 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/en.yml b/lang/en.yml index 3cc788b8c3..2307b15915 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -521,6 +521,7 @@ label_reverse_chronological_order: In reverse chronological order label_planning: Planning label_incoming_emails: Incoming emails label_generate_key: Generate a key +label_issue_watchers: Watchers button_login: Login button_submit: Submit diff --git a/lang/es.yml b/lang/es.yml index c753f367f0..7f27d53e57 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -636,3 +636,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/fi.yml b/lang/fi.yml index b48d8a3193..031d59d63c 100644 --- a/lang/fi.yml +++ b/lang/fi.yml @@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/fr.yml b/lang/fr.yml index b9d542da61..0372520675 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -521,6 +521,7 @@ label_reverse_chronological_order: Dans l'ordre chronologique inverse label_planning: Planning label_incoming_emails: Emails entrants label_generate_key: Générer une clé +label_issue_watchers: Utilisateurs surveillant cette demande button_login: Connexion button_submit: Soumettre diff --git a/lang/he.yml b/lang/he.yml index 63aa2bb643..9c8fbae7e8 100644 --- a/lang/he.yml +++ b/lang/he.yml @@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/hu.yml b/lang/hu.yml index 9becbb3499..a5d208cb66 100644 --- a/lang/hu.yml +++ b/lang/hu.yml @@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Web Service engedélyezése a beérkezett leve setting_mail_handler_api_key: API kulcs text_email_delivery_not_configured: "Az E-mail küldés nincs konfigurálva, és az értesítések ki vannak kapcsolva.\nÁllítsd be az SMTP szervert a config/email.yml fájlban és indítsd újra az alkalmazást, hogy érvénybe lépjen." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/it.yml b/lang/it.yml index e7a8772cc0..5d62e32555 100644 --- a/lang/it.yml +++ b/lang/it.yml @@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Abilita WS per le e-mail in arrivo setting_mail_handler_api_key: chiave API text_email_delivery_not_configured: "La consegna via e-mail non è configurata e le notifiche sono disabilitate.\nConfigura il tuo server SMTP in config/email.yml e riavvia l'applicazione per abilitarle." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/ja.yml b/lang/ja.yml index f78fcdba47..f3ade750dd 100644 --- a/lang/ja.yml +++ b/lang/ja.yml @@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/ko.yml b/lang/ko.yml index 77672c6017..961255e016 100644 --- a/lang/ko.yml +++ b/lang/ko.yml @@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/lt.yml b/lang/lt.yml index 706133bfe0..58f7985060 100644 --- a/lang/lt.yml +++ b/lang/lt.yml @@ -636,3 +636,4 @@ setting_mail_handler_api_key: API raktas text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/nl.yml b/lang/nl.yml index 3cfb0aa193..08e300143d 100644 --- a/lang/nl.yml +++ b/lang/nl.yml @@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/no.yml b/lang/no.yml index 0836bd48fa..7af029db9f 100644 --- a/lang/no.yml +++ b/lang/no.yml @@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/pl.yml b/lang/pl.yml index 278d56a88d..0a29b7c473 100644 --- a/lang/pl.yml +++ b/lang/pl.yml @@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/pt-br.yml b/lang/pt-br.yml index 9276d768e0..3ab24aeb04 100644 --- a/lang/pt-br.yml +++ b/lang/pt-br.yml @@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/pt.yml b/lang/pt.yml index a7647e31f1..bd32cd1404 100644 --- a/lang/pt.yml +++ b/lang/pt.yml @@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/ro.yml b/lang/ro.yml index c3640d7e10..2e562e2378 100644 --- a/lang/ro.yml +++ b/lang/ro.yml @@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/ru.yml b/lang/ru.yml index e8bda05b72..61e7136947 100644 --- a/lang/ru.yml +++ b/lang/ru.yml @@ -637,3 +637,4 @@ setting_mail_handler_api_enabled: Включить веб-сервис для в setting_mail_handler_api_key: API ключ text_email_delivery_not_configured: "Параметры работы с почтовым сервером не настроены и функция уведомления по email не активна.\nНастроить параметры для вашего SMTP сервера вы можете в файле config/email.yml. Для применения изменений перезапустите приложение." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/sr.yml b/lang/sr.yml index 688fa8ede2..ba79d4ef2b 100644 --- a/lang/sr.yml +++ b/lang/sr.yml @@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/sv.yml b/lang/sv.yml index 58507a0b70..9505759c82 100644 --- a/lang/sv.yml +++ b/lang/sv.yml @@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/th.yml b/lang/th.yml index a7f949c96e..6c4ce30d63 100644 --- a/lang/th.yml +++ b/lang/th.yml @@ -636,3 +636,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/uk.yml b/lang/uk.yml index 766ddaaab4..4fa27f7d30 100644 --- a/lang/uk.yml +++ b/lang/uk.yml @@ -635,3 +635,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_key: API key text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/zh-tw.yml b/lang/zh-tw.yml index 82f26ab868..1e6483631a 100644 --- a/lang/zh-tw.yml +++ b/lang/zh-tw.yml @@ -634,3 +634,4 @@ enumeration_issue_priorities: 項目優先權 enumeration_doc_categories: 文件分類 enumeration_activities: 活動 (時間追蹤) field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lang/zh.yml b/lang/zh.yml index b4ae89ba7e..7158a7f83b 100644 --- a/lang/zh.yml +++ b/lang/zh.yml @@ -634,3 +634,4 @@ enumeration_doc_categories: 文档类别 enumeration_activities: 活动(时间跟踪) text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." field_parent_title: Parent page +label_issue_watchers: Watchers diff --git a/lib/redmine.rb b/lib/redmine.rb index bd413c96c6..9890ab06f4 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -46,6 +46,9 @@ Redmine::AccessControl.map do |map| # Gantt & calendar map.permission :view_gantt, :projects => :gantt map.permission :view_calendar, :projects => :calendar + # Watchers + map.permission :view_issue_watchers, {} + map.permission :add_issue_watchers, {:watchers => :new} end map.project_module :time_tracking do |map| diff --git a/test/fixtures/roles.yml b/test/fixtures/roles.yml index e7b1422684..234e971c4e 100644 --- a/test/fixtures/roles.yml +++ b/test/fixtures/roles.yml @@ -15,6 +15,8 @@ roles_001: - :add_issue_notes - :move_issues - :delete_issues + - :view_issue_watchers + - :add_issue_watchers - :manage_public_queries - :save_queries - :view_gantt @@ -58,6 +60,7 @@ roles_002: - :add_issue_notes - :move_issues - :delete_issues + - :view_issue_watchers - :save_queries - :view_gantt - :view_calendar @@ -95,6 +98,7 @@ roles_003: - :manage_issue_relations - :add_issue_notes - :move_issues + - :view_issue_watchers - :save_queries - :view_gantt - :view_calendar diff --git a/test/fixtures/watchers.yml b/test/fixtures/watchers.yml new file mode 100644 index 0000000000..a8c4829557 --- /dev/null +++ b/test/fixtures/watchers.yml @@ -0,0 +1,6 @@ +--- +watchers_001: + watchable_type: Issue + watchable_id: 2 + user_id: 3 + \ No newline at end of file diff --git a/test/functional/watchers_controller_test.rb b/test/functional/watchers_controller_test.rb new file mode 100644 index 0000000000..cd6539410d --- /dev/null +++ b/test/functional/watchers_controller_test.rb @@ -0,0 +1,70 @@ +# Redmine - project management software +# Copyright (C) 2006-2008 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.dirname(__FILE__) + '/../test_helper' +require 'watchers_controller' + +# Re-raise errors caught by the controller. +class WatchersController; def rescue_action(e) raise e end; end + +class WatchersControllerTest < Test::Unit::TestCase + fixtures :projects, :users, :roles, :members, :enabled_modules, + :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers + + def setup + @controller = WatchersController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + User.current = nil + end + + def test_get_watch_should_be_invalid + @request.session[:user_id] = 3 + get :watch, :object_type => 'issue', :object_id => '1' + assert_response 405 + end + + def test_watch + @request.session[:user_id] = 3 + assert_difference('Watcher.count') do + xhr :post, :watch, :object_type => 'issue', :object_id => '1' + assert_response :success + assert_select_rjs :replace_html, 'watcher' + end + assert Issue.find(1).watched_by?(User.find(3)) + end + + def test_unwatch + @request.session[:user_id] = 3 + assert_difference('Watcher.count', -1) do + xhr :post, :unwatch, :object_type => 'issue', :object_id => '2' + assert_response :success + assert_select_rjs :replace_html, 'watcher' + end + assert !Issue.find(1).watched_by?(User.find(3)) + end + + def test_new_watcher + @request.session[:user_id] = 2 + assert_difference('Watcher.count') do + xhr :post, :new, :object_type => 'issue', :object_id => '2', :watcher => {:user_id => '4'} + assert_response :success + assert_select_rjs :replace_html, 'watchers' + end + assert Issue.find(2).watched_by?(User.find(4)) + end +end diff --git a/vendor/plugins/acts_as_watchable/lib/acts_as_watchable.rb b/vendor/plugins/acts_as_watchable/lib/acts_as_watchable.rb index 53e4455cff..2cb1227959 100644 --- a/vendor/plugins/acts_as_watchable/lib/acts_as_watchable.rb +++ b/vendor/plugins/acts_as_watchable/lib/acts_as_watchable.rb @@ -13,6 +13,7 @@ module Redmine class_eval do has_many :watchers, :as => :watchable, :dependent => :delete_all + has_many :watcher_users, :through => :watchers, :source => :user end end end @@ -22,25 +23,40 @@ module Redmine base.extend ClassMethods end + # Returns an array of users that are proposed as watchers + def addable_watcher_users + self.project.users.sort - self.watcher_users + end + + # Adds user as a watcher def add_watcher(user) self.watchers << Watcher.new(:user => user) end + # Removes user from the watchers list def remove_watcher(user) return nil unless user && user.is_a?(User) Watcher.delete_all "watchable_type = '#{self.class}' AND watchable_id = #{self.id} AND user_id = #{user.id}" end + # Adds/removes watcher + def set_watcher(user, watching=true) + watching ? add_watcher(user) : remove_watcher(user) + end + + # Returns if object is watched by user def watched_by?(user) !self.watchers.find(:first, :conditions => ["#{Watcher.table_name}.user_id = ?", user.id]).nil? end + # Returns an array of watchers' email addresses def watcher_recipients self.watchers.collect { |w| w.user.mail if w.user.active? }.compact end module ClassMethods + # Returns the objects that are watched by user def watched_by(user) find(:all, :include => :watchers, @@ -50,4 +66,4 @@ module Redmine end end end -end \ No newline at end of file +end diff --git a/vendor/plugins/gloc-1.1.0/lib/gloc-rails-text.rb b/vendor/plugins/gloc-1.1.0/lib/gloc-rails-text.rb index f437410dc6..51c0248389 100644 --- a/vendor/plugins/gloc-1.1.0/lib/gloc-rails-text.rb +++ b/vendor/plugins/gloc-1.1.0/lib/gloc-rails-text.rb @@ -138,8 +138,8 @@ module ActionView #:nodoc: def add_options(option_tags, options, value = nil) option_tags = "\n" + option_tags if options[:include_blank] - if value.blank? && options[:prompt] - ("\n") + option_tags + if options[:prompt] + ("\n") + option_tags else option_tags end